From 83656b56cb1b18531ed16584146156f2721e557d Mon Sep 17 00:00:00 2001 From: Jeongseop Lim Date: Sat, 8 Aug 2026 05:53:29 +0900 Subject: [PATCH] Reject a fifth argument to property() PropertyArgs declared a fifth positional-or-keyword field, name, so the derived arity was 0..=5 and property(None, None, None, None, None) built a property object with the fifth argument stored in the __name__ slot. CPython's property.__init__ is Argument Clinic generated with maxpos = 4 and the keyword list {fget, fset, fdel, doc}, so it rejects both that call and property(name='x'). Drop the field. Nothing passed it: clone_property_with always supplied None and copies the name separately, and the name slot is still filled by __set_name__ and the __name__ setter. Assisted-by: Claude Code:claude-opus-5 --- crates/vm/src/builtins/property.rs | 6 +----- extra_tests/snippets/builtin_property.py | 7 +++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/vm/src/builtins/property.rs b/crates/vm/src/builtins/property.rs index cff5a8a60d0..65ae48222fa 100644 --- a/crates/vm/src/builtins/property.rs +++ b/crates/vm/src/builtins/property.rs @@ -1,7 +1,7 @@ /*! Python `property` descriptor class. */ -use super::{PyStrRef, PyType}; +use super::PyType; use crate::common::lock::PyRwLock; use crate::function::{IntoFuncArgs, PosArgs}; use crate::{ @@ -41,8 +41,6 @@ pub struct PropertyArgs { fdel: Option, #[pyarg(any, default)] doc: Option, - #[pyarg(any, default)] - name: Option, } impl GetDescriptor for PyProperty { @@ -221,7 +219,6 @@ impl PyProperty { fset: new_setter.or_else(|| zelf.fset()), fdel: new_deleter.or_else(|| zelf.fdel()), doc, - name: None, }; // Create new property using py_new and init @@ -401,7 +398,6 @@ impl Initializer for PyProperty { *zelf.getter.write() = args.fget; *zelf.setter.write() = args.fset; *zelf.deleter.write() = args.fdel; - *zelf.name.write() = args.name.map(|a| a.as_object().to_owned()); zelf.getter_doc.store(getter_doc, Ordering::Relaxed); Ok(()) diff --git a/extra_tests/snippets/builtin_property.py b/extra_tests/snippets/builtin_property.py index de64e526228..397d41fb075 100644 --- a/extra_tests/snippets/builtin_property.py +++ b/extra_tests/snippets/builtin_property.py @@ -85,3 +85,10 @@ def foo(self): p2 = property("a", doc="pdoc") # assert p2.__doc__ == 'pdoc' + + +# property() takes at most four arguments, and `name` is not one of them: +# the name slot is filled by __set_name__ and the __name__ setter instead. +assert_raises(TypeError, property, None, None, None, None, None) +assert_raises(TypeError, property, "a", "b", "c", "d", "e") +assert_raises(TypeError, property, name="x")