Updated changes to work with new Place type

This commit is contained in:
Blair Allan 2025-10-20 18:08:11 +05:00
parent 80468d15e8
commit f1b356ceb3

View file

@ -3531,8 +3531,9 @@ impl<'db> ClassLiteral<'db> {
// The attribute is not *declared* in the class body. It could still be declared/bound // The attribute is not *declared* in the class body. It could still be declared/bound
// in a method. // in a method.
let result = Self::implicit_attribute(db, body_scope, name, MethodDecorator::None); let result =
self.apply_slots_constraints(db, name, result) Self::implicit_attribute(db, body_scope, name, MethodDecorator::None);
self.apply_slots_constraints(db, name, result.inner)
} }
} }
} else { } else {
@ -3540,7 +3541,7 @@ impl<'db> ClassLiteral<'db> {
// It could still be implicitly defined in a method. // It could still be implicitly defined in a method.
let result = Self::implicit_attribute(db, body_scope, name, MethodDecorator::None); let result = Self::implicit_attribute(db, body_scope, name, MethodDecorator::None);
self.apply_slots_constraints(db, name, result) self.apply_slots_constraints(db, name, result.inner)
} }
} }
@ -5527,14 +5528,15 @@ impl<'db> ClassLiteral<'db> {
/// Extract the names of attributes defined in __slots__ as a set of strings. /// Extract the names of attributes defined in __slots__ as a set of strings.
/// Returns None if __slots__ is not defined, empty, or dynamic. /// Returns None if __slots__ is not defined, empty, or dynamic.
pub(super) fn slots_members(self, db: &'db dyn Db) -> Option<FxHashSet<String>> { pub(super) fn slots_members(self, db: &'db dyn Db) -> Option<FxHashSet<String>> {
let Place::Type(slots_ty, bound) = self let Place::Defined(slots_ty, _, definedness) = self
.own_class_member(db, self.generic_context(db), None, "__slots__") .own_class_member(db, self.generic_context(db), None, "__slots__")
.inner
.place .place
else { else {
return None; return None;
}; };
if matches!(bound, Boundness::PossiblyUnbound) { if matches!(definedness, Definedness::PossiblyUndefined) {
return None; return None;
} }
@ -5579,24 +5581,31 @@ impl<'db> ClassLiteral<'db> {
db: &'db dyn Db, db: &'db dyn Db,
name: &str, name: &str,
result: PlaceAndQualifiers<'db>, result: PlaceAndQualifiers<'db>,
) -> PlaceAndQualifiers<'db> { ) -> Member<'db> {
// TODO: This function will be extended to support: // TODO: This function will be extended to support:
// - Inheritance: Check slots across the MRO chain // - Inheritance: Check slots across the MRO chain
// - `__dict__` special case: Allow dynamic attributes when `__dict__` is in slots // - `__dict__` special case: Allow dynamic attributes when `__dict__` is in slots
if let Some(slots) = self.slots_members(db) { if let Some(slots) = self.slots_members(db) {
if slots.contains(name) { if slots.contains(name) {
// Attribute is in __slots__, so it's allowed even if not found elsewhere // Attribute is in __slots__, so it's allowed even if not found elsewhere
if result.place.is_unbound() { if result.place.is_undefined() {
// Return as possibly unbound since it's declared but not necessarily initialized // Return as possibly unbound since it's declared but not necessarily initialized
return Place::Type(Type::unknown(), Boundness::PossiblyUnbound).into(); return Member {
inner: Place::Defined(
Type::unknown(),
TypeOrigin::Inferred,
Definedness::PossiblyUndefined,
)
.into(),
};
} }
return result; return Member { inner: result };
} }
// Attribute is not in __slots__ // Attribute is not in __slots__
return Place::Unbound.into(); return Member::unbound();
} }
result Member { inner: result }
} }
} }