Skip to content

Commit 3574d2c

Browse files
committed
wip
1 parent 2a3a5ab commit 3574d2c

File tree

1 file changed

+58
-25
lines changed

1 file changed

+58
-25
lines changed

vm/src/builtins/type.rs

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -972,26 +972,38 @@ impl Constructor for PyType {
972972
if let Some(ref slots) = heaptype_slots {
973973
let mut offset = base_member_count;
974974
for member in slots.as_slice() {
975-
let member_def = PyMemberDef {
976-
name: member.to_string(),
977-
kind: MemberKind::ObjectEx,
978-
getter: MemberGetter::Offset(offset),
979-
setter: MemberSetter::Offset(offset),
980-
doc: None,
981-
};
982-
let member_descriptor: PyRef<PyMemberDescriptor> =
983-
vm.ctx.new_pyref(PyMemberDescriptor {
984-
common: PyDescriptorOwned {
985-
typ: typ.clone(),
986-
name: vm.ctx.intern_str(member.as_str()),
987-
qualname: PyRwLock::new(None),
988-
},
989-
member: member_def,
990-
});
991-
992975
let attr_name = vm.ctx.intern_str(member.to_string());
993-
if !typ.has_attr(attr_name) {
994-
typ.set_attr(attr_name, member_descriptor.into());
976+
977+
// Special handling for __dict__ slot - use getset_descriptor instead of member_descriptor
978+
if member.as_str() == "__dict__" {
979+
if !typ.has_attr(attr_name) {
980+
let dict_descriptor = unsafe {
981+
vm.ctx
982+
.new_getset("__dict__", &typ, subtype_get_dict, subtype_set_dict)
983+
};
984+
typ.set_attr(attr_name, dict_descriptor.into());
985+
}
986+
} else {
987+
let member_def = PyMemberDef {
988+
name: member.to_string(),
989+
kind: MemberKind::ObjectEx,
990+
getter: MemberGetter::Offset(offset),
991+
setter: MemberSetter::Offset(offset),
992+
doc: None,
993+
};
994+
let member_descriptor: PyRef<PyMemberDescriptor> =
995+
vm.ctx.new_pyref(PyMemberDescriptor {
996+
common: PyDescriptorOwned {
997+
typ: typ.clone(),
998+
name: vm.ctx.intern_str(member.as_str()),
999+
qualname: PyRwLock::new(None),
1000+
},
1001+
member: member_def,
1002+
});
1003+
1004+
if !typ.has_attr(attr_name) {
1005+
typ.set_attr(attr_name, member_descriptor.into());
1006+
}
9951007
}
9961008

9971009
offset += 1;
@@ -1005,13 +1017,34 @@ impl Constructor for PyType {
10051017
// (with exceptions, e.g function)
10061018
// Also, type subclasses don't need their own __dict__ descriptor
10071019
// since they inherit it from type
1008-
if !inherits_from_type {
1020+
// Additionally, if __slots__ contains __dict__, don't add descriptor
1021+
// as the slot handles __dict__ directly
1022+
let has_dict_slot = attributes
1023+
.get(identifier!(vm, __slots__))
1024+
.and_then(|slots| {
1025+
if let Ok(tuple) = slots.clone().downcast::<PyTuple>() {
1026+
Some(tuple.iter().any(|item| {
1027+
item.downcast_ref::<PyStr>()
1028+
.map(|s| s.as_str() == "__dict__")
1029+
.unwrap_or(false)
1030+
}))
1031+
} else if let Ok(string) = slots.clone().downcast::<PyStr>() {
1032+
Some(string.as_str() == "__dict__")
1033+
} else {
1034+
None
1035+
}
1036+
})
1037+
.unwrap_or(false);
1038+
1039+
if !inherits_from_type && !has_dict_slot {
10091040
let __dict__ = identifier!(vm, __dict__);
1010-
attributes.entry(__dict__).or_insert_with(|| unsafe {
1011-
vm.ctx
1012-
.new_getset("__dict__", &typ, subtype_get_dict, subtype_set_dict)
1013-
.into()
1014-
});
1041+
if !attributes.contains_key(__dict__) {
1042+
attributes.insert(__dict__, unsafe {
1043+
vm.ctx
1044+
.new_getset("__dict__", &typ, subtype_get_dict, subtype_set_dict)
1045+
.into()
1046+
});
1047+
}
10151048
}
10161049

10171050
if let Some(cell) = attributes.get(identifier!(vm, __classcell__)) {

0 commit comments

Comments
 (0)