[ty] Fix subtyping of invariant generics specialized with Any (#20650)

This commit is contained in:
Alex Waygood 2025-10-01 11:05:54 +01:00 committed by GitHub
parent d9473a2fcf
commit 20eb5b5b35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 51 additions and 11 deletions

View file

@ -602,18 +602,22 @@ fn has_relation_in_invariant_position<'db>(
base_mat,
visitor,
),
// Subtyping between invariant type parameters without a top/bottom materialization involved
// is equivalence
(None, None, TypeRelation::Subtyping) => derived_type.when_equivalent_to(db, *base_type),
(None, None, TypeRelation::Assignability) => derived_type
.has_relation_to_impl(db, *base_type, TypeRelation::Assignability, visitor)
// Subtyping between invariant type parameters without a top/bottom materialization necessitates
// checking the subtyping relation both ways: `A` must be a subtype of `B` *and* `B` must be a
// subtype of `A`. The same applies to assignability.
//
// For subtyping between fully static types, this is the same as equivalence. However, we cannot
// use `is_equivalent_to` (or `when_equivalent_to`) here, because we (correctly) understand
// `list[Any]` as being equivalent to `list[Any]`, but we don't want `list[Any]` to be
// considered a subtype of `list[Any]`. For assignability, we would have the opposite issue if
// we simply checked for equivalence here: `Foo[Any]` should be considered assignable to
// `Foo[list[Any]]` even if `Foo` is invariant, and even though `Any` is not equivalent to
// `list[Any]`, because `Any` is assignable to `list[Any]` and `list[Any]` is assignable to
// `Any`.
(None, None, relation) => derived_type
.has_relation_to_impl(db, *base_type, relation, visitor)
.and(db, || {
base_type.has_relation_to_impl(
db,
*derived_type,
TypeRelation::Assignability,
visitor,
)
base_type.has_relation_to_impl(db, *derived_type, relation, visitor)
}),
// For gradual types, A <: B (subtyping) is defined as Top[A] <: Bottom[B]
(None, Some(base_mat), TypeRelation::Subtyping) => is_subtype_in_invariant_position(