diff --git a/extra_tests/snippets/builtin_type.py b/extra_tests/snippets/builtin_type.py index 923028f2cd..820ee36615 100644 --- a/extra_tests/snippets/builtin_type.py +++ b/extra_tests/snippets/builtin_type.py @@ -595,3 +595,15 @@ def my_repr_func(): # https://github.com/RustPython/RustPython/issues/3100 assert issubclass(types.BuiltinMethodType, types.BuiltinFunctionType) + +assert type.__dict__["__dict__"].__objclass__ is type +assert ( + type(type(type.__dict__["__dict__"]).__objclass__).__name__ == "member_descriptor" +) + + +class A(type): + pass + + +assert "__dict__" not in A.__dict__ diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index ded0ae4b3a..1e18d6fd63 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -936,9 +936,9 @@ impl Constructor for PyType { return Err(vm.new_value_error("type name must not contain null characters")); } - let (metatype, base, bases) = if bases.is_empty() { + let (metatype, base, bases, base_is_type) = if bases.is_empty() { let base = vm.ctx.types.object_type.to_owned(); - (metatype, base.clone(), vec![base]) + (metatype, base.clone(), vec![base], false) } else { let bases = bases .iter() @@ -972,8 +972,9 @@ impl Constructor for PyType { }; let base = best_base(&bases, vm)?; + let base_is_type = base.is(vm.ctx.types.type_type); - (metatype, base.to_owned(), bases) + (metatype, base.to_owned(), bases, base_is_type) }; let qualname = dict @@ -1021,17 +1022,21 @@ impl Constructor for PyType { // All *classes* should have a dict. Exceptions are *instances* of // classes that define __slots__ and instances of built-in classes // (with exceptions, e.g function) - let __dict__ = identifier!(vm, __dict__); - attributes.entry(__dict__).or_insert_with(|| { - vm.ctx - .new_static_getset( - "__dict__", - vm.ctx.types.type_type, - subtype_get_dict, - subtype_set_dict, - ) - .into() - }); + // Also, type subclasses don't need their own __dict__ descriptor + // since they inherit it from type + if !base_is_type { + let __dict__ = identifier!(vm, __dict__); + attributes.entry(__dict__).or_insert_with(|| { + vm.ctx + .new_static_getset( + "__dict__", + vm.ctx.types.type_type, + subtype_get_dict, + subtype_set_dict, + ) + .into() + }); + } // TODO: Flags is currently initialized with HAS_DICT. Should be // updated when __slots__ are supported (toggling the flag off if pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy