-
Notifications
You must be signed in to change notification settings - Fork 511
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
Add support for ruby 2.7 **nil
syntax
#3330
Conversation
This commit tracks upstream commit ruby/ruby@6a9ce1f. Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
When found, we save the state in the MethodDef. Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
5a55753
to
3be6afb
Compare
e.addErrorLine(method.data(gs)->loc(), "`{}` defined with `{}` here", data->show(gs), "**nil"); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks to me like this test case is allowed in Ruby 2.7:
def foo(x, **nil)
p x
end
x = {hello: :world}
foo(x)
but I think after the changes in this PR Sorbet will reject this code, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Morriar Are you down to land the changes to expand the parser and the changes to make use of the new **nil
syntax downstream in infer
separately? I have a couple of reasons:
- We don't like adding more bits to ast nodes (like the
isKwnil
bit that was added here) - We don't like adding new flags to the symbol table (like the
isMethodWitKwnil
flag here) - I don't think the change as implemented current models Ruby particularly well (it emits too many errors than it should)
The **nil
seems to be me to be a property of a method's arity / arguments, but we're modeling it as a bit on a method symbol, not stored anywhere near the arguments. It might be that's the best place for it, but I'm not sure at a glance, and I think the parser changes should be enough to be permissive with this new syntax, and we can take more time to think about what the semantics should be.
Sure, I opened #3412 with only the parser bits. To be honest, Sorbet already handles those errors through the signature validation. The infer part of this PR is mostly to catch those errors earlier and display a different error message.
For me it felt more like a property of the method symbol itself than something related to a particular argument. The syntax ties it to an arg but it if we had to write a Sorbet signature builder for it we would most likely have added it the same way we did for |
Keeping this PR open until we figure out what to do with the |
Sounds good to me. Just chatted with @elliottt about this, and it's starting to sound like we'll have to significantly revamp how Sorbet treats keyword args, at which point supporting So I think we're good to keep this open until then. Another thing so I don't forget it: Trevor and I were discussing an idea where instead of having the Thanks again for getting the parser support broken out into a separate PR. |
Motivation
Ruby 2.7 introduces the no-keyword-arguments syntax
**nil
.You can use
**nil
in a method definition to explicitly mark that the method accepts no keyword arguments. Calling such methods with keyword arguments will result in anArgumentError
.This pull request makes Sorbet support the
**nil
syntax and raise errors when keyword arguments are passed to methods that use it. See the many examples intest/testdata/infer/kwnil.rb
.Approach
I wanted to avoid touching the way arguments were handled just for
**nil
, so I figured the easiest way was to just remove it completely from the args list.**nil
and added to the arguments list**nil
**nil
(I reused theMethodArgumentCountMismatch
error)**nil
in procs and lambdaWith Ruby 2.7, you can also use
**nil
in procs and lambdas:While this PR changes the parser so it does not create a syntax error, the
**nil
is still not checked in procs and lambdas.We can store the information in the block definition but then the call is a special case with
Proc.call
and I'm not sure how to get back the**nil
tag from the block at this point.Test plan
See included automated tests.
This PR can be read commit by commit.