Skip to content

Commit ac861a4

Browse files
committed
Special cases for new, and type error on bad call.
1 parent dce628d commit ac861a4

File tree

2 files changed

+20
-5
lines changed

2 files changed

+20
-5
lines changed

vm/src/builtins.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,5 +659,15 @@ pub fn builtin_build_class_(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> Py
659659

660660
let bases = vm.context().new_tuple(bases);
661661

662-
vm.call_method(&metaclass, "__new__", vec![name_arg, bases, namespace])
662+
// Special case: __new__ must be looked up on the metaclass, not the meta-metaclass as
663+
// per vm.call(metaclass, "__new__", ...)
664+
let new = metaclass.get_attr("__new__").unwrap();
665+
let wrapped = vm.call_get_descriptor(new, metaclass)?;
666+
vm.invoke(
667+
wrapped,
668+
PyFuncArgs {
669+
args: vec![name_arg, bases, namespace],
670+
kwargs: vec![],
671+
},
672+
)
663673
}

vm/src/vm.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,16 @@ impl VirtualMachine {
187187
method_name: &str,
188188
args: PyFuncArgs,
189189
) -> PyResult {
190+
// This is only used in the vm for magic methods, which use a greatly simplified attribute lookup.
190191
let cls = obj.typ();
191-
let func = cls.get_attr(method_name).unwrap();
192-
trace!("vm.call_method {:?} {:?} -> {:?}", obj, method_name, func);
193-
let wrapped = self.call_get_descriptor(func, obj.clone())?;
194-
self.invoke(wrapped, args)
192+
match cls.get_attr(method_name) {
193+
Some(func) => {
194+
trace!("vm.call_method {:?} {:?} -> {:?}", obj, method_name, func);
195+
let wrapped = self.call_get_descriptor(func, obj.clone())?;
196+
self.invoke(wrapped, args)
197+
}
198+
None => Err(self.new_type_error(format!("Unsupported method: {}", method_name))),
199+
}
195200
}
196201

197202
pub fn invoke(&mut self, func_ref: PyObjectRef, args: PyFuncArgs) -> PyResult {

0 commit comments

Comments
 (0)