From 5d196a58e974d2306ed9adcb1c883c7f4667c48d Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sat, 28 Jun 2025 03:00:53 +0900 Subject: [PATCH 1/2] type.__dict__ --- vm/src/builtins/type.rs | 46 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index ded0ae4b3a..010f4d0dae 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -1018,21 +1018,6 @@ impl Constructor for PyType { attributes.insert(identifier!(vm, __hash__), vm.ctx.none.clone().into()); } - // 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() - }); - // TODO: Flags is currently initialized with HAS_DICT. Should be // updated when __slots__ are supported (toggling the flag off if // a class has __slots__ defined). @@ -1124,15 +1109,28 @@ impl Constructor for PyType { } } - if let Some(cell) = typ.attributes.write().get(identifier!(vm, __classcell__)) { - let cell = PyCellRef::try_from_object(vm, cell.clone()).map_err(|_| { - vm.new_type_error(format!( - "__classcell__ must be a nonlocal cell, not {}", - cell.class().name() - )) - })?; - cell.set(Some(typ.clone().into())); - }; + { + let mut attributes = typ.attributes.write(); + // 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(|| unsafe { + vm.ctx + .new_getset("__dict__", &typ, subtype_get_dict, subtype_set_dict) + .into() + }); + + if let Some(cell) = attributes.get(identifier!(vm, __classcell__)) { + let cell = PyCellRef::try_from_object(vm, cell.clone()).map_err(|_| { + vm.new_type_error(format!( + "__classcell__ must be a nonlocal cell, not {}", + cell.class().name() + )) + })?; + cell.set(Some(typ.clone().into())); + }; + } // avoid deadlock let attributes = typ From eeaf78fad9e8c1ee8440e22f10d4eb0241554a10 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Sat, 28 Jun 2025 11:39:50 +0900 Subject: [PATCH 2/2] fix --- extra_tests/snippets/builtin_type.py | 12 ++++++ vm/src/builtins/type.rs | 57 ++++++++++++++++------------ 2 files changed, 44 insertions(+), 25 deletions(-) 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 010f4d0dae..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 @@ -1018,6 +1019,25 @@ impl Constructor for PyType { attributes.insert(identifier!(vm, __hash__), vm.ctx.none.clone().into()); } + // 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) + // 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 // a class has __slots__ defined). @@ -1109,28 +1129,15 @@ impl Constructor for PyType { } } - { - let mut attributes = typ.attributes.write(); - // 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(|| unsafe { - vm.ctx - .new_getset("__dict__", &typ, subtype_get_dict, subtype_set_dict) - .into() - }); - - if let Some(cell) = attributes.get(identifier!(vm, __classcell__)) { - let cell = PyCellRef::try_from_object(vm, cell.clone()).map_err(|_| { - vm.new_type_error(format!( - "__classcell__ must be a nonlocal cell, not {}", - cell.class().name() - )) - })?; - cell.set(Some(typ.clone().into())); - }; - } + if let Some(cell) = typ.attributes.write().get(identifier!(vm, __classcell__)) { + let cell = PyCellRef::try_from_object(vm, cell.clone()).map_err(|_| { + vm.new_type_error(format!( + "__classcell__ must be a nonlocal cell, not {}", + cell.class().name() + )) + })?; + cell.set(Some(typ.clone().into())); + }; // avoid deadlock let attributes = typ 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