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

+ ruby{33,34}.y: allow blocks inherit anonymous args. #1010

Merged
merged 1 commit into from
Apr 26, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/parser/ruby33.y
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions lib/parser/ruby34.y
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
59 changes: 47 additions & 12 deletions lib/parser/static_environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -47,6 +62,8 @@ def declared?(name)
@variables.include?(name.to_sym)
end

# Forward args

def declare_forward_args
declare(FORWARD_ARGS)
end
Expand All @@ -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?
Expand Down
30 changes: 30 additions & 0 deletions test/test_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading