Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler: don't visit enum member expanded by macro twice #10105

Merged
merged 1 commit into from Dec 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions spec/compiler/semantic/enum_spec.cr
Expand Up @@ -492,4 +492,19 @@ describe "Semantic: enum" do
end
))
end

it "doesn't visit enum members generated by macros twice (#10104)" do
result = semantic(%(
enum Foo
A = 1

{% begin %}
def foo
end
{% end %}
end
))
a_def = result.program.types["Foo"].lookup_defs("foo").first
a_def.previous.should be_nil
end
end
16 changes: 8 additions & 8 deletions src/compiler/crystal/semantic/semantic_visitor.cr
Expand Up @@ -269,11 +269,11 @@ abstract class Crystal::SemanticVisitor < Crystal::Visitor
node.raise "can't #{op} dynamically" if inside_exp?
end

def expand_macro(node, raise_on_missing_const = true, first_pass = false)
def expand_macro(node, raise_on_missing_const = true, first_pass = false, accept = true)
if expanded = node.expanded
@exp_nest -= 1
eval_macro(node) do
expanded.accept self
expanded.accept self if accept
end
@exp_nest += 1
return true
Expand Down Expand Up @@ -311,7 +311,7 @@ abstract class Crystal::SemanticVisitor < Crystal::Visitor
args = expand_macro_arguments(node, expansion_scope)

@exp_nest -= 1
generated_nodes = expand_macro(the_macro, node, visibility: node.visibility) do
generated_nodes = expand_macro(the_macro, node, visibility: node.visibility, accept: accept) do
old_args = node.args
node.args = args
expanded_macro, macro_expansion_pragmas = @program.expand_macro the_macro, node, expansion_scope, expansion_scope, @untyped_def
Expand All @@ -327,7 +327,7 @@ abstract class Crystal::SemanticVisitor < Crystal::Visitor
true
end

def expand_macro(the_macro, node, mode = nil, *, visibility : Visibility)
def expand_macro(the_macro, node, mode = nil, *, visibility : Visibility, accept = true)
expanded_macro, macro_expansion_pragmas =
eval_macro(node) do
yield
Expand Down Expand Up @@ -357,7 +357,7 @@ abstract class Crystal::SemanticVisitor < Crystal::Visitor
generated_nodes.accept PropagateDocVisitor.new(node_doc)
end

generated_nodes.accept self
generated_nodes.accept self if accept
generated_nodes
end

Expand Down Expand Up @@ -406,10 +406,10 @@ abstract class Crystal::SemanticVisitor < Crystal::Visitor
args
end

def expand_inline_macro(node, mode = nil)
def expand_inline_macro(node, mode = nil, accept = true)
if expanded = node.expanded
eval_macro(node) do
expanded.accept self
expanded.accept self if accept
end
return expanded
end
Expand All @@ -418,7 +418,7 @@ abstract class Crystal::SemanticVisitor < Crystal::Visitor

skip_macro_exception = nil

generated_nodes = expand_macro(the_macro, node, mode: mode, visibility: :public) do
generated_nodes = expand_macro(the_macro, node, mode: mode, visibility: :public, accept: accept) do
begin
@program.expand_macro node, (@scope || current_type), @path_lookup, free_vars, @untyped_def
rescue ex : SkipMacroException
Expand Down
7 changes: 4 additions & 3 deletions src/compiler/crystal/semantic/top_level_visitor.cr
Expand Up @@ -381,6 +381,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor
end

target_type.add_def node

node.set_type @program.nil

if is_instance_method
Expand Down Expand Up @@ -633,13 +634,13 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor
def visit_enum_member(node, member, counter, all_value, overflow, **options)
case member
when MacroIf
expanded = expand_inline_macro(member, mode: Parser::ParseMode::Enum)
expanded = expand_inline_macro(member, mode: Parser::ParseMode::Enum, accept: false)
visit_enum_member(node, expanded, counter, all_value, overflow, **options)
when MacroExpression
expanded = expand_inline_macro(member, mode: Parser::ParseMode::Enum)
expanded = expand_inline_macro(member, mode: Parser::ParseMode::Enum, accept: false)
visit_enum_member(node, expanded, counter, all_value, overflow, **options)
when MacroFor
expanded = expand_inline_macro(member, mode: Parser::ParseMode::Enum)
expanded = expand_inline_macro(member, mode: Parser::ParseMode::Enum, accept: false)
visit_enum_member(node, expanded, counter, all_value, overflow, **options)
when Expressions
visit_enum_members(node, member.expressions, counter, all_value, overflow, **options)
Expand Down