diff --git a/vm/src/builtins/pytype.rs b/vm/src/builtins/pytype.rs index a335901f4..cc6565447 100644 --- a/vm/src/builtins/pytype.rs +++ b/vm/src/builtins/pytype.rs @@ -629,7 +629,7 @@ fn subtype_get_dict(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { // TODO: obj.class().as_pyref() need to be supported let cls = obj.clone_class(); let ret = match find_base_dict_descr(&cls, vm) { - Some(descr) => vm.call_get_descriptor(descr, obj).unwrap_or_else(|| { + Some(descr) => vm.call_get_descriptor(descr, obj).unwrap_or_else(|_| { Err(vm.new_type_error(format!( "this __dict__ descriptor does not support '{}' objects", cls.name diff --git a/vm/src/function.rs b/vm/src/function.rs index 6428fd18d..42626593f 100644 --- a/vm/src/function.rs +++ b/vm/src/function.rs @@ -26,6 +26,11 @@ where } } +macro_rules! count { + () => (0usize); + ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); +} + // A tuple of values that each implement `IntoPyObject` represents a sequence of // arguments that can be bound and passed to a built-in function. macro_rules! into_func_args_from_tuple { @@ -37,7 +42,9 @@ macro_rules! into_func_args_from_tuple { #[inline] fn into_args(self, vm: &VirtualMachine) -> FuncArgs { let ($($n,)*) = self; - vec![$($n.into_pyobject(vm),)*].into() + let mut result = Vec::with_capacity(count!($($n,)*) + 1); + $(result.push($n.into_pyobject(vm), );)* + result.into() } } }; diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 69b90f92b..7ab652421 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -944,19 +944,25 @@ impl VirtualMachine { descr: PyObjectRef, obj: Option, cls: Option, - ) -> Option { + ) -> Result { let descr_get = descr.class().mro_find_map(|cls| cls.slots.descr_get.load()); - descr_get.map(|descr_get| descr_get(descr, obj, cls, self)) + match descr_get { + Some(descr_get) => Ok(descr_get(descr, obj, cls, self)), + None => Err(descr), + } } - pub fn call_get_descriptor(&self, descr: PyObjectRef, obj: PyObjectRef) -> Option { + pub fn call_get_descriptor( + &self, + descr: PyObjectRef, + obj: PyObjectRef, + ) -> Result { let cls = obj.clone_class().into_object(); self.call_get_descriptor_specific(descr, Some(obj), Some(cls)) } pub fn call_if_get_descriptor(&self, attr: PyObjectRef, obj: PyObjectRef) -> PyResult { - self.call_get_descriptor(attr.clone(), obj) - .unwrap_or(Ok(attr)) + self.call_get_descriptor(attr, obj).unwrap_or_else(Ok) } pub fn call_method(&self, obj: &PyObjectRef, method_name: &str, args: T) -> PyResult @@ -1257,7 +1263,7 @@ impl VirtualMachine { if let Some(ref attr) = cls_attr { if attr.class().has_attr("__set__") { - if let Some(r) = self.call_get_descriptor(attr.clone(), obj.clone()) { + if let Ok(r) = self.call_get_descriptor(attr.clone(), obj.clone()) { return r.map(Some); } }