Skip to content

Commit 8a5182a

Browse files
committed
make get_method_or_type_error() error message lazy
1 parent 3bfd66b commit 8a5182a

8 files changed

Lines changed: 34 additions & 50 deletions

File tree

vm/src/builtins.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,9 @@ use crate::vm::VirtualMachine;
3131
use crate::stdlib::io::io_open;
3232

3333
fn builtin_abs(x: PyObjectRef, vm: &VirtualMachine) -> PyResult {
34-
let method = vm.get_method_or_type_error(
35-
x.clone(),
36-
"__abs__",
37-
format!("bad operand type for abs(): '{}'", x.class().name),
38-
)?;
34+
let method = vm.get_method_or_type_error(x.clone(), "__abs__", || {
35+
format!("bad operand type for abs(): '{}'", x.class().name)
36+
})?;
3937
vm.invoke(method, PyFuncArgs::new(vec![], vec![]))
4038
}
4139

@@ -369,11 +367,9 @@ fn builtin_iter(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
369367

370368
fn builtin_len(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
371369
arg_check!(vm, args, required = [(obj, None)]);
372-
let method = vm.get_method_or_type_error(
373-
obj.clone(),
374-
"__len__",
375-
format!("object of type '{}' has no len()", obj.class().name),
376-
)?;
370+
let method = vm.get_method_or_type_error(obj.clone(), "__len__", || {
371+
format!("object of type '{}' has no len()", obj.class().name)
372+
})?;
377373
vm.invoke(method, PyFuncArgs::default())
378374
}
379375

@@ -671,11 +667,9 @@ fn builtin_reversed(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
671667
arg_check!(vm, args, required = [(obj, None)]);
672668

673669
// TODO: fallback to using __len__ and __getitem__, if object supports sequence protocol
674-
let method = vm.get_method_or_type_error(
675-
obj.clone(),
676-
"__reversed__",
677-
format!("argument to reversed() must be a sequence"),
678-
)?;
670+
let method = vm.get_method_or_type_error(obj.clone(), "__reversed__", || {
671+
format!("argument to reversed() must be a sequence")
672+
})?;
679673
vm.invoke(method, PyFuncArgs::default())
680674
}
681675

vm/src/obj/objfloat.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -557,14 +557,12 @@ pub fn make_float(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<f64> {
557557
if objtype::isinstance(obj, &vm.ctx.float_type()) {
558558
Ok(get_value(obj))
559559
} else {
560-
let method = vm.get_method_or_type_error(
561-
obj.clone(),
562-
"__float__",
560+
let method = vm.get_method_or_type_error(obj.clone(), "__float__", || {
563561
format!(
564562
"float() argument must be a string or a number, not '{}'",
565563
obj.class().name
566-
),
567-
)?;
564+
)
565+
})?;
568566
let result = vm.invoke(method, vec![])?;
569567
Ok(get_value(&result))
570568
}

vm/src/obj/objint.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -657,12 +657,9 @@ pub fn to_int(vm: &VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult<Big
657657
)))
658658
},
659659
obj => {
660-
let method = vm.get_method_or_type_error(
661-
obj.clone(),
662-
"__int__",
663-
format!("int() argument must be a string or a number, not '{}'",
664-
obj.class().name)
665-
)?;
660+
let method = vm.get_method_or_type_error(obj.clone(), "__int__", || {
661+
format!("int() argument must be a string or a number, not '{}'", obj.class().name)
662+
})?;
666663
let result = vm.invoke(method, PyFuncArgs::default())?;
667664
match result.payload::<PyInt>() {
668665
Some(int_obj) => Ok(int_obj.as_bigint().clone()),

vm/src/obj/objiter.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,9 @@ pub fn get_iter(vm: &VirtualMachine, iter_target: &PyObjectRef) -> PyResult {
2222
let method = method_or_err?;
2323
vm.invoke(method, vec![])
2424
} else {
25-
vm.get_method_or_type_error(
26-
iter_target.clone(),
27-
"__getitem__",
28-
format!("Cannot iterate over {}", iter_target.class().name),
29-
)?;
25+
vm.get_method_or_type_error(iter_target.clone(), "__getitem__", || {
26+
format!("Cannot iterate over {}", iter_target.class().name)
27+
})?;
3028
let obj_iterator = PySequenceIterator {
3129
position: Cell::new(0),
3230
obj: iter_target.clone(),

vm/src/obj/objstr.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -869,11 +869,9 @@ impl PyString {
869869
// https://docs.python.org/3/library/stdtypes.html#str.translate
870870
#[pymethod]
871871
fn translate(&self, table: PyObjectRef, vm: &VirtualMachine) -> PyResult<String> {
872-
vm.get_method_or_type_error(
873-
table.clone(),
874-
"__getitem__",
875-
format!("'{}' object is not subscriptable", table.class().name),
876-
)?;
872+
vm.get_method_or_type_error(table.clone(), "__getitem__", || {
873+
format!("'{}' object is not subscriptable", table.class().name)
874+
})?;
877875

878876
let mut translated = String::new();
879877
for c in self.value.chars() {

vm/src/pyobject.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,11 +1141,9 @@ where
11411141
_item: std::marker::PhantomData,
11421142
})
11431143
} else {
1144-
vm.get_method_or_type_error(
1145-
obj.clone(),
1146-
"__getitem__",
1147-
format!("'{}' object is not iterable", obj.class().name),
1148-
)?;
1144+
vm.get_method_or_type_error(obj.clone(), "__getitem__", || {
1145+
format!("'{}' object is not iterable", obj.class().name)
1146+
})?;
11491147
Self::try_from_object(
11501148
vm,
11511149
objiter::PySequenceIterator {

vm/src/stdlib/math.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,15 +173,13 @@ fn math_lgamma(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
173173
}
174174

175175
fn try_magic_method(func_name: &str, vm: &VirtualMachine, value: &PyObjectRef) -> PyResult {
176-
let method = vm.get_method_or_type_error(
177-
value.clone(),
178-
func_name,
176+
let method = vm.get_method_or_type_error(value.clone(), func_name, || {
179177
format!(
180178
"type '{}' doesn't define '{}' method",
181179
value.class().name,
182180
func_name,
183-
),
184-
)?;
181+
)
182+
})?;
185183
vm.invoke(method, vec![])
186184
}
187185

vm/src/vm.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -624,16 +624,19 @@ impl VirtualMachine {
624624

625625
// get_method should be used for internal access to magic methods (by-passing
626626
// the full getattribute look-up.
627-
pub fn get_method_or_type_error(
627+
pub fn get_method_or_type_error<F>(
628628
&self,
629629
obj: PyObjectRef,
630630
method_name: &str,
631-
err_msg: String,
632-
) -> PyResult {
631+
err_msg: F,
632+
) -> PyResult
633+
where
634+
F: FnOnce() -> String,
635+
{
633636
let cls = obj.class();
634637
match objtype::class_get_attr(&cls, method_name) {
635638
Some(method) => self.call_get_descriptor(method, obj.clone()),
636-
None => Err(self.new_type_error(err_msg)),
639+
None => Err(self.new_type_error(err_msg())),
637640
}
638641
}
639642

0 commit comments

Comments
 (0)