Skip to content

Commit d0ae853

Browse files
committed
slot_repr for structseq
1 parent f5ccd4f commit d0ae853

File tree

2 files changed

+35
-25
lines changed

2 files changed

+35
-25
lines changed

vm/src/protocol/object.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,9 +332,10 @@ impl PyObject {
332332
vm.with_recursion("while getting the repr of an object", || {
333333
match self.class().slots.repr.load() {
334334
Some(slot) => slot(self, vm),
335-
None => vm
336-
.call_special_method(self, identifier!(vm, __repr__), ())?
337-
.try_into_value(vm), // TODO: remove magic method call once __repr__ is fully ported to slot
335+
None => Err(vm.new_runtime_error(format!(
336+
"BUG: object of type '{}' has no __repr__ method. This is a bug in RustPython.",
337+
self.class().name()
338+
))),
338339
}
339340
})
340341
}

vm/src/types/structseq.rs

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
2-
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
3-
builtins::{PyBaseExceptionRef, PyTuple, PyTupleRef, PyType},
2+
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
3+
builtins::{PyBaseExceptionRef, PyStrRef, PyTuple, PyTupleRef, PyType},
44
class::{PyClassImpl, StaticType},
55
vm::Context,
66
};
@@ -47,31 +47,40 @@ pub trait PyStructSequence: StaticType + PyClassImpl + Sized + 'static {
4747
Ok(seq)
4848
}
4949

50-
#[pymethod]
51-
fn __repr__(zelf: PyRef<PyTuple>, vm: &VirtualMachine) -> PyResult<String> {
50+
#[pyslot]
51+
fn slot_repr(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyStrRef> {
52+
let zelf = zelf
53+
.downcast_ref::<PyTuple>()
54+
.ok_or_else(|| vm.new_type_error("unexpected payload for __repr__"))?;
55+
5256
let format_field = |(value, name): (&PyObjectRef, _)| {
5357
let s = value.repr(vm)?;
5458
Ok(format!("{name}={s}"))
5559
};
56-
let (body, suffix) = if let Some(_guard) =
57-
rustpython_vm::recursion::ReprGuard::enter(vm, zelf.as_object())
58-
{
59-
if Self::REQUIRED_FIELD_NAMES.len() == 1 {
60-
let value = zelf.first().unwrap();
61-
let formatted = format_field((value, Self::REQUIRED_FIELD_NAMES[0]))?;
62-
(formatted, ",")
60+
let (body, suffix) =
61+
if let Some(_guard) = rustpython_vm::recursion::ReprGuard::enter(vm, zelf.as_ref()) {
62+
if Self::REQUIRED_FIELD_NAMES.len() == 1 {
63+
let value = zelf.first().unwrap();
64+
let formatted = format_field((value, Self::REQUIRED_FIELD_NAMES[0]))?;
65+
(formatted, ",")
66+
} else {
67+
let fields: PyResult<Vec<_>> = zelf
68+
.iter()
69+
.zip(Self::REQUIRED_FIELD_NAMES.iter().copied())
70+
.map(format_field)
71+
.collect();
72+
(fields?.join(", "), "")
73+
}
6374
} else {
64-
let fields: PyResult<Vec<_>> = zelf
65-
.iter()
66-
.zip(Self::REQUIRED_FIELD_NAMES.iter().copied())
67-
.map(format_field)
68-
.collect();
69-
(fields?.join(", "), "")
70-
}
71-
} else {
72-
(String::new(), "...")
73-
};
74-
Ok(format!("{}({}{})", Self::TP_NAME, body, suffix))
75+
(String::new(), "...")
76+
};
77+
let repr_str = format!("{}({}{})", Self::TP_NAME, body, suffix);
78+
Ok(vm.ctx.new_str(repr_str))
79+
}
80+
81+
#[pymethod]
82+
fn __repr__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStrRef> {
83+
Self::slot_repr(&zelf, vm)
7584
}
7685

7786
#[pymethod]

0 commit comments

Comments
 (0)