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

ruby27: Introduce numbered parameters support #3344

Merged
merged 20 commits into from
Sep 10, 2020

Conversation

Morriar
Copy link
Collaborator

@Morriar Morriar commented Aug 4, 2020

Motivation

Ruby 27 introduced numbered parameters:

In block without explicitly specified parameters, variables _1 through _9 can be used to reference parameters.

With numbered parameters, this snippet:

filenames.each { |f| File.read(f) }

Is equivalent to

filenames.each { File.read(_1) }

This pull request introduces full support for numbered parameters in Sorbet:

[1, 2, 3].map { T.reveal_type(_1) } # Revealed type: `Integer`

["albatross", "dog", "horse"].max(2) do
  T.reveal_type(_1) # Revealed type: `String`
  T.reveal_type(_2) # Revealed type: `String`
  _1.length <=> _2.length
end

See the tests for more usage examples.

Implementation

During parsing blocks containing identifiers _1 to _9 are created as NumBlock instead of Block and we keep a stack of the numbers used.

During desugar, the NumBlock is translated into an ordinary block. Implicit parameters are added to the block args from _1 to the max number used.

At this point, Sorbet can work its magic on the block and perform the typing.

Test plan

See included automated tests.

@Morriar Morriar requested a review from a team as a code owner August 4, 2020 16:54
@Morriar Morriar requested review from DarkDimius and removed request for a team August 4, 2020 16:54
@Morriar Morriar mentioned this pull request Aug 4, 2020
@Morriar Morriar force-pushed the at-ruby27-numparams branch 2 times, most recently from 5d5c331 to 6644684 Compare August 4, 2020 17:39
parser/Builder.cc Outdated Show resolved Hide resolved
parser/Builder.cc Outdated Show resolved Hide resolved
parser/Builder.cc Outdated Show resolved Hide resolved
parser/Builder.cc Outdated Show resolved Hide resolved
parser/Builder.cc Outdated Show resolved Hide resolved
parser/Builder.cc Show resolved Hide resolved
ast/desugar/Desugar.cc Outdated Show resolved Hide resolved
ast/desugar/Desugar.cc Outdated Show resolved Hide resolved
ast/desugar/Desugar.cc Outdated Show resolved Hide resolved
@jez
Copy link
Collaborator

jez commented Sep 10, 2020

This looks really good. I'm done leaving comments for now. Feel free to re-request review when you want another look.

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>
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>
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>
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>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
…cks and lambdas

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>
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>
// For each scope we save the highest numparam used (or 0) and all the nodes in the
// scope referencing a numparam.
//
// The stack as 3 states:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// The stack as 3 states:
// The stack has 3 states:

Comment on lines +67 to +71
if (auto *lvar = parser::cast_node<parser::LVar>(decl.get())) {
if (numparamNum(dctx, decl.get()) == num) {
return MK::Local(lvar->loc, lvar->name);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be an ENFORCE if this cast ever fails?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(i.e., it's fine for it to fallback to the dummy MK::Local if this search fails to find something so that sorbet doesn't crash, but would that be an expected situation or a bug in sorbet?)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh i see, we might be making locals for like _1 and _2 only because we saw _3 in the body. makes sense, i see that the comment is getting at that now.

Copy link
Collaborator

@jez jez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@jez
Copy link
Collaborator

jez commented Sep 10, 2020

We have a policy of testing changes to Sorbet against Stripe's codebase before
merging them. I've kicked off a test run for the current PR. When the build
finishes, I'll share with you whether or how it failed. Thanks!

Stripe employees can see the build result here:

https://go/builds/bui_HzyMorejlXmxQ4

@jez jez merged commit 19a4f19 into sorbet:master Sep 10, 2020
@Morriar Morriar deleted the at-ruby27-numparams branch September 11, 2020 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants