Add more fast-paths

This commit is contained in:
Charlie Marsh
2026-01-13 20:36:53 -05:00
parent 3dba88b2fe
commit 0eb28df0b0

View File

@@ -823,23 +823,47 @@ impl<'db> Type<'db> {
})
}),
// Fast path for pure negations (~X): these are semantically `object & ~X`, so they're
// only assignable to types that `object` is assignable to. Since `object` is only
// assignable to `object`, dynamic types, unions/protocols/intersections that might
// contain `object`, we can short-circuit most cases directly.
(Type::Intersection(intersection), _) if intersection.positive(db).is_empty() => {
match target {
// `object` is a subtype of `object`
_ if target.is_object() => ConstraintSet::from(true),
// `object` is a subtype of dynamic types
Type::Dynamic(_) => ConstraintSet::from(true),
// These cases need more complex checking - delegate to full machinery
// (TypeVar needs special handling for inference)
Type::Union(_)
| Type::ProtocolInstance(_)
| Type::Intersection(_)
| Type::TypeVar(_) => Type::object().has_relation_to_impl(
db,
target,
inferable,
relation,
relation_visitor,
disjointness_visitor,
),
// `object` is not a subtype of any other type
_ => ConstraintSet::from(false),
}
}
(Type::Intersection(intersection), _) => {
// An intersection type is a subtype of another type if at least one of its
// positive elements is a subtype of that type. If there are no positive elements,
// we treat `object` as the implicit positive element (e.g., `~str` is semantically
// `object & ~str`).
intersection
.positive_elements_or_object(db)
.when_any(db, |elem_ty| {
elem_ty.has_relation_to_impl(
db,
target,
inferable,
relation,
relation_visitor,
disjointness_visitor,
)
})
// positive elements is a subtype of that type.
intersection.positive(db).iter().when_any(db, |&elem_ty| {
elem_ty.has_relation_to_impl(
db,
target,
inferable,
relation,
relation_visitor,
disjointness_visitor,
)
})
}
// Other than the special cases checked above, no other types are a subtype of a