Skip to content

Commit 8ab7aa2

Browse files
authored
type.__dict__ (#5957)
1 parent 16aaad7 commit 8ab7aa2

File tree

2 files changed

+31
-14
lines changed

2 files changed

+31
-14
lines changed

extra_tests/snippets/builtin_type.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,15 @@ 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 (
601+
type(type(type.__dict__["__dict__"]).__objclass__).__name__ == "member_descriptor"
602+
)
603+
604+
605+
class A(type):
606+
pass
607+
608+
609+
assert "__dict__" not in A.__dict__

vm/src/builtins/type.rs

Lines changed: 19 additions & 14 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
@@ -1021,17 +1022,21 @@ impl Constructor for PyType {
10211022
// All *classes* should have a dict. Exceptions are *instances* of
10221023
// classes that define __slots__ and instances of built-in classes
10231024
// (with exceptions, e.g function)
1024-
let __dict__ = identifier!(vm, __dict__);
1025-
attributes.entry(__dict__).or_insert_with(|| {
1026-
vm.ctx
1027-
.new_static_getset(
1028-
"__dict__",
1029-
vm.ctx.types.type_type,
1030-
subtype_get_dict,
1031-
subtype_set_dict,
1032-
)
1033-
.into()
1034-
});
1025+
// Also, type subclasses don't need their own __dict__ descriptor
1026+
// since they inherit it from type
1027+
if !base_is_type {
1028+
let __dict__ = identifier!(vm, __dict__);
1029+
attributes.entry(__dict__).or_insert_with(|| {
1030+
vm.ctx
1031+
.new_static_getset(
1032+
"__dict__",
1033+
vm.ctx.types.type_type,
1034+
subtype_get_dict,
1035+
subtype_set_dict,
1036+
)
1037+
.into()
1038+
});
1039+
}
10351040

10361041
// TODO: Flags is currently initialized with HAS_DICT. Should be
10371042
// updated when __slots__ are supported (toggling the flag off if

0 commit comments

Comments
 (0)