[ty] cache Type::is_redundant_with (#20477)

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
This commit is contained in:
Carl Meyer 2025-10-16 04:46:56 -07:00 committed by GitHub
parent 5fb142374d
commit d23826ce46
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 0 deletions

View file

@ -360,3 +360,14 @@ type X = tuple[X, int]
def _(x: X):
reveal_type(x is x) # revealed: bool
```
### Recursive invariant
```py
type X = dict[str, X]
type Y = X | str | dict[str, Y]
def _(y: Y):
if isinstance(y, dict):
reveal_type(y) # revealed: dict[str, X] | dict[str, Y]
```

View file

@ -1543,6 +1543,7 @@ impl<'db> Type<'db> {
/// Return `true` if it would be redundant to add `self` to a union that already contains `other`.
///
/// See [`TypeRelation::Redundancy`] for more details.
#[salsa::tracked(cycle_fn=is_redundant_with_cycle_recover, cycle_initial=is_redundant_with_cycle_initial, heap_size=ruff_memory_usage::heap_size)]
pub(crate) fn is_redundant_with(self, db: &'db dyn Db, other: Type<'db>) -> bool {
self.has_relation_to(db, other, InferableTypeVars::None, TypeRelation::Redundancy)
.is_always_satisfied()
@ -7326,6 +7327,25 @@ impl<'db> VarianceInferable<'db> for Type<'db> {
}
}
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_redundant_with_cycle_recover<'db>(
_db: &'db dyn Db,
_value: &bool,
_count: u32,
_subtype: Type<'db>,
_supertype: Type<'db>,
) -> salsa::CycleRecoveryAction<bool> {
salsa::CycleRecoveryAction::Iterate
}
fn is_redundant_with_cycle_initial<'db>(
_db: &'db dyn Db,
_subtype: Type<'db>,
_supertype: Type<'db>,
) -> bool {
true
}
fn apply_specialization_cycle_recover<'db>(
_db: &'db dyn Db,
_value: &Type<'db>,