Compare commits
1 Commits
zb/cache-n
...
alex/use-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec8a3548d7 |
@@ -715,7 +715,6 @@ impl<'db> ClassType<'db> {
|
||||
/// Return the [`DisjointBase`] that appears first in the MRO of this class.
|
||||
///
|
||||
/// Returns `None` if this class does not have any disjoint bases in its MRO.
|
||||
#[salsa::tracked(heap_size=ruff_memory_usage::heap_size)]
|
||||
pub(super) fn nearest_disjoint_base(self, db: &'db dyn Db) -> Option<DisjointBase<'db>> {
|
||||
self.iter_mro(db)
|
||||
.filter_map(ClassBase::into_class)
|
||||
@@ -4234,7 +4233,7 @@ impl InheritanceCycle {
|
||||
/// `TypeError`s resulting from class definitions.
|
||||
///
|
||||
/// [PEP 800]: https://peps.python.org/pep-0800/
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, get_size2::GetSize, salsa::Update)]
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
||||
pub(super) struct DisjointBase<'db> {
|
||||
pub(super) class: ClassLiteral<'db>,
|
||||
pub(super) kind: DisjointBaseKind,
|
||||
@@ -4271,7 +4270,7 @@ impl<'db> DisjointBase<'db> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, get_size2::GetSize, salsa::Update)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub(super) enum DisjointBaseKind {
|
||||
/// We know the class is a disjoint base because it's either hardcoded in ty
|
||||
/// or has the `@disjoint_base` decorator.
|
||||
|
||||
@@ -1027,31 +1027,23 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
|
||||
&& rhs_ty.is_singleton(self.db)
|
||||
{
|
||||
let is_positive_check = is_positive == (ops[0] == ast::CmpOp::Is);
|
||||
let filtered: Vec<_> = union
|
||||
.elements(self.db)
|
||||
.iter()
|
||||
.filter(|elem| {
|
||||
elem.as_nominal_instance()
|
||||
.and_then(|inst| inst.tuple_spec(self.db))
|
||||
.and_then(|spec| spec.py_index(self.db, index).ok())
|
||||
.is_none_or(|el_ty| {
|
||||
if is_positive_check {
|
||||
// `is X` context: keep tuples where element could be X
|
||||
!el_ty.is_disjoint_from(self.db, rhs_ty)
|
||||
} else {
|
||||
// `is not X` context: keep tuples where element is not always X
|
||||
!el_ty.is_subtype_of(self.db, rhs_ty)
|
||||
}
|
||||
})
|
||||
})
|
||||
.copied()
|
||||
.collect();
|
||||
if filtered.len() < union.elements(self.db).len() {
|
||||
let filtered = union.filter(self.db, |elem| {
|
||||
elem.as_nominal_instance()
|
||||
.and_then(|inst| inst.tuple_spec(self.db))
|
||||
.and_then(|spec| spec.py_index(self.db, index).ok())
|
||||
.is_none_or(|el_ty| {
|
||||
if is_positive_check {
|
||||
// `is X` context: keep tuples where element could be X
|
||||
!el_ty.is_disjoint_from(self.db, rhs_ty)
|
||||
} else {
|
||||
// `is not X` context: keep tuples where element is not always X
|
||||
!el_ty.is_subtype_of(self.db, rhs_ty)
|
||||
}
|
||||
})
|
||||
});
|
||||
if filtered != Type::Union(union) {
|
||||
let place = self.expect_place(&subscript_place_expr);
|
||||
constraints.insert(
|
||||
place,
|
||||
NarrowingConstraint::regular(UnionType::from_elements(self.db, filtered)),
|
||||
);
|
||||
constraints.insert(place, NarrowingConstraint::typeguard(filtered));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1708,33 +1700,25 @@ impl<'db, 'ast> NarrowingConstraintsBuilder<'db, 'ast> {
|
||||
}
|
||||
|
||||
// Filter the union based on whether each tuple element at the index could match the rhs.
|
||||
let filtered: Vec<_> = union
|
||||
.elements(self.db)
|
||||
.iter()
|
||||
.filter(|elem| {
|
||||
elem.as_nominal_instance()
|
||||
.and_then(|inst| inst.tuple_spec(self.db))
|
||||
.and_then(|spec| spec.py_index(self.db, index).ok())
|
||||
.is_none_or(|el_ty| {
|
||||
if constrain_with_equality {
|
||||
// Keep tuples where element could be equal to rhs.
|
||||
!el_ty.is_disjoint_from(self.db, rhs_type)
|
||||
} else {
|
||||
// Keep tuples where element is not always equal to rhs.
|
||||
!el_ty.is_subtype_of(self.db, rhs_type)
|
||||
}
|
||||
})
|
||||
})
|
||||
.copied()
|
||||
.collect();
|
||||
let filtered = union.filter(self.db, |elem| {
|
||||
elem.as_nominal_instance()
|
||||
.and_then(|inst| inst.tuple_spec(self.db))
|
||||
.and_then(|spec| spec.py_index(self.db, index).ok())
|
||||
.is_none_or(|el_ty| {
|
||||
if constrain_with_equality {
|
||||
// Keep tuples where element could be equal to rhs.
|
||||
!el_ty.is_disjoint_from(self.db, rhs_type)
|
||||
} else {
|
||||
// Keep tuples where element is not always equal to rhs.
|
||||
!el_ty.is_subtype_of(self.db, rhs_type)
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Only create a constraint if we actually narrowed something.
|
||||
if filtered.len() < union.elements(self.db).len() {
|
||||
if filtered != rhs_type {
|
||||
let place = self.expect_place(&subscript_place_expr);
|
||||
Some((
|
||||
place,
|
||||
NarrowingConstraint::regular(UnionType::from_elements(self.db, filtered)),
|
||||
))
|
||||
Some((place, NarrowingConstraint::typeguard(filtered)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user