diff --git a/vm/src/builtins/iter.rs b/vm/src/builtins/iter.rs index 492aee776..1081b16f3 100644 --- a/vm/src/builtins/iter.rs +++ b/vm/src/builtins/iter.rs @@ -70,9 +70,7 @@ impl PySequenceIterator { let hint = if self.reversed { pos + 1 } else { - let len = vm._len(&self.obj).unwrap_or_else(|| { - Err(vm.new_type_error("sequence has no __len__ method".to_owned())) - })?; + let len = vm.obj_len(&self.obj)?; len as isize - pos }; Ok(hint) diff --git a/vm/src/builtins/make_module.rs b/vm/src/builtins/make_module.rs index c068294c9..7a5384f3d 100644 --- a/vm/src/builtins/make_module.rs +++ b/vm/src/builtins/make_module.rs @@ -440,12 +440,7 @@ mod decl { #[pyfunction] fn len(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { - vm._len(&obj).unwrap_or_else(|| { - Err(vm.new_type_error(format!( - "object of type '{}' has no len()", - obj.class().name - ))) - }) + vm.obj_len(&obj) } #[pyfunction] diff --git a/vm/src/iterator.rs b/vm/src/iterator.rs index 339e46836..e7040c42f 100644 --- a/vm/src/iterator.rs +++ b/vm/src/iterator.rs @@ -108,7 +108,7 @@ pub fn stop_iter_value(vm: &VirtualMachine, exc: &PyBaseExceptionRef) -> PyResul } pub fn length_hint(vm: &VirtualMachine, iter: PyObjectRef) -> PyResult> { - if let Some(len) = vm._len(&iter) { + if let Some(len) = vm.obj_len_opt(&iter) { match len { Ok(len) => return Ok(Some(len)), Err(e) => { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 400c0df9b..9ac06e32f 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -1525,7 +1525,7 @@ impl VirtualMachine { hash(&obj, self) } - pub fn _len(&self, obj: &PyObjectRef) -> Option> { + pub fn obj_len_opt(&self, obj: &PyObjectRef) -> Option> { self.get_method(obj.clone(), "__len__").map(|len| { let len = self.invoke(&len?, ())?; let len = len @@ -1547,6 +1547,15 @@ impl VirtualMachine { }) } + pub fn obj_len(&self, obj: &PyObjectRef) -> PyResult { + self.obj_len_opt(obj).unwrap_or_else(|| { + Err(self.new_type_error(format!( + "object of type '{}' has no len()", + obj.class().name + ))) + }) + } + // https://docs.python.org/3/reference/expressions.html#membership-test-operations fn _membership_iter_search(&self, haystack: PyObjectRef, needle: PyObjectRef) -> PyResult { let iter = iterator::get_iter(self, &haystack)?;