Skip to content

Commit e6975f9

Browse files
committed
Handle __classcell__ and __classdictcell__ in type.__new__
- Remove __classcell__ from class dict after setting the cell value - Add __classdictcell__ handling: set cell to class namespace dict, then remove from class dict - Register __classdictcell__ identifier - Use LoadClosure instead of LoadDeref for __classdictcell__ emission - Reorder MakeFunctionFlag bits to match CPython - Run ruff format on scripts
1 parent 93c1ea6 commit e6975f9

File tree

4 files changed

+37
-16
lines changed

4 files changed

+37
-16
lines changed

crates/codegen/src/compile.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4693,7 +4693,13 @@ impl Compiler {
46934693
// Store __classdictcell__ if __classdict__ is a cell variable
46944694
if self.current_symbol_table().needs_classdict {
46954695
let classdict_idx = self.get_cell_var_index("__classdict__")?;
4696-
emit!(self, Instruction::LoadDeref { i: classdict_idx });
4696+
// Use LoadClosure to get the cell object itself (not the value inside)
4697+
emit!(
4698+
self,
4699+
PseudoInstruction::LoadClosure {
4700+
i: classdict_idx
4701+
}
4702+
);
46974703
let classdictcell = self.name("__classdictcell__");
46984704
emit!(
46994705
self,

crates/compiler-core/src/bytecode/oparg.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -385,13 +385,13 @@ bitflagset::bitflag! {
385385
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
386386
#[repr(u8)]
387387
pub enum MakeFunctionFlag {
388-
Closure = 0,
389-
Annotations = 1,
390-
KwOnlyDefaults = 2,
391-
Defaults = 3,
392-
TypeParams = 4,
388+
Defaults = 0,
389+
KwOnlyDefaults = 1,
390+
Annotations = 2,
391+
Closure = 3,
393392
/// PEP 649: __annotate__ function closure (instead of __annotations__ dict)
394-
Annotate = 5,
393+
Annotate = 4,
394+
TypeParams = 5,
395395
}
396396
}
397397

crates/vm/src/builtins/type.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,15 +2133,29 @@ impl Constructor for PyType {
21332133
}
21342134
}
21352135

2136-
if let Some(cell) = typ.attributes.write().get(identifier!(vm, __classcell__)) {
2137-
let cell = PyCellRef::try_from_object(vm, cell.clone()).map_err(|_| {
2138-
vm.new_type_error(format!(
2139-
"__classcell__ must be a nonlocal cell, not {}",
2140-
cell.class().name()
2141-
))
2142-
})?;
2143-
cell.set(Some(typ.clone().into()));
2144-
};
2136+
{
2137+
let mut attrs = typ.attributes.write();
2138+
if let Some(cell) = attrs.get(identifier!(vm, __classcell__)) {
2139+
let cell = PyCellRef::try_from_object(vm, cell.clone()).map_err(|_| {
2140+
vm.new_type_error(format!(
2141+
"__classcell__ must be a nonlocal cell, not {}",
2142+
cell.class().name()
2143+
))
2144+
})?;
2145+
cell.set(Some(typ.clone().into()));
2146+
attrs.shift_remove(identifier!(vm, __classcell__));
2147+
}
2148+
if let Some(cell) = attrs.get(identifier!(vm, __classdictcell__)) {
2149+
let cell = PyCellRef::try_from_object(vm, cell.clone()).map_err(|_| {
2150+
vm.new_type_error(format!(
2151+
"__classdictcell__ must be a nonlocal cell, not {}",
2152+
cell.class().name()
2153+
))
2154+
})?;
2155+
cell.set(Some(dict.clone().into()));
2156+
attrs.shift_remove(identifier!(vm, __classdictcell__));
2157+
}
2158+
}
21452159

21462160
// All *classes* should have a dict. Exceptions are *instances* of
21472161
// classes that define __slots__ and instances of built-in classes

crates/vm/src/vm/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ declare_const_name! {
118118
__class__,
119119
__class_getitem__,
120120
__classcell__,
121+
__classdictcell__,
121122
__complex__,
122123
__contains__,
123124
__copy__,

0 commit comments

Comments
 (0)