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

Unclear error when yielding wrong number of arguments in overloaded method #15391

Open
spuun opened this issue Jan 31, 2025 · 2 comments
Open
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. status:discussion topic:compiler:semantic

Comments

@spuun
Copy link
Contributor

spuun commented Jan 31, 2025

Bug Report

abstract class Foo
  abstract def bar(&)
end

class Baz < Foo
  def bar(&)
    yield 1
  end
end

results in

Error: abstract def Foo#bar(&) must be implemented by Baz

The error should probably say something about wrong number of arguments.

@spuun spuun added the kind:bug A bug in the code. Does not apply to documentation, specs, etc. label Jan 31, 2025
@straight-shoota
Copy link
Member

I believe the root of the problem is that originally the & parameter only indicates that the method receives a block, but not its type.
However, when used in an abstract def, the compiler infers from the absence of any type information that the type must be Proc(_) (I believe?).
This then creates a conflict with the implementation method where yield 1 in the body informs that the block actually receives one argument.

Of course we can (and probably should) improve the error message to make it easier to understand what's wrong. Because the signatures look identical you would think that it's implemented correctly.

Going one step further however, I'm wondering if abstract def should require an explicit type restriction for the block argument.
Maybe the formatter could even fill this in automatically?

-  abstract def bar(&)
+  abstract def bar(& : -> _)

This would also help to make the difference stand out more clearly.

Related: #8764

@straight-shoota
Copy link
Member

I just realize that the explicit block type restriction doesn't even seem to have much effect. Ignoring the abstract def part for now, a block signature of -> _ apparently doesn't prevent yielding a value?

def bar(& : -> _)
  yield 1
end

bar {|x| x } # => 1

I would've expected that to be an error.
And I would expect that error to apply to he abstract def implementation when the block type conflicts with the yield behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. status:discussion topic:compiler:semantic
Projects
None yet
Development

No branches or pull requests

2 participants