From 8af86b0e52bdc2f0c1276725b16fdf02b698a25c Mon Sep 17 00:00:00 2001 From: Ilya Bylich Date: Fri, 26 Apr 2024 20:45:11 +0200 Subject: [PATCH] + ruby{33,34}.y: allow blocks inherit anonymous args. (#1010) This commit tracks upstream commit ruby/ruby@596db9c. --- lib/parser/ruby33.y | 6 ++-- lib/parser/ruby34.y | 6 ++-- lib/parser/static_environment.rb | 59 +++++++++++++++++++++++++------- test/test_parser.rb | 30 ++++++++++++++++ 4 files changed, 83 insertions(+), 18 deletions(-) diff --git a/lib/parser/ruby33.y b/lib/parser/ruby33.y index e1e066db2..a6e0c8bf5 100644 --- a/lib/parser/ruby33.y +++ b/lib/parser/ruby33.y @@ -1101,7 +1101,7 @@ rule end if @context.in_dynamic_block? && context.in_def && - @static_env.declared_anonymous_blockarg? && @static_env.parent_has_anonymous_blockarg? + @static_env.declared_anonymous_blockarg_in_current_scpe? && @static_env.parent_has_anonymous_blockarg? diagnostic :error, :ambiguous_anonymous_blockarg, nil, val[0] end @@ -1142,7 +1142,7 @@ rule end if @context.in_dynamic_block? && context.in_def && - @static_env.declared_anonymous_restarg? && @static_env.parent_has_anonymous_restarg? + @static_env.declared_anonymous_restarg_in_current_scope? && @static_env.parent_has_anonymous_restarg? diagnostic :error, :ambiguous_anonymous_restarg, nil, val[0] end @@ -3059,7 +3059,7 @@ f_opt_paren_args: f_paren_args end if @context.in_dynamic_block? && context.in_def && - @static_env.declared_anonymous_kwrestarg? && @static_env.parent_has_anonymous_kwrestarg? + @static_env.declared_anonymous_kwrestarg_in_current_scope? && @static_env.parent_has_anonymous_kwrestarg? diagnostic :error, :ambiguous_anonymous_kwrestarg, nil, val[0] end diff --git a/lib/parser/ruby34.y b/lib/parser/ruby34.y index 8f3769dba..8e5760195 100644 --- a/lib/parser/ruby34.y +++ b/lib/parser/ruby34.y @@ -1101,7 +1101,7 @@ rule end if @context.in_dynamic_block? && context.in_def && - @static_env.declared_anonymous_blockarg? && @static_env.parent_has_anonymous_blockarg? + @static_env.declared_anonymous_blockarg_in_current_scpe? && @static_env.parent_has_anonymous_blockarg? diagnostic :error, :ambiguous_anonymous_blockarg, nil, val[0] end @@ -1142,7 +1142,7 @@ rule end if @context.in_dynamic_block? && context.in_def && - @static_env.declared_anonymous_restarg? && @static_env.parent_has_anonymous_restarg? + @static_env.declared_anonymous_restarg_in_current_scope? && @static_env.parent_has_anonymous_restarg? diagnostic :error, :ambiguous_anonymous_restarg, nil, val[0] end @@ -3059,7 +3059,7 @@ f_opt_paren_args: f_paren_args end if @context.in_dynamic_block? && context.in_def && - @static_env.declared_anonymous_kwrestarg? && @static_env.parent_has_anonymous_kwrestarg? + @static_env.declared_anonymous_kwrestarg_in_current_scope? && @static_env.parent_has_anonymous_kwrestarg? diagnostic :error, :ambiguous_anonymous_kwrestarg, nil, val[0] end diff --git a/lib/parser/static_environment.rb b/lib/parser/static_environment.rb index 44e2f1a7c..a3e5537cc 100644 --- a/lib/parser/static_environment.rb +++ b/lib/parser/static_environment.rb @@ -4,9 +4,15 @@ module Parser class StaticEnvironment FORWARD_ARGS = :FORWARD_ARGS - ANONYMOUS_BLOCKARG = :ANONYMOUS_BLOCKARG - ANONYMOUS_RESTARG = :ANONYMOUS_RESTARG - ANONYMOUS_KWRESTARG = :ANONYMOUS_KWRESTARG + + ANONYMOUS_RESTARG_IN_CURRENT_SCOPE = :ANONYMOUS_RESTARG_IN_CURRENT_SCOPE + ANONYMOUS_RESTARG_INHERITED = :ANONYMOUS_RESTARG_INHERITED + + ANONYMOUS_KWRESTARG_IN_CURRENT_SCOPE = :ANONYMOUS_KWRESTARG_IN_CURRENT_SCOPE + ANONYMOUS_KWRESTARG_INHERITED = :ANONYMOUS_KWRESTARG_INHERITED + + ANONYMOUS_BLOCKARG_IN_CURRENT_SCOPE = :ANONYMOUS_BLOCKARG_IN_CURRENT_SCOPE + ANONYMOUS_BLOCKARG_INHERITED = :ANONYMOUS_BLOCKARG_INHERITED def initialize reset @@ -27,6 +33,15 @@ def extend_static def extend_dynamic @stack.push(@variables) @variables = @variables.dup + if @variables.delete(ANONYMOUS_BLOCKARG_IN_CURRENT_SCOPE) + @variables.add(ANONYMOUS_BLOCKARG_INHERITED) + end + if @variables.delete(ANONYMOUS_RESTARG_IN_CURRENT_SCOPE) + @variables.add(ANONYMOUS_RESTARG_INHERITED) + end + if @variables.delete(ANONYMOUS_KWRESTARG_IN_CURRENT_SCOPE) + @variables.add(ANONYMOUS_KWRESTARG_INHERITED) + end self end @@ -47,6 +62,8 @@ def declared?(name) @variables.include?(name.to_sym) end + # Forward args + def declare_forward_args declare(FORWARD_ARGS) end @@ -55,40 +72,58 @@ def declared_forward_args? declared?(FORWARD_ARGS) end + # Anonymous blockarg + def declare_anonymous_blockarg - declare(ANONYMOUS_BLOCKARG) + declare(ANONYMOUS_BLOCKARG_IN_CURRENT_SCOPE) end def declared_anonymous_blockarg? - declared?(ANONYMOUS_BLOCKARG) + declared?(ANONYMOUS_BLOCKARG_IN_CURRENT_SCOPE) || declared?(ANONYMOUS_BLOCKARG_INHERITED) + end + + def declared_anonymous_blockarg_in_current_scpe? + declared?(ANONYMOUS_BLOCKARG_IN_CURRENT_SCOPE) end def parent_has_anonymous_blockarg? - @stack.any? { |variables| variables.include?(ANONYMOUS_BLOCKARG) } + @stack.any? { |variables| variables.include?(ANONYMOUS_BLOCKARG_IN_CURRENT_SCOPE) } end + # Anonymous restarg + def declare_anonymous_restarg - declare(ANONYMOUS_RESTARG) + declare(ANONYMOUS_RESTARG_IN_CURRENT_SCOPE) end def declared_anonymous_restarg? - declared?(ANONYMOUS_RESTARG) + declared?(ANONYMOUS_RESTARG_IN_CURRENT_SCOPE) || declared?(ANONYMOUS_RESTARG_INHERITED) + end + + def declared_anonymous_restarg_in_current_scope? + declared?(ANONYMOUS_RESTARG_IN_CURRENT_SCOPE) end def parent_has_anonymous_restarg? - @stack.any? { |variables| variables.include?(ANONYMOUS_RESTARG) } + @stack.any? { |variables| variables.include?(ANONYMOUS_RESTARG_IN_CURRENT_SCOPE) } end + # Anonymous kwresarg + def declare_anonymous_kwrestarg - declare(ANONYMOUS_KWRESTARG) + declare(ANONYMOUS_KWRESTARG_IN_CURRENT_SCOPE) end def declared_anonymous_kwrestarg? - declared?(ANONYMOUS_KWRESTARG) + declared?(ANONYMOUS_KWRESTARG_IN_CURRENT_SCOPE) || declared?(ANONYMOUS_KWRESTARG_INHERITED) + end + + def declared_anonymous_kwrestarg_in_current_scope? + declared?(ANONYMOUS_KWRESTARG_IN_CURRENT_SCOPE) end def parent_has_anonymous_kwrestarg? - @stack.any? { |variables| variables.include?(ANONYMOUS_KWRESTARG) } + @stack.any? { |variables| variables.include?(ANONYMOUS_KWRESTARG_IN_CURRENT_SCOPE) } end def empty? diff --git a/test/test_parser.rb b/test/test_parser.rb index c93f4676d..b0ca33c1b 100644 --- a/test/test_parser.rb +++ b/test/test_parser.rb @@ -11497,4 +11497,34 @@ def test_parser_bug_989 %q{}, ALL_VERSIONS) end + + def test_parser_bug_19370 + refute_diagnoses( + 'def b(&) ->() {c(&)} end', + SINCE_3_3) + + refute_diagnoses( + 'def b(*) ->() {c(*)} end', + SINCE_3_3) + + refute_diagnoses( + 'def b(a, *) ->() {c(1, *)} end', + SINCE_3_3) + + refute_diagnoses( + 'def b(*) ->(a) {c(*)} end', + SINCE_3_3) + + refute_diagnoses( + 'def b(**) ->() {c(**)} end', + SINCE_3_3) + + refute_diagnoses( + 'def b(k:, **) ->() {c(k: 1, **)} end', + SINCE_3_3) + + refute_diagnoses( + 'def b(**) ->(k:) {c(**)} end', + SINCE_3_3) + end end