Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lub: Better reduce AndTypes created during type inference. (#4435)
lub: Better reduce AndTypes created during type inference. Adds the following support to `lub`: * When lubbing an `AndType` and an `OrType`, call `lubDistributeOr` if our `AndType` lub attempt fails rather than making a new `OrType`. * When lubbing an `AndType` and an `AndType`, check if their parts are (deeply) referentially equivalent. There are tests that demonstrate the change. Not handled in this PR is the following scenario: * lubbing an `OrType` and an `OrType` Attempts to handle this use-case ended up being too expensive to land, and changed the types that Sorbet inferred causing type errors on Stripe's codebase. I may pursue this change in a subsequent PR, as type inference still produces some `T.any` types with redundant members. ### Motivation <!-- Why make this change? Describe the problem, not the solution. This can also be a link to an issue. --> Type inference creates AndTypes which get nested into OrTypes. This process causes `lub` to get called in a few scenarios that, prior to this change, it was ill-equipped to deal with: * An `AndType` and an `OrType`. * An `AndType` and an `AndType` that are equivalent. One particular file at Stripe spent a lot of time lubbing these types together, which resulted in monstrous types such as the following (note: `Boolean` != `T::Boolean` in this case; Stripe has a legacy module named `Boolean`): ``` T.any(T.all(Boolean, T.nilable(FalseClass)), T.all(Boolean, NilClass), T.all(Boolean, NilClass), T.all(Boolean, NilClass), T.all(Boolean, T.nilable(FalseClass)), FalseClass, T.all(Boolean, NilClass), TrueClass) ``` All of this time spent in lub added up to a long typechecking time. The changes in this PR halves the time it spends in typechecking.
- Loading branch information