Skip to content

Require RBI::Type objects throughout the model - #646

Open
Morriar wants to merge 5 commits into
mainfrom
type-only-model
Open

Require RBI::Type objects throughout the model#646
Morriar wants to merge 5 commits into
mainfrom
type-only-model

Conversation

@Morriar

@Morriar Morriar commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

What

This PR removes the backwards-compatible support for passing type strings to RBI model objects. APIs that previously accepted RBI::Type | String now accept only RBI::Type.

It also migrates internal producers and consumers to the new contract:

  • The parser converts type syntax into RBI::Type objects using Type.parse_string.
  • Signature return types, signature parameters, and T::Struct fields are represented as Type.
  • Rewriters and benchmarks construct types through the Type API.
  • The RBI printer consumes Type objects directly.
  • The RBS printer handles and simplifies already-parsed Type objects.

Why

RBI::Type was introduced while retaining String support for backwards compatibility. Keeping both representations means every consumer must handle two possible types and allows unparsed type syntax to flow through the model.

Using a single representation:

  • Makes the model contract explicit.
  • Centralizes parsing and validation in the type parser.
  • Removes String compatibility branches from downstream consumers.
  • Allows rewriters and printers to operate on the structured type representation.

Output changes

Parsing and printing an RBI now uses Type#to_rbi, which canonicalizes Sorbet helpers with an absolute ::T prefix.

For example:

-sig { params(value: T.untyped).returns(T.nilable(String)) }
+sig { params(value: ::T.untyped).returns(::T.nilable(String)) }

This preserves the existing Type#to_rbi behavior and prevents a locally defined T constant from shadowing Sorbet’s top-level T.

Generic names whose qualification is represented directly by the parsed type remain unchanged, such as T::Array[String].

Breaking changes

Callers must replace type strings with RBI::Type objects:

-RBI::SigParam.new("value", "T.nilable(String)")
+RBI::SigParam.new(
+  "value",
+  RBI::Type.nilable(RBI::Type.simple("String")),
+)
-RBI::Sig.new(return_type: "void")
+RBI::Sig.new(return_type: RBI::Type.void)

The affected APIs include:

  • RBI::Method#add_sig
  • RBI::Sig#initialize
  • RBI::Sig#return_type=
  • RBI::Sig#add_param
  • RBI::SigParam#initialize
  • RBI::TStructConst#initialize
  • RBI::TStructProp#initialize
  • RBI::TStructField#type=

@Morriar
Morriar requested a review from a team as a code owner August 4, 2026 19:57
@Morriar
Morriar force-pushed the type-only-model branch 2 times, most recently from 270706d to 72dcac3 Compare August 4, 2026 20:12
Comment thread rbi/rbi.rbi
sig { returns(::RBI::Type) }
def return_type; end

def return_type=(_arg0); end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FYI I think this is coming from an attr_accessor above and even though the reader is typed the writer isn't.

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.

2 participants