Bug #20478
openCircular parameter syntax error rules
Description
I would like to revisit https://bugs.ruby-lang.org/issues/16343.
These cases are syntax errors:
def foo(bar = -> { bar }) end # no lambda parameters
def foo(bar = ->() { bar }) end # no lambda parameters
def foo(bar = baz { bar }) end # no block parameters
def foo(bar = baz { _1 + bar }) end # parameters, but no pipes
def foo(bar = baz { it + bar }) end # parameters, but no pipes
These cases are not syntax errors:
def foo(bar = ->(baz) { bar }) end # lambda parameters
def foo(bar = baz { || bar }) end # no block parameters but empty pipes
def foo(bar = baz { |qux| bar }) end # block parameters
I don't think these rules are very intuitive, and they feel somewhat arbitrary. I would like to suggest we change them to be either:
- Syntax error is raised if the parameter is ever read in its default value at any scope depth
- Syntax error is raised if the parameter is ever read in its default value at depth 0
Either one is fine by me, but gating the syntax error based on the presence of pipes is really confusing.
Updated by nobu (Nobuyoshi Nakada) 11 days ago
Given that these Proc
s are only created if the argument bar
is not assigned, should they all be syntax errors?
Updated by kddnewton (Kevin Newton) 10 days ago
Yes, I very much think they should all be syntax errors.
Updated by nobu (Nobuyoshi Nakada) 9 days ago
Even this should be a syntax error?
def foo(bar = ->(baz = bar) {}) end
That means it needs to manage the list of yet-unusable variables, not only tracking single variable.
Updated by kddnewton (Kevin Newton) 7 days ago
I figured that was already happening for the "unused" warning.
Updated by byroot (Jean Boussier) 7 days ago
- Related to Bug #16343: Inconsistent behavior of 'circular argument reference' error added
Updated by kddnewton (Kevin Newton) about 6 hours ago
@nobu (Nobuyoshi Nakada) another option would be to delete those tests and leave it up to the parser instead of forcing parse.y to implement it. Specifically I'm talking about:
o = Object.new
assert_warn("") do
o.instance_eval("def foo(var: bar {| | var}) var end")
end
o = Object.new
assert_warn("") do
o.instance_eval("def foo(var: bar {|| var}) var end")
end
and
o = Object.new
assert_warn("") do
o.instance_eval("def foo(var = bar {| | var}) var end")
end
o = Object.new
assert_warn("") do
o.instance_eval("def foo(var = bar {|| var}) var end")
end
If it's too complicated to implement in parse.y, then removing these tests would be a good compromise. These tests themselves are the issue blocking me.