Skip to content

Commit

Permalink
Compiler: don't visit enum member expanded by macro twice (#10105)
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite authored Dec 20, 2020
1 parent 1db7d5f commit cf9c261
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 11 deletions.
15 changes: 15 additions & 0 deletions spec/compiler/semantic/enum_spec.cr
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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

0 comments on commit cf9c261

Please sign in to comment.