mirror of https://github.com/astral-sh/ruff
add ConstraintSetAssignability relation
This commit is contained in:
parent
8ec6673230
commit
b9691b8a07
|
|
@ -1955,6 +1955,33 @@ impl<'db> Type<'db> {
|
|||
return constraints.implies_subtype_of(db, self, target);
|
||||
}
|
||||
|
||||
// Handle the new constraint-set-based assignability relation next. Comparisons with a
|
||||
// typevar are translated directly into a constraint set.
|
||||
if relation.is_constraint_set_assignability() {
|
||||
// A typevar satisfies a relation when...it satisfies the relation. Yes that's a
|
||||
// tautology! We're moving the caller's subtyping/assignability requirement into a
|
||||
// constraint set. If the typevar has an upper bound or constraints, then the relation
|
||||
// only has to hold when the typevar has a valid specialization (i.e., one that
|
||||
// satisfies the upper bound/constraints).
|
||||
if let Type::TypeVar(bound_typevar) = self {
|
||||
return ConstraintSet::constrain_typevar(
|
||||
db,
|
||||
bound_typevar,
|
||||
Type::Never,
|
||||
target,
|
||||
relation,
|
||||
);
|
||||
} else if let Type::TypeVar(bound_typevar) = target {
|
||||
return ConstraintSet::constrain_typevar(
|
||||
db,
|
||||
bound_typevar,
|
||||
self,
|
||||
Type::object(),
|
||||
relation,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
match (self, target) {
|
||||
// Everything is a subtype of `object`.
|
||||
(_, Type::NominalInstance(instance)) if instance.is_object() => {
|
||||
|
|
@ -2035,7 +2062,7 @@ impl<'db> Type<'db> {
|
|||
);
|
||||
ConstraintSet::from(match relation {
|
||||
TypeRelation::Subtyping | TypeRelation::SubtypingAssuming(_) => false,
|
||||
TypeRelation::Assignability => true,
|
||||
TypeRelation::Assignability | TypeRelation::ConstraintSetAssignability => true,
|
||||
TypeRelation::Redundancy => match target {
|
||||
Type::Dynamic(_) => true,
|
||||
Type::Union(union) => union.elements(db).iter().any(Type::is_dynamic),
|
||||
|
|
@ -2045,7 +2072,7 @@ impl<'db> Type<'db> {
|
|||
}
|
||||
(_, Type::Dynamic(_)) => ConstraintSet::from(match relation {
|
||||
TypeRelation::Subtyping | TypeRelation::SubtypingAssuming(_) => false,
|
||||
TypeRelation::Assignability => true,
|
||||
TypeRelation::Assignability | TypeRelation::ConstraintSetAssignability => true,
|
||||
TypeRelation::Redundancy => match self {
|
||||
Type::Dynamic(_) => true,
|
||||
Type::Intersection(intersection) => {
|
||||
|
|
@ -2309,14 +2336,19 @@ impl<'db> Type<'db> {
|
|||
TypeRelation::Subtyping
|
||||
| TypeRelation::Redundancy
|
||||
| TypeRelation::SubtypingAssuming(_) => self,
|
||||
TypeRelation::Assignability => self.bottom_materialization(db),
|
||||
TypeRelation::Assignability | TypeRelation::ConstraintSetAssignability => {
|
||||
self.bottom_materialization(db)
|
||||
}
|
||||
};
|
||||
intersection.negative(db).iter().when_all(db, |&neg_ty| {
|
||||
let neg_ty = match relation {
|
||||
TypeRelation::Subtyping
|
||||
| TypeRelation::Redundancy
|
||||
| TypeRelation::SubtypingAssuming(_) => neg_ty,
|
||||
TypeRelation::Assignability => neg_ty.bottom_materialization(db),
|
||||
TypeRelation::Assignability
|
||||
| TypeRelation::ConstraintSetAssignability => {
|
||||
neg_ty.bottom_materialization(db)
|
||||
}
|
||||
};
|
||||
self_ty.is_disjoint_from_impl(
|
||||
db,
|
||||
|
|
@ -11860,6 +11892,11 @@ pub(crate) enum TypeRelation<'db> {
|
|||
/// are not actually subtypes of each other. (That is, `implies_subtype_of(false, int, str)`
|
||||
/// will return true!)
|
||||
SubtypingAssuming(ConstraintSet<'db>),
|
||||
|
||||
/// A placeholder for the new assignability relation that uses constraint sets to encode
|
||||
/// relationships with a typevar. This will eventually replace `Assignability`, but allows us
|
||||
/// to start using the new relation in a controlled manner in some places.
|
||||
ConstraintSetAssignability,
|
||||
}
|
||||
|
||||
impl TypeRelation<'_> {
|
||||
|
|
@ -11867,6 +11904,10 @@ impl TypeRelation<'_> {
|
|||
matches!(self, TypeRelation::Assignability)
|
||||
}
|
||||
|
||||
pub(crate) const fn is_constraint_set_assignability(self) -> bool {
|
||||
matches!(self, TypeRelation::ConstraintSetAssignability)
|
||||
}
|
||||
|
||||
pub(crate) const fn is_subtyping(self) -> bool {
|
||||
matches!(self, TypeRelation::Subtyping)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -637,7 +637,9 @@ impl<'db> ClassType<'db> {
|
|||
| TypeRelation::SubtypingAssuming(_) => {
|
||||
ConstraintSet::from(other.is_object(db))
|
||||
}
|
||||
TypeRelation::Assignability => ConstraintSet::from(!other.is_final(db)),
|
||||
TypeRelation::Assignability | TypeRelation::ConstraintSetAssignability => {
|
||||
ConstraintSet::from(!other.is_final(db))
|
||||
}
|
||||
},
|
||||
|
||||
// Protocol, Generic, and TypedDict are not represented by a ClassType.
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ impl<'db> ConstraintSet<'db> {
|
|||
lower.top_materialization(db),
|
||||
upper.bottom_materialization(db),
|
||||
),
|
||||
TypeRelation::Assignability => (
|
||||
TypeRelation::Assignability | TypeRelation::ConstraintSetAssignability => (
|
||||
lower.bottom_materialization(db),
|
||||
upper.top_materialization(db),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -903,7 +903,11 @@ fn has_relation_in_invariant_position<'db>(
|
|||
disjointness_visitor,
|
||||
),
|
||||
// And A <~ B (assignability) is Bottom[A] <: Top[B]
|
||||
(None, Some(base_mat), TypeRelation::Assignability) => is_subtype_in_invariant_position(
|
||||
(
|
||||
None,
|
||||
Some(base_mat),
|
||||
TypeRelation::Assignability | TypeRelation::ConstraintSetAssignability,
|
||||
) => is_subtype_in_invariant_position(
|
||||
db,
|
||||
derived_type,
|
||||
MaterializationKind::Bottom,
|
||||
|
|
@ -913,7 +917,11 @@ fn has_relation_in_invariant_position<'db>(
|
|||
relation_visitor,
|
||||
disjointness_visitor,
|
||||
),
|
||||
(Some(derived_mat), None, TypeRelation::Assignability) => is_subtype_in_invariant_position(
|
||||
(
|
||||
Some(derived_mat),
|
||||
None,
|
||||
TypeRelation::Assignability | TypeRelation::ConstraintSetAssignability,
|
||||
) => is_subtype_in_invariant_position(
|
||||
db,
|
||||
derived_type,
|
||||
derived_mat,
|
||||
|
|
|
|||
Loading…
Reference in New Issue