Note The information in this doc is no longer relevant, as the option has been removed in current versions of Sorbet. It remains here as a reference for those using older Sorbet versions.
In new Sorbet versions, this functionality has been replaced with Untyped Blame tracking, which is a more powerful and precise mechanism to achieve a similar goal.
The first version to remove the
--suggest-sigflag was 0.5.10841.
It's possible to build Sorbet in a way that it can suggest the "most impactful" methods to add a signature to, something like this:
❯ sorbet --suggest-sig foo.rb
No errors! Great job.
Typing `::A#bar` would impact 100.0% callsites(2 out of 2).
There are some fairly involved setup steps to get this working.
Something less involved is asking Sorbet to directly edit a project's source code with sigs that might work. This involves less custom setup.
Most impactful has a narrow definition: the most impactful method to add a sig to is the method which would increase the call-site-level typedness the most. Read this doc to learn what this means, and why the Sorbet team recommends tracking it. It's important to know that this definition of "most impactful" doesn't always match up with your team's or organization's definition of highest impact at any given time.
This approach involves some special setup.
The Sorbet team does not publish versions of Sorbet that can emit a list of most impactful methods to sig out of the box. The logic which collects it to output this information slows down every type check run, not just the runs which output this information.
To gain access to this feature, you'll need to build Sorbet locally in debug
mode. You can check whether your version of Sorbet is in debug mode using the
--version flag:
❯ srb tc --version
Sorbet typechecker ... debug_mode=true
If you see debug_mode=true, then Sorbet was built in debug mode.
To build Sorbet in debug mode, follow the setup instructions in the README and then run:
./bazel build //main:sorbet --config=release-debug-linux
(There are many other ways to build debug mode versions of Sorbet; see the README if you're curious.)
After having built Sorbet from source, there will be a file
bazel-bin/main/sorbet in the Sorbet project folder. To run this version of
Sorbet on a Ruby project:
-
Change to the project's directory.
-
Run
./path/to/bazel-bin/main/sorbetwith whatever arguments you usually give tosrb tc, but add--suggest-sig:./path/to/bazel-bin/main/sorbet --suggest-sig <...>
If your project doesn't run
srb tcdirectly but wraps it with a custom script, you can setSRB_SORBET_EXEbefore running your custom script, likeexport SRB_SORBET_EXE=./path/to/bazel-bin/main/sorbet my-custom-script.sh <...>
After Sorbet finishes checking the project, it will output a bunch of lines that look like:
Typing `::A#bar` would impact 100.0% callsites(2 out of 2).
The units of what's being counted here is kind of abstract (fully understanding
it involves fully understanding the intermediate representation that Sorbet uses
when typechecking a method), but at a high level it's counting the
number of sub-expressions in that method whose types reference anything untyped.
It tracks back the source of the untypedness to the definition that introduced
the T.untyped.
Feel free to try to read the source code if that's confusing. The point I'm trying to make is that this metric is not 1-to-1 with the call-site-level typedness metric (i.e., the percentage is not a measure of how much the call-site-level typedness will improve by adding a sig to that thing).
Rather, treat it as an ordered list; the ones higher on the list will have more of an impact on the metric than the ones lower.
Sorbet can sometimes make an educated guess about what sig to put on a method, and directly edit the project to include this sig. This is useful as a starting point for a more manual effort.
Note that while much of this is automated, it is not a silver bullet. Sometimes
the sigs Sorbet guesses are bad or have lots of T.untyped in them. Sometimes
the sigs that Sorbet inserts reveal type errors in other parts of a codebase. In
these cases. Play around with this to see how well it works for you.
In typed: strict files, it's an error for a method to not have a sig. When
reporting these errors, Sorbet attempts to guess a signature that might work for
that method, and then adds it to the error message.
editor.rb:5: The method `bar` does not have a sig https://srb.help/7017
5 | def bar; end
^^^^^^^
Autocorrect: Use `-a` to autocorrect
editor.rb:5: Insert sig {returns(NilClass)}
5 | def bar; end
^
Errors: 1
These errors always have the error code 7017, are only reported if the file is
typed: strict or higher. They can be applied with the --autocorrect option.
To opt all files into this strictness level and insert as many sigs as Sorbet can guess, run this:
srb tc --typed=strict --isolate-error-code=7017 --autocorrect
This
- opts all files into
typed: strict, regardless of what level they were previously at - silences reporting errors for any error other than
7017(so that the only autocorrects will be for inserting sigs, not fixing any other type errors) - edits the files in place whenever Sorbet could suggest a sig.
We used these options heavily when rolling out signatures in Stripe's codebase. Some tips:
-
Run this command until Sorbet stops editing files. Frequently adding a sig in one place will give Sorbet enough information to add a sig in another place.
-
If a particular sig looks like it introduces a lot of type errors, remove it. You can fix it manually later, rather than trying to get Sorbet to suggest a different or better sig.
-
Run your test suite. This is one area where having
sigs checked at runtime helps: if Sorbet's guess was wrong, it's likely that the tests will catch it.