use subtyping

This commit is contained in:
Douglas Creager
2026-01-06 17:31:10 -05:00
parent ca4984bf8e
commit ac3f0db809
2 changed files with 27 additions and 7 deletions

View File

@@ -747,12 +747,16 @@ impl<'db> ConstrainedTypeVar<'db> {
if !self.typevar(db).is_same_typevar_as(db, other.typevar(db)) {
return false;
}
// Note that we check that the bounds are _subtypes_ of each other, because we do not want
// dynamic types like `Any` to be pivots that we can use to compute transitive sequent map
// relationships.
other
.lower(db)
.is_constraint_set_assignable_to(db, self.lower(db))
.is_constraint_set_subtype_of(db, self.lower(db))
&& self
.upper(db)
.is_constraint_set_assignable_to(db, other.upper(db))
.is_constraint_set_subtype_of(db, other.upper(db))
}
/// Returns the intersection of two range constraints, or `None` if the intersection is empty.
@@ -763,7 +767,7 @@ impl<'db> ConstrainedTypeVar<'db> {
// If `lower ≰ upper`, then the intersection is empty, since there is no type that is both
// greater than `lower`, and less than `upper`.
if !lower.is_constraint_set_assignable_to(db, upper) {
if !lower.is_constraint_set_subtype_of(db, upper) {
return IntersectionResult::Disjoint;
}

View File

@@ -260,15 +260,17 @@ impl<'db> Type<'db> {
}
/// Return true if this type is assignable to type `target` using constraint-set assignability.
///
/// This uses `TypeRelation::ConstraintSetAssignability`, which encodes typevar relations into
/// a constraint set and lets `satisfied_by_all_typevars` perform existential vs universal
/// reasoning depending on inferable typevars.
pub fn is_constraint_set_assignable_to(self, db: &'db dyn Db, target: Type<'db>) -> bool {
self.when_constraint_set_assignable_to(db, target, InferableTypeVars::None)
.is_always_satisfied(db)
}
/// Return true if this type is assignable to type `target` using constraint-set assignability.
pub fn is_constraint_set_subtype_of(self, db: &'db dyn Db, target: Type<'db>) -> bool {
self.when_constraint_set_subtype_of(db, target, InferableTypeVars::None)
.is_always_satisfied(db)
}
pub(super) fn when_assignable_to(
self,
db: &'db dyn Db,
@@ -297,6 +299,20 @@ impl<'db> Type<'db> {
)
}
pub(super) fn when_constraint_set_subtype_of(
self,
db: &'db dyn Db,
target: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
) -> ConstraintSet<'db> {
self.has_relation_to(
db,
target,
inferable,
TypeRelation::Subtyping(UseConstraintSets::Yes),
)
}
/// Return `true` if it would be redundant to add `self` to a union that already contains `other`.
///
/// See [`TypeRelation::Redundancy`] for more details.