Project

General

Profile

Actions

Bug #20392

closed

Delegate super calls with a block

Added by tenderlovemaking (Aaron Patterson) 8 months ago. Updated 8 months ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 3.4.0dev (2024-03-15T18:08:39Z master e3a82d79fd) [arm64-darwin23]
[ruby-core:117313]

Description

I'm seeing strange behavior with calls to super when combined with ... and a block. I'm not sure if this is expected behavior or not, so I'm filing this ticket.

Using delegate ... with an explicit block will cause an error:

# Example 1
def foo ...
  yield
end

def bar ...
  foo(...) { } # test.rb: test.rb:6: both block arg and actual block given (SyntaxError)
end

However, calling super and passing a block works:

# Example 2
class A
  def foo
    yield(3)
  end
end

class B < A
  def foo(...)
    super do |x|
      yield(2 + x)
    end
  end
end

p B.new.foo { |x| x } # 5

In the above code, I imagine the bare super to basically be equivalent of super(...) since I defined the method foo as foo(...).

However, if I explicitly pass ... to super, there is no syntax error, just the block I provided is ignored:

# Example 3
class A
  def foo
    yield(3)
  end
end

class B < A
  def foo(...)
    super(...) do |x|
      raise "should I be called?"
    end
  end
end

p B.new.foo { |x| x } # 3

I'd expect Example 3 to raise an exception like Example 1. Additionally, I think the behavior in Example 2 is odd, but zsupers are "special" so I can understand if it is intended behavior.

Is Example 3 intended behavior? If not, how should it behave?

Thanks.

Updated by Dan0042 (Daniel DeLorme) 8 months ago

In Ruby 3.2, example 3 raised an exception "both block arg and actual block given"
So this looks like a Ruby 3.3 regression.

Updated by jeremyevans0 (Jeremy Evans) 8 months ago

super(...){}should be a syntax error, just as foo(...){} is.

super behavior in general is special. For example, super(arg) is not a zsuper, but still passes the block implicitly, you have to do super(arg, &nil) to avoid passing a block. super{} passes the args implicitly, but uses the block given. While I find that confusing, I don't think changing that behavior is worth it, as the backwards compatibility breakage is not worth the benefit IMO.

Updated by tenderlovemaking (Aaron Patterson) 8 months ago

Dan0042 (Daniel DeLorme) wrote in #note-1:

In Ruby 3.2, example 3 raised an exception "both block arg and actual block given"
So this looks like a Ruby 3.3 regression.

Thanks, I should have checked older versions. According to git bisect, this was introduced in fdc329ea6f5bce922e95645a0c2118cfd3e1cdea (though I'm not sure how that commit caused this)

jeremyevans0 (Jeremy Evans) wrote in #note-2:

super(...){}should be a syntax error, just as foo(...){} is.

super behavior in general is special. For example, super(arg) is not a zsuper, but still passes the block implicitly, you have to do super(arg, &nil) to avoid passing a block. super{} passes the args implicitly, but uses the block given. While I find that confusing, I don't think changing that behavior is worth it, as the backwards compatibility breakage is not worth the benefit IMO.

It's very odd behavior, but I definitely agree.

Updated by jeremyevans0 (Jeremy Evans) 8 months ago

tenderlovemaking (Aaron Patterson) wrote in #note-3:

Dan0042 (Daniel DeLorme) wrote in #note-1:

In Ruby 3.2, example 3 raised an exception "both block arg and actual block given"
So this looks like a Ruby 3.3 regression.

Thanks, I should have checked older versions. According to git bisect, this was introduced in fdc329ea6f5bce922e95645a0c2118cfd3e1cdea (though I'm not sure how that commit caused this)

It's missing entries for NODE_SUPER and NODE_ZSUPER in get_nd_args, so the nd_args are ignored for those nodes. At least those node types should be fixed, and all other node types in the switch should be checked to see if this isn't swallowing other syntax errors. @yui-knk (Kaneko Yuichiro) is my analysis correct?

Updated by nobu (Nobuyoshi Nakada) 8 months ago

jeremyevans0 (Jeremy Evans) wrote in #note-4:

It's missing entries for NODE_SUPER and NODE_ZSUPER in get_nd_args, so the nd_args are ignored for those nodes. At least those node types should be fixed, and all other node types in the switch should be checked to see if this isn't swallowing other syntax errors. @yui-knk (Kaneko Yuichiro) is my analysis correct?

I think that zsuper is special.

Actions #7

Updated by nobu (Nobuyoshi Nakada) 8 months ago

  • Status changed from Open to Closed

Applied in changeset git|a850cd1a87bef738c40d9c550fb8823699083f2e.


[Bug #20392] Block arguments duplication check at super

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0