# typed: strict
module Bar
extend(T::Sig)
sig { returns(T.proc.params(a: T.untyped, b: T.untyped).void) }
def hello
-> (a,b) { a + b }
end
end
editor.rb:7: Method lambda does not exist on Bar https://srb.help/7003
7 | -> (a,b) { a + b }
^^^^^^^^^^^^^^^^^^
Did you mean to `include Kernel` in this module?
https://github.com/sorbet/sorbet/tree/master/rbi/core/kernel.rbi#L1715: Did you mean: Kernel#lambda?
1715 | def lambda(&blk); end
^^^^^^^^^^^^^^^^
Errors: 1
No issues to be displayed.
This is expected behavior. See https://github.com/sorbet/sorbet/issues/2236
This is something we could model more precisely, but it's going to be a lot of work for comparatively little benefit. You can already work around this problem by using include Kernel in the body of your module, like the error message suggests.
@jez I think this particular case is a little different, though, since this is actually valid Ruby code being flagged as invalid by Sorbet.
For example:
module Bar
def hello
-> (a,b) { a + b }
end
end
class Foo < BasicObject
include ::Bar
end
Foo.new.hello # is ok
Foo.new.hello.(1, 2) #=> 3
I think the problem is that Sorbet desugars -> to lambda but lambda happens to be a Kernel method, thus causing the error in Sorbet. However, at runtime -> has slightly different semantics than Kernel#lambda, so the code is actually valid.
But I see the point @aisamanra is making, that it might be way more hassle to model this precisely. I just wanted to point out that this is not exactly the same case as #2236, though.
What about desugaring -> as Kernel.lambda?
module Bar
def hello
Kernel.lambda { |a, b| a + b }
end
end
class Foo < BasicObject
include ::Bar
end
puts Foo.new.hello # is ok
puts Foo.new.hello.(1, 2) #=> 3
And it typechecks.
Nice idea! Would you be up to make a PR with it?