8000 Add T.bind for changing bindings inside procs and lambdas by vinistock · Pull Request #4170 · sorbet/sorbet · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add T.bind for changing bindings inside procs and lambdas #4170

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

Merged
merged 6 commits into from
Apr 29, 2021

Conversation

vinistock
Copy link
Collaborator
@vinistock vinistock commented Apr 22, 2021

This PR introduces T.bind outside of the context of method signatures to allow users to bind procs and lambdas to different types. This is especially useful in the Rails world, where a lot of procs are executed with instance_exec.

For example,

class Post < ApplicationRecord
  # In callbacks from ActiveRecord, ActiveModel and Actionpack, `if` and `unless` options
  # can be passed as lambdas to determine whether it should run or not. These keys are part
  # of keyword arguments and the block is captured and then executed in the context of the instance.
  #
  # Sorbet doesn't know that it will be executed in an instance context and errors with
  # "method `should_do_it?` is not defined for T.class_of(Post)
  before_create :do_something, if: -> { should_do_it? }

  private

  def should_do_it?
    true
  end
end

With the changes in this PR, users can indicate the correct binding inside each proc, guaranteeing that type checking is verifying against the right types. Below is an example usage and more examples can be found in the tests included.

class Post < ApplicationRecord
  # Proc is now bound to `Post` and not `T.class_of(Post)`. No errors!
  before_create :do_something, if: -> { T.bind(self, Post); should_do_it? }

  private

  def should_do_it?
    true
  end
end

Motivation

Sorbet currently does not allow indicating the context in which a captured block will run, which limits typing in common Rails use cases, such as the previously mentioned callbacks, but also active support concerns.

Test plan

The included tests display examples for concerns and callbacks.

@vinistock vinistock requested a review from a team as a code owner April 22, 2021 18:21
@vinistock vinistock requested review from jez and removed request for a team April 22, 2021 18:21
@Morriar
Copy link
Collaborator
Morriar commented Apr 22, 2021 8000

I think this PR is also providing a solution for #230?

@vinistock vinistock force-pushed the add_t_bind_for_procs branch from a49f22e to e342768 Compare April 28, 2021 13:40
@vinistock
Copy link
Collaborator Author

Updated the PR description to also close #230, which indeed will be fixed by this.

@jez should I add documentation about T.bind to the website code in this PR or in a subsequent one?

@jez
Copy link
Collaborator
jez commented Apr 28, 2021

@jez should I add documentation about T.bind to the website code in this PR or in a subsequent one?

I prefer in this PR, but if you wanted to do it in a follow up PR I wouldn't block this PR on it.

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.

This looks great, thanks for those changes!

Some small suggested changes, and then waiting to hear back w.r.t. whether you want to do docs in this PR or another. I can merge as is or wait for the docs, just let me know.

@vinistock
Copy link
Collaborator Author

Cool! I'll add the documentation to this PR and address the remaining comments, so that we can ship it all in one go.

@vinistock vinistock force-pushed the add_t_bind_for_procs branch from 11ddf47 to fa47097 Compare April 29, 2021 18:51
@vinistock
Copy link
Collaborator Author

Alright, added website documentation. Let me know if the copy looks good!

@jez
Copy link
Collaborator
jez commented Apr 29, 2021

@vinistock Does this actually close #4095?

That issue requests a static error when using T.proc.bind on a non-block argument.

This PR implements an alternative for people who think that they want the behavior they imagine would be possible with T.proc.bind on a non-block argument.

I don't think we should expand the scope of this PR, but I am going to mark this PR as not closing that issue.

@jez
Copy link
Collaborator
jez commented Apr 29, 2021

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 results here:

https://go/builds/bui_JOUwqSiKKgp6Fd
https://go/builds/bui_JOUwYlCyr4Mq8r

@jez jez merged commit 47d5519 into sorbet:master Apr 29, 2021
@jez
Copy link
Collaborator
jez commented Apr 29, 2021

Thanks!

@vinistock vinistock deleted the add_t_bind_for_procs branch April 30, 2021 13:23
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.

3 participants
0