Skip to content

Commit 9a18d90

Browse files
committed
Expose descriptor names and owner types as members
method_descriptor, classmethod_descriptor, and wrapper_descriptor expose `__objclass__` and `__name__` as readonly members, and method-wrapper exposes `__self__` as a readonly member. The separate `objclass` field of method and classmethod descriptors always equaled `common.typ` and is removed. Assisted-by: Grok:4.7 Assisted-by: Claude:claude-opus-5-5
1 parent 57fb4bf commit 9a18d90

2 files changed

Lines changed: 12 additions & 43 deletions

File tree

‎crates/vm/src/builtins/descriptor.rs‎

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ pub struct PyDescriptorOwned {
3333

3434
#[pyclass(name = "method_descriptor", module = false)]
3535
pub struct PyMethodDescriptor {
36+
#[pymember(readonly, name = "__objclass__", path = "typ")]
37+
#[pymember(readonly, name = "__name__", path = "name")]
3638
pub common: PyDescriptor,
3739
pub method: &'static PyMethodDef,
3840
// vectorcall: vector_call_func,
39-
pub objclass: &'static Py<PyType>, // TODO: move to tp_members
4041
/// Prevent HeapMethodDef from being freed while this descriptor references it
4142
pub(crate) _method_def_owner: Option<PyObjectRef>,
4243
}
@@ -50,7 +51,6 @@ impl PyMethodDescriptor {
5051
qualname: PyRwLock::new(None),
5152
},
5253
method,
53-
objclass: typ,
5454
_method_def_owner: None,
5555
}
5656
}
@@ -127,11 +127,6 @@ impl PyMethodDescriptor {
127127
flags(METHOD_DESCRIPTOR, DISALLOW_INSTANTIATION)
128128
)]
129129
impl PyMethodDescriptor {
130-
#[pygetset]
131-
const fn __name__(&self) -> &'static PyStrInterned {
132-
self.common.name
133-
}
134-
135130
#[pygetset]
136131
fn __qualname__(&self) -> String {
137132
format!("{}.{}", self.common.typ.name(), self.common.name)
@@ -149,11 +144,6 @@ impl PyMethodDescriptor {
149144
type_::get_text_signature_from_internal_doc(self.method.name, doc)
150145
}
151146

152-
#[pygetset]
153-
fn __objclass__(&self) -> PyTypeRef {
154-
self.objclass.to_owned()
155-
}
156-
157147
#[pymethod]
158148
fn __reduce__(
159149
&self,
@@ -179,9 +169,10 @@ impl Representable for PyMethodDescriptor {
179169
/// METH_CLASS descriptors. Same layout as method_descriptor; a distinct type.
180170
#[pyclass(name = "classmethod_descriptor", module = false)]
181171
pub struct PyClassMethodDescriptor {
172+
#[pymember(readonly, name = "__objclass__", path = "typ")]
173+
#[pymember(readonly, name = "__name__", path = "name")]
182174
pub common: PyDescriptor,
183175
pub method: &'static PyMethodDef,
184-
pub objclass: &'static Py<PyType>,
185176
pub(crate) _method_def_owner: Option<PyObjectRef>,
186177
}
187178

@@ -194,7 +185,6 @@ impl PyClassMethodDescriptor {
194185
qualname: PyRwLock::new(None),
195186
},
196187
method,
197-
objclass: typ,
198188
_method_def_owner: None,
199189
}
200190
}
@@ -286,11 +276,6 @@ impl Callable for PyClassMethodDescriptor {
286276
flags(DISALLOW_INSTANTIATION)
287277
)]
288278
impl PyClassMethodDescriptor {
289-
#[pygetset]
290-
const fn __name__(&self) -> &'static PyStrInterned {
291-
self.common.name
292-
}
293-
294279
#[pygetset]
295280
fn __qualname__(&self) -> String {
296281
format!("{}.{}", self.common.typ.name(), self.common.name)
@@ -307,11 +292,6 @@ impl PyClassMethodDescriptor {
307292
let doc = self.method.doc?;
308293
type_::get_text_signature_from_internal_doc(self.method.name, doc)
309294
}
310-
311-
#[pygetset]
312-
fn __objclass__(&self) -> PyTypeRef {
313-
self.objclass.to_owned()
314-
}
315295
}
316296

317297
impl Representable for PyClassMethodDescriptor {
@@ -379,6 +359,7 @@ impl ObjectMember for crate::object::PyAtomicRef<PyObject> {}
379359
impl ObjectMember for crate::object::PyAtomicRef<Option<PyObject>> {}
380360
impl<T: PyPayload> ObjectMember for crate::object::PyAtomicRef<Option<T>> {}
381361
impl ObjectMember for &'static crate::builtins::PyStrInterned {}
362+
impl<T: PyPayload> ObjectMember for &'static Py<T> {}
382363

383364
/// A writable object member. The cell owns the pointer and updates it atomically.
384365
#[doc(hidden)]
@@ -1165,7 +1146,9 @@ fn parse_buffer_flags(
11651146
#[pyclass(name = "wrapper_descriptor", module = false)]
11661147
#[derive(Debug)]
11671148
pub(crate) struct PyWrapper {
1149+
#[pymember(readonly, name = "__objclass__")]
11681150
pub typ: &'static Py<PyType>,
1151+
#[pymember(readonly, name = "__name__")]
11691152
pub name: &'static PyStrInterned,
11701153
pub wrapped: SlotFunc,
11711154
pub doc: Option<&'static str>,
@@ -1223,21 +1206,11 @@ impl Callable for PyWrapper {
12231206
flags(DISALLOW_INSTANTIATION)
12241207
)]
12251208
impl PyWrapper {
1226-
#[pygetset]
1227-
fn __name__(&self) -> &'static PyStrInterned {
1228-
self.name
1229-
}
1230-
12311209
#[pygetset]
12321210
fn __qualname__(&self) -> String {
12331211
format!("{}.{}", self.typ.name(), self.name)
12341212
}
12351213

1236-
#[pygetset]
1237-
fn __objclass__(&self) -> PyTypeRef {
1238-
self.typ.to_owned()
1239-
}
1240-
12411214
#[pygetset]
12421215
fn __doc__(&self) -> Option<&'static str> {
12431216
let doc = self.doc?;
@@ -1272,6 +1245,7 @@ impl Representable for PyWrapper {
12721245
#[derive(Debug)]
12731246
pub(crate) struct PyMethodWrapper {
12741247
pub wrapper: PyRef<PyWrapper>,
1248+
#[pymember(readonly, name = "__self__")]
12751249
#[pytraverse(skip)]
12761250
pub obj: PyObjectRef,
12771251
}
@@ -1304,11 +1278,6 @@ impl Callable for PyMethodWrapper {
13041278
flags(DISALLOW_INSTANTIATION)
13051279
)]
13061280
impl PyMethodWrapper {
1307-
#[pygetset]
1308-
fn __self__(&self) -> PyObjectRef {
1309-
self.obj.clone()
1310-
}
1311-
13121281
#[pygetset]
13131282
fn __name__(&self) -> &'static PyStrInterned {
13141283
self.wrapper.name

‎crates/vm/src/frame.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7047,7 +7047,7 @@ impl ExecutingFrame<'_> {
70477047
.localsplus
70487048
.stack_index(self_index)
70497049
.as_ref()
7050-
.is_some_and(|self_obj| self_obj.class().is(descr.objclass))
7050+
.is_some_and(|self_obj| self_obj.class().is(descr.common.typ))
70517051
{
70527052
let func = descr.method.func;
70537053
let callee = Callee::named(descr.method.name).with_instance_arg(true);
@@ -7088,7 +7088,7 @@ impl ExecutingFrame<'_> {
70887088
.localsplus
70897089
.stack_index(self_index)
70907090
.as_ref()
7091-
.is_some_and(|self_obj| self_obj.class().is(descr.objclass))
7091+
.is_some_and(|self_obj| self_obj.class().is(descr.common.typ))
70927092
{
70937093
let func = descr.method.func;
70947094
let callee = Callee::named(descr.method.name).with_instance_arg(true);
@@ -7129,7 +7129,7 @@ impl ExecutingFrame<'_> {
71297129
.localsplus
71307130
.stack_index(self_index)
71317131
.as_ref()
7132-
.is_some_and(|self_obj| self_obj.class().is(descr.objclass))
7132+
.is_some_and(|self_obj| self_obj.class().is(descr.common.typ))
71337133
{
71347134
let func = descr.method.func;
71357135
let callee = Callee::named(descr.method.name).with_instance_arg(true);
@@ -7235,7 +7235,7 @@ impl ExecutingFrame<'_> {
72357235
.localsplus
72367236
.stack_index(self_index)
72377237
.as_ref()
7238-
.is_some_and(|self_obj| self_obj.class().is(descr.objclass))
7238+
.is_some_and(|self_obj| self_obj.class().is(descr.common.typ))
72397239
{
72407240
let func = descr.method.func;
72417241
let callee = Callee::named(descr.method.name).with_instance_arg(true);

0 commit comments

Comments
 (0)