Project

General

Profile

Actions

Bug #20478

closed

Circular parameter syntax error rules

Added by kddnewton (Kevin Newton) 2 months ago. Updated about 1 month ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:117812]

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.


Related issues 1 (0 open1 closed)

Related to Ruby master - Bug #16343: Inconsistent behavior of 'circular argument reference' errorClosedActions

Updated by nobu (Nobuyoshi Nakada) 2 months ago

Given that these Procs are only created if the argument bar is not assigned, should they all be syntax errors?

Updated by kddnewton (Kevin Newton) 2 months ago

Yes, I very much think they should all be syntax errors.

Updated by nobu (Nobuyoshi Nakada) 2 months 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) 2 months ago

I figured that was already happening for the "unused" warning.

Actions #5

Updated by byroot (Jean Boussier) 2 months ago

  • Related to Bug #16343: Inconsistent behavior of 'circular argument reference' error added

Updated by kddnewton (Kevin Newton) about 2 months 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.

Updated by kddnewton (Kevin Newton) about 2 months ago

If we go with only syntax errors at depth 0, then this:

def foo(bar = baz { bar }) end

should not be a syntax error either. I think that makes sense, because the baz method could use instance_exec/instance_eval so we don't know if bar is going to be the same variable here or not.

Updated by kddnewton (Kevin Newton) about 2 months ago

Also:

def foo(bar = ->    { bar }) end
def foo(bar = ->( ) { bar }) end
def foo(bar = ->(_) { bar }) end

Two of these are a syntax error, but I think either all of them should be or none of them should be.

Updated by mame (Yusuke Endoh) about 1 month ago

Discussed at the dev meeting. @matz (Yukihiro Matsumoto) said all cases should be accepted with no syntax error. So def foo(bar = bar) = bar; foo will return nil with no warning and error.

Updated by kddnewton (Kevin Newton) about 1 month ago

  • Status changed from Open to Closed

Merged.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0