Skip to content

Commit b31540e

Browse files
committed
use expr in/not in instead of eq/not eq
1 parent 8a99037 commit b31540e

File tree

1 file changed

+2
-142
lines changed

1 file changed

+2
-142
lines changed

crates/ty_python_semantic/src/types/narrow.rs

Lines changed: 2 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -475,146 +475,6 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
475475
self.evaluate_simple_expr(&expr_named.target, is_positive)
476476
}
477477

478-
fn evaluate_expr_eq(&mut self, lhs_ty: Type<'db>, rhs_ty: Type<'db>) -> Option<Type<'db>> {
479-
// We can only narrow on equality checks against single-valued types.
480-
if rhs_ty.is_single_valued(self.db) || rhs_ty.is_union_of_single_valued(self.db) {
481-
// The fully-general (and more efficient) approach here would be to introduce a
482-
// `NeverEqualTo` type that can wrap a single-valued type, and then simply return
483-
// `~NeverEqualTo(rhs_ty)` here and let union/intersection builder sort it out. This is
484-
// how we handle `AlwaysTruthy` and `AlwaysFalsy`. But this means we have to deal with
485-
// this type everywhere, and possibly have it show up unsimplified in some cases, and
486-
// so we instead prefer to just do the simplification here. (Another hybrid option that
487-
// would be similar to this, but more efficient, would be to allow narrowing to return
488-
// something that is not a type, and handle this not-a-type in `symbol_from_bindings`,
489-
// instead of intersecting with a type.)
490-
491-
// Return `true` if it is possible for any two inhabitants of the given types to
492-
// compare equal to each other; otherwise return `false`.
493-
fn could_compare_equal<'db>(
494-
db: &'db dyn Db,
495-
left_ty: Type<'db>,
496-
right_ty: Type<'db>,
497-
) -> bool {
498-
if !left_ty.is_disjoint_from(db, right_ty) {
499-
// If types overlap, they have inhabitants in common; it's definitely possible
500-
// for an object to compare equal to itself.
501-
return true;
502-
}
503-
match (left_ty, right_ty) {
504-
// In order to be sure a union type cannot compare equal to another type, it
505-
// must be true that no element of the union can compare equal to that type.
506-
(Type::Union(union), _) => union
507-
.elements(db)
508-
.iter()
509-
.any(|ty| could_compare_equal(db, *ty, right_ty)),
510-
(_, Type::Union(union)) => union
511-
.elements(db)
512-
.iter()
513-
.any(|ty| could_compare_equal(db, left_ty, *ty)),
514-
// Boolean literals and int literals are disjoint, and single valued, and yet
515-
// `True == 1` and `False == 0`.
516-
(Type::BooleanLiteral(b), Type::IntLiteral(i))
517-
| (Type::IntLiteral(i), Type::BooleanLiteral(b)) => i64::from(b) == i,
518-
// Other than the above cases, two single-valued disjoint types cannot compare
519-
// equal.
520-
_ => !(left_ty.is_single_valued(db) && right_ty.is_single_valued(db)),
521-
}
522-
}
523-
524-
// Return `true` if `lhs_ty` consists only of `LiteralString` and types that cannot
525-
// compare equal to `rhs_ty`.
526-
fn can_narrow_to_rhs<'db>(
527-
db: &'db dyn Db,
528-
lhs_ty: Type<'db>,
529-
rhs_ty: Type<'db>,
530-
) -> bool {
531-
match lhs_ty {
532-
Type::Union(union) => union
533-
.elements(db)
534-
.iter()
535-
.all(|ty| can_narrow_to_rhs(db, *ty, rhs_ty)),
536-
// Either `rhs_ty` is a string literal, in which case we can narrow to it (no
537-
// other string literal could compare equal to it), or it is not a string
538-
// literal, in which case (given that it is single-valued), LiteralString
539-
// cannot compare equal to it.
540-
Type::LiteralString => true,
541-
_ => !could_compare_equal(db, lhs_ty, rhs_ty),
542-
}
543-
}
544-
545-
// Filter `ty` to just the types that cannot be equal to `rhs_ty`.
546-
fn filter_to_cannot_be_equal<'db>(
547-
db: &'db dyn Db,
548-
ty: Type<'db>,
549-
rhs_ty: Type<'db>,
550-
) -> Type<'db> {
551-
match ty {
552-
Type::Union(union) => {
553-
union.map(db, |ty| filter_to_cannot_be_equal(db, *ty, rhs_ty))
554-
}
555-
// Treat `bool` as `Literal[True, False]`.
556-
Type::NominalInstance(instance)
557-
if instance.class(db).is_known(db, KnownClass::Bool) =>
558-
{
559-
UnionType::from_elements(
560-
db,
561-
[Type::BooleanLiteral(true), Type::BooleanLiteral(false)]
562-
.into_iter()
563-
.map(|ty| filter_to_cannot_be_equal(db, ty, rhs_ty)),
564-
)
565-
}
566-
// Treat enums as a union of their members.
567-
Type::NominalInstance(instance)
568-
if enum_metadata(db, instance.class(db).class_literal(db).0).is_some() =>
569-
{
570-
UnionType::from_elements(
571-
db,
572-
enum_member_literals(db, instance.class(db).class_literal(db).0, None)
573-
.expect("Calling `enum_member_literals` on an enum class")
574-
.map(|ty| filter_to_cannot_be_equal(db, ty, rhs_ty)),
575-
)
576-
}
577-
_ => {
578-
if ty.is_single_valued(db) && !could_compare_equal(db, ty, rhs_ty) {
579-
ty
580-
} else {
581-
Type::Never
582-
}
583-
}
584-
}
585-
}
586-
Some(if can_narrow_to_rhs(self.db, lhs_ty, rhs_ty) {
587-
rhs_ty
588-
} else {
589-
filter_to_cannot_be_equal(self.db, lhs_ty, rhs_ty).negate(self.db)
590-
})
591-
} else {
592-
None
593-
}
594-
}
595-
596-
fn evaluate_expr_ne(&mut self, lhs_ty: Type<'db>, rhs_ty: Type<'db>) -> Option<Type<'db>> {
597-
match (lhs_ty, rhs_ty) {
598-
(Type::NominalInstance(instance), Type::IntLiteral(i))
599-
if instance.class(self.db).is_known(self.db, KnownClass::Bool) =>
600-
{
601-
if i == 0 {
602-
Some(Type::BooleanLiteral(false).negate(self.db))
603-
} else if i == 1 {
604-
Some(Type::BooleanLiteral(true).negate(self.db))
605-
} else {
606-
None
607-
}
608-
}
609-
(_, Type::BooleanLiteral(b)) => Some(
610-
UnionType::from_elements(self.db, [rhs_ty, Type::IntLiteral(i64::from(b))])
611-
.negate(self.db),
612-
),
613-
_ if rhs_ty.is_single_valued(self.db) => Some(rhs_ty.negate(self.db)),
614-
_ => None,
615-
}
616-
}
617-
618478
fn evaluate_expr_in(&mut self, lhs_ty: Type<'db>, rhs_ty: Type<'db>) -> Option<Type<'db>> {
619479
if lhs_ty.is_single_valued(self.db) || lhs_ty.is_union_of_single_valued(self.db) {
620480
rhs_ty
@@ -713,8 +573,8 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
713573
}
714574
}
715575
ast::CmpOp::Is => Some(rhs_ty),
716-
ast::CmpOp::Eq => self.evaluate_expr_eq(lhs_ty, rhs_ty),
717-
ast::CmpOp::NotEq => self.evaluate_expr_ne(lhs_ty, rhs_ty),
576+
ast::CmpOp::Eq => self.evaluate_expr_in(lhs_ty, rhs_ty),
577+
ast::CmpOp::NotEq => self.evaluate_expr_not_in(lhs_ty, rhs_ty),
718578
ast::CmpOp::In => self.evaluate_expr_in(lhs_ty, rhs_ty),
719579
ast::CmpOp::NotIn => self.evaluate_expr_not_in(lhs_ty, rhs_ty),
720580
_ => None,

0 commit comments

Comments
 (0)