Skip to content

Commit 51794e4

Browse files
committed
fix
1 parent 5d196a5 commit 51794e4

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

extra_tests/snippets/builtin_type.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,10 @@ def my_repr_func():
595595

596596
# https://github.com/RustPython/RustPython/issues/3100
597597
assert issubclass(types.BuiltinMethodType, types.BuiltinFunctionType)
598+
599+
assert type.__dict__['__dict__'].__objclass__ is type
600+
assert type(type(type.__dict__['__dict__']).__objclass__).__name__ == 'member_descriptor'
601+
602+
class A(type): pass
603+
604+
assert '__dict__' not in A.__dict__

vm/src/builtins/type.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -936,9 +936,9 @@ impl Constructor for PyType {
936936
return Err(vm.new_value_error("type name must not contain null characters"));
937937
}
938938

939-
let (metatype, base, bases) = if bases.is_empty() {
939+
let (metatype, base, bases, base_is_type) = if bases.is_empty() {
940940
let base = vm.ctx.types.object_type.to_owned();
941-
(metatype, base.clone(), vec![base])
941+
(metatype, base.clone(), vec![base], false)
942942
} else {
943943
let bases = bases
944944
.iter()
@@ -972,8 +972,9 @@ impl Constructor for PyType {
972972
};
973973

974974
let base = best_base(&bases, vm)?;
975+
let base_is_type = base.is(vm.ctx.types.type_type);
975976

976-
(metatype, base.to_owned(), bases)
977+
(metatype, base.to_owned(), bases, base_is_type)
977978
};
978979

979980
let qualname = dict
@@ -1114,12 +1115,16 @@ impl Constructor for PyType {
11141115
// All *classes* should have a dict. Exceptions are *instances* of
11151116
// classes that define __slots__ and instances of built-in classes
11161117
// (with exceptions, e.g function)
1117-
let __dict__ = identifier!(vm, __dict__);
1118-
attributes.entry(__dict__).or_insert_with(|| unsafe {
1119-
vm.ctx
1120-
.new_getset("__dict__", &typ, subtype_get_dict, subtype_set_dict)
1121-
.into()
1122-
});
1118+
// Also, type subclasses don't need their own __dict__ descriptor
1119+
// since they inherit it from type
1120+
if !base_is_type {
1121+
let __dict__ = identifier!(vm, __dict__);
1122+
attributes.entry(__dict__).or_insert_with(|| unsafe {
1123+
vm.ctx
1124+
.new_getset("__dict__", &typ, subtype_get_dict, subtype_set_dict)
1125+
.into()
1126+
});
1127+
}
11231128

11241129
if let Some(cell) = attributes.get(identifier!(vm, __classcell__)) {
11251130
let cell = PyCellRef::try_from_object(vm, cell.clone()).map_err(|_| {

0 commit comments

Comments
 (0)