diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 9435db199a..17a7498360 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -531,7 +531,50 @@ impl VirtualMachine { } pub fn _and(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult { - self.call_method(&a, "__and__", vec![b]) + // 1. Try __and__, next __rand__, next, give up + if let Ok(method) = self.get_method(a.clone(), "__and__") { + match self.invoke( + method, + PyFuncArgs { + args: vec![b.clone()], + kwargs: vec![], + }, + ) { + Ok(value) => return Ok(value), + Err(err) => { + if !objtype::isinstance(&err, &self.ctx.exceptions.not_implemented_error) { + return Err(err); + } + } + } + } + + // 2. try __rand__ + if let Ok(method) = self.get_method(b.clone(), "__rand__") { + match self.invoke( + method, + PyFuncArgs { + args: vec![a.clone()], + kwargs: vec![], + }, + ) { + Ok(value) => return Ok(value), + Err(err) => { + if !objtype::isinstance(&err, &self.ctx.exceptions.not_implemented_error) { + return Err(err); + } + } + } + } + + // 3. It all failed :( + // Cannot and a and b + let a_type_name = objtype::get_type_name(&a.typ()); + let b_type_name = objtype::get_type_name(&b.typ()); + Err(self.new_type_error(format!( + "Unsupported operand types for '&': '{}' and '{}'", + a_type_name, b_type_name + ))) } pub fn _eq(&mut self, a: &PyObjectRef, b: PyObjectRef) -> PyResult {