[ty] Fix invariant generic disjointness via materialization overlap#25583
Conversation
Typing conformance resultsNo changes detected ✅Current numbersThe percentage of diagnostics emitted that were expected errors held steady at 91.94%. The percentage of expected errors that received a diagnostic held steady at 87.09%. The number of fully passing files held steady at 92/134. |
Memory usage reportSummary
Significant changesClick to expand detailed breakdowntrio
sphinx
prefect
|
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
type-assertion-failure |
0 | 0 | 1 |
| Total | 0 | 0 | 1 |
Raw diff:
pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
- tests/test_api_types.py:372:9 error[type-assertion-failure] Type `Categorical[str]` does not match asserted type `Categorical[int]`
+ tests/test_api_types.py:372:9 error[type-assertion-failure] Type `Categorical[Unknown]` does not match asserted type `Categorical[int]`| static_assert(is_disjoint_from(Invariant[A | Any], Invariant[B])) | ||
| static_assert(is_disjoint_from(Invariant[B], Invariant[A | Any])) | ||
| static_assert(is_disjoint_from(Invariant[Intersection[A, Any]], Invariant[B])) | ||
| static_assert(is_disjoint_from(Invariant[B], Invariant[Intersection[A, Any]])) |
There was a problem hiding this comment.
The previous "must be fully static" guard did not handle these cases -- but we know these are disjoint.
| static_assert(not is_disjoint_from(Invariant[Id[U]], Invariant[int])) | ||
|
|
||
| static_assert(not is_disjoint_from(Invariant[Id[int]], Invariant[int])) | ||
| static_assert(is_disjoint_from(Invariant[Id[int]], Invariant[str])) |
There was a problem hiding this comment.
The previous "must be fully static" guard also failed this case, because it didn't properly expand the generic typevar (expand_eagerly uses raw_value_type and throws away generics).
| && self_alias | ||
| .specialization(db) | ||
| .generic_context(db) | ||
| .variables(db) | ||
| .any(|typevar| { | ||
| matches!(typevar.variance(db), TypeVarVariance::Invariant) | ||
| }) |
There was a problem hiding this comment.
This guard isn't needed for correctness; it's redundant with the behavior of specialization disjointness, which already handles the different variances correctly.
If this is here as a perf optimization (and you've already demonstrated that it's needed to avoid regression) then we can keep it.
| // `Bottom[L] <: Top[R]` asks whether the materialization ranges for `L` | ||
| // and `R` have any common materialization, so this is symmetric despite | ||
| // using a directional subtyping checker. | ||
| self.as_relation_checker(TypeRelation::Subtyping) | ||
| .check_subtyping_in_invariant_position( | ||
| db, | ||
| left_type, | ||
| MaterializationKind::Bottom, | ||
| right_type, | ||
| MaterializationKind::Top, |
There was a problem hiding this comment.
This is the correct handling of gradual types here, which lets us still detect disjointness in the case of gradual types that can't possibly materialize to the same type.
| db: &'db dyn Db, | ||
| other: Self, | ||
| constraints: &ConstraintSetBuilder<'db>, | ||
| ) -> bool { |
There was a problem hiding this comment.
All these changes are just threading through a common disjointness checker so we maintain our cycle guards when looking at cyclic MRO graphs. (It's probably clearest to look at the two commits in this PR separately: the first commit is just the semantic changes we need, the second looks more invasive but it's just threading things through to fix the stack overflow, no semantic change.)
No description provided.