Skip to content

Commit 1cd8ab3

Browse files
[ty] Remove the Constraints trait (#20355)
This PR removes the `Constraints` trait. We removed the `bool` implementation several weeks back, and are using `ConstraintSet` everywhere. There have been discussions about trying to include the reason for an assignability failure as part of the result, but that there are no concrete plans to do so soon, and it's not clear that we'll need the `Constraints` trait to do that. (We can ideally just update the `ConstraintSet` type directly.) In the meantime, this just complicates the code for no good reason. This PR is a pure refactoring, and contains no behavioral changes. --------- Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
1 parent 3688819 commit 1cd8ab3

File tree

12 files changed

+551
-571
lines changed

12 files changed

+551
-571
lines changed

crates/ty_python_semantic/src/types.rs

Lines changed: 186 additions & 184 deletions
Large diffs are not rendered by default.

crates/ty_python_semantic/src/types/call/bind.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use crate::db::Db;
1717
use crate::dunder_all::dunder_all_names;
1818
use crate::place::{Boundness, Place};
1919
use crate::types::call::arguments::{Expansion, is_expandable_type};
20-
use crate::types::constraints::{ConstraintSet, Constraints};
2120
use crate::types::diagnostic::{
2221
CALL_NON_CALLABLE, CONFLICTING_ARGUMENT_FORMS, INVALID_ARGUMENT_TYPE, MISSING_ARGUMENT,
2322
NO_MATCHING_OVERLOAD, PARAMETER_ALREADY_ASSIGNED, TOO_MANY_POSITIONAL_ARGUMENTS,
@@ -586,8 +585,7 @@ impl<'db> Bindings<'db> {
586585
Type::FunctionLiteral(function_type) => match function_type.known(db) {
587586
Some(KnownFunction::IsEquivalentTo) => {
588587
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
589-
let constraints =
590-
ty_a.when_equivalent_to::<ConstraintSet>(db, *ty_b);
588+
let constraints = ty_a.when_equivalent_to(db, *ty_b);
591589
let tracked = TrackedConstraintSet::new(db, constraints);
592590
overload.set_return_type(Type::KnownInstance(
593591
KnownInstanceType::ConstraintSet(tracked),
@@ -597,7 +595,7 @@ impl<'db> Bindings<'db> {
597595

598596
Some(KnownFunction::IsSubtypeOf) => {
599597
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
600-
let constraints = ty_a.when_subtype_of::<ConstraintSet>(db, *ty_b);
598+
let constraints = ty_a.when_subtype_of(db, *ty_b);
601599
let tracked = TrackedConstraintSet::new(db, constraints);
602600
overload.set_return_type(Type::KnownInstance(
603601
KnownInstanceType::ConstraintSet(tracked),
@@ -607,8 +605,7 @@ impl<'db> Bindings<'db> {
607605

608606
Some(KnownFunction::IsAssignableTo) => {
609607
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
610-
let constraints =
611-
ty_a.when_assignable_to::<ConstraintSet>(db, *ty_b);
608+
let constraints = ty_a.when_assignable_to(db, *ty_b);
612609
let tracked = TrackedConstraintSet::new(db, constraints);
613610
overload.set_return_type(Type::KnownInstance(
614611
KnownInstanceType::ConstraintSet(tracked),
@@ -618,8 +615,7 @@ impl<'db> Bindings<'db> {
618615

619616
Some(KnownFunction::IsDisjointFrom) => {
620617
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
621-
let constraints =
622-
ty_a.when_disjoint_from::<ConstraintSet>(db, *ty_b);
618+
let constraints = ty_a.when_disjoint_from(db, *ty_b);
623619
let tracked = TrackedConstraintSet::new(db, constraints);
624620
overload.set_return_type(Type::KnownInstance(
625621
KnownInstanceType::ConstraintSet(tracked),
@@ -2252,8 +2248,8 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
22522248
// constraint set that we get from this assignability check, instead of inferring and
22532249
// building them in an earlier separate step.
22542250
if argument_type
2255-
.when_assignable_to::<ConstraintSet>(self.db, expected_ty)
2256-
.is_never_satisfied(self.db)
2251+
.when_assignable_to(self.db, expected_ty)
2252+
.is_never_satisfied()
22572253
{
22582254
let positional = matches!(argument, Argument::Positional | Argument::Synthetic)
22592255
&& !parameter.is_variadic();

crates/ty_python_semantic/src/types/class.rs

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::semantic_index::symbol::Symbol;
1414
use crate::semantic_index::{
1515
DeclarationWithConstraint, SemanticIndex, attribute_declarations, attribute_scopes,
1616
};
17-
use crate::types::constraints::{ConstraintSet, Constraints, IteratorConstraintsExtension};
17+
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
1818
use crate::types::context::InferContext;
1919
use crate::types::diagnostic::{INVALID_LEGACY_TYPE_VARIABLE, INVALID_TYPE_ALIAS_TYPE};
2020
use crate::types::enums::enum_metadata;
@@ -524,46 +524,45 @@ impl<'db> ClassType<'db> {
524524

525525
/// Return `true` if `other` is present in this class's MRO.
526526
pub(super) fn is_subclass_of(self, db: &'db dyn Db, other: ClassType<'db>) -> bool {
527-
self.when_subclass_of::<ConstraintSet>(db, other)
528-
.is_always_satisfied(db)
527+
self.when_subclass_of(db, other).is_always_satisfied()
529528
}
530529

531-
pub(super) fn when_subclass_of<C: Constraints<'db>>(
530+
pub(super) fn when_subclass_of(
532531
self,
533532
db: &'db dyn Db,
534533
other: ClassType<'db>,
535-
) -> C {
534+
) -> ConstraintSet<'db> {
536535
self.has_relation_to_impl(
537536
db,
538537
other,
539538
TypeRelation::Subtyping,
540-
&HasRelationToVisitor::new(C::always_satisfiable(db)),
539+
&HasRelationToVisitor::default(),
541540
)
542541
}
543542

544-
pub(super) fn has_relation_to_impl<C: Constraints<'db>>(
543+
pub(super) fn has_relation_to_impl(
545544
self,
546545
db: &'db dyn Db,
547546
other: Self,
548547
relation: TypeRelation,
549-
visitor: &HasRelationToVisitor<'db, C>,
550-
) -> C {
548+
visitor: &HasRelationToVisitor<'db>,
549+
) -> ConstraintSet<'db> {
551550
self.iter_mro(db).when_any(db, |base| {
552551
match base {
553552
ClassBase::Dynamic(_) => match relation {
554-
TypeRelation::Subtyping => C::from_bool(db, other.is_object(db)),
555-
TypeRelation::Assignability => C::from_bool(db, !other.is_final(db)),
553+
TypeRelation::Subtyping => ConstraintSet::from(other.is_object(db)),
554+
TypeRelation::Assignability => ConstraintSet::from(!other.is_final(db)),
556555
},
557556

558557
// Protocol and Generic are not represented by a ClassType.
559-
ClassBase::Protocol | ClassBase::Generic => C::unsatisfiable(db),
558+
ClassBase::Protocol | ClassBase::Generic => ConstraintSet::from(false),
560559

561560
ClassBase::Class(base) => match (base, other) {
562561
(ClassType::NonGeneric(base), ClassType::NonGeneric(other)) => {
563-
C::from_bool(db, base == other)
562+
ConstraintSet::from(base == other)
564563
}
565564
(ClassType::Generic(base), ClassType::Generic(other)) => {
566-
C::from_bool(db, base.origin(db) == other.origin(db)).and(db, || {
565+
ConstraintSet::from(base.origin(db) == other.origin(db)).and(db, || {
567566
base.specialization(db).has_relation_to_impl(
568567
db,
569568
other.specialization(db),
@@ -573,34 +572,38 @@ impl<'db> ClassType<'db> {
573572
})
574573
}
575574
(ClassType::Generic(_), ClassType::NonGeneric(_))
576-
| (ClassType::NonGeneric(_), ClassType::Generic(_)) => C::unsatisfiable(db),
575+
| (ClassType::NonGeneric(_), ClassType::Generic(_)) => {
576+
ConstraintSet::from(false)
577+
}
577578
},
578579

579580
ClassBase::TypedDict => {
580581
// TODO: Implement subclassing and assignability for TypedDicts.
581-
C::always_satisfiable(db)
582+
ConstraintSet::from(true)
582583
}
583584
}
584585
})
585586
}
586587

587-
pub(super) fn is_equivalent_to_impl<C: Constraints<'db>>(
588+
pub(super) fn is_equivalent_to_impl(
588589
self,
589590
db: &'db dyn Db,
590591
other: ClassType<'db>,
591-
visitor: &IsEquivalentVisitor<'db, C>,
592-
) -> C {
592+
visitor: &IsEquivalentVisitor<'db>,
593+
) -> ConstraintSet<'db> {
593594
if self == other {
594-
return C::always_satisfiable(db);
595+
return ConstraintSet::from(true);
595596
}
596597

597598
match (self, other) {
598599
// A non-generic class is never equivalent to a generic class.
599600
// Two non-generic classes are only equivalent if they are equal (handled above).
600-
(ClassType::NonGeneric(_), _) | (_, ClassType::NonGeneric(_)) => C::unsatisfiable(db),
601+
(ClassType::NonGeneric(_), _) | (_, ClassType::NonGeneric(_)) => {
602+
ConstraintSet::from(false)
603+
}
601604

602605
(ClassType::Generic(this), ClassType::Generic(other)) => {
603-
C::from_bool(db, this.origin(db) == other.origin(db)).and(db, || {
606+
ConstraintSet::from(this.origin(db) == other.origin(db)).and(db, || {
604607
this.specialization(db).is_equivalent_to_impl(
605608
db,
606609
other.specialization(db),
@@ -1701,13 +1704,13 @@ impl<'db> ClassLiteral<'db> {
17011704
.contains(&ClassBase::Class(other))
17021705
}
17031706

1704-
pub(super) fn when_subclass_of<C: Constraints<'db>>(
1707+
pub(super) fn when_subclass_of(
17051708
self,
17061709
db: &'db dyn Db,
17071710
specialization: Option<Specialization<'db>>,
17081711
other: ClassType<'db>,
1709-
) -> C {
1710-
C::from_bool(db, self.is_subclass_of(db, specialization, other))
1712+
) -> ConstraintSet<'db> {
1713+
ConstraintSet::from(self.is_subclass_of(db, specialization, other))
17111714
}
17121715

17131716
/// Return `true` if this class constitutes a typed dict specification (inherits from
@@ -4360,12 +4363,12 @@ impl KnownClass {
43604363
.is_ok_and(|class| class.is_subclass_of(db, None, other))
43614364
}
43624365

4363-
pub(super) fn when_subclass_of<'db, C: Constraints<'db>>(
4366+
pub(super) fn when_subclass_of<'db>(
43644367
self,
43654368
db: &'db dyn Db,
43664369
other: ClassType<'db>,
4367-
) -> C {
4368-
C::from_bool(db, self.is_subclass_of(db, other))
4370+
) -> ConstraintSet<'db> {
4371+
ConstraintSet::from(self.is_subclass_of(db, other))
43694372
}
43704373

43714374
/// Return the module in which we should look up the definition for this class

0 commit comments

Comments
 (0)