diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index 5798ba6b1..e1997fb47 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -80,24 +80,12 @@ macro_rules! impl_into_pyobject_int { impl_into_pyobject_int!(isize i8 i16 i32 i64 usize u8 u16 u32 u64 BigInt); -pub(crate) fn try_to_primitive<'a, I>(i: &'a BigInt, vm: &VirtualMachine) -> PyResult -where - I: PrimInt + TryFrom<&'a BigInt>, -{ - I::try_from(i).map_err(|_| { - vm.new_overflow_error(format!( - "Python int too large to convert to Rust {}", - std::any::type_name::() - )) - }) -} - macro_rules! impl_try_from_object_int { ($(($t:ty, $to_prim:ident),)*) => {$( impl TryFromBorrowedObject for $t { fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { try_value_from_borrowed_object(vm, obj, |int: &PyInt| { - try_to_primitive(int.as_bigint(), vm) + int.try_to_primitive(vm) }) } } @@ -306,7 +294,12 @@ impl PyInt { where I: PrimInt + TryFrom<&'a BigInt>, { - try_to_primitive(self.as_bigint(), vm) + I::try_from(self.as_bigint()).map_err(|_| { + vm.new_overflow_error(format!( + "Python int too large to convert to Rust {}", + std::any::type_name::() + )) + }) } #[inline] diff --git a/vm/src/builtins/iter.rs b/vm/src/builtins/iter.rs index 6e9d64e49..14598a3a9 100644 --- a/vm/src/builtins/iter.rs +++ b/vm/src/builtins/iter.rs @@ -2,7 +2,7 @@ * iterator types */ -use super::{int, PyInt, PyTypeRef}; +use super::{PyInt, PyTypeRef}; use crate::{ function::ArgCallable, protocol::PyIterReturn, @@ -43,7 +43,7 @@ impl PositionIterInternal { { if let IterStatus::Active(obj) = &self.status { if let Some(i) = state.payload::() { - let i = int::try_to_primitive(i.as_bigint(), vm).unwrap_or(0); + let i = i.try_to_primitive(vm).unwrap_or(0); self.position = f(obj, i); Ok(()) } else { diff --git a/vm/src/cformat.rs b/vm/src/cformat.rs index 1b0728025..f3d5272bc 100644 --- a/vm/src/cformat.rs +++ b/vm/src/cformat.rs @@ -3,7 +3,7 @@ use crate::common::float_ops; use crate::{ - builtins::{int, try_f64_to_bigint, tuple, IntoPyFloat, PyBytes, PyFloat, PyInt, PyStr}, + builtins::{try_f64_to_bigint, tuple, IntoPyFloat, PyBytes, PyFloat, PyInt, PyStr}, protocol::PyBuffer, ItemProtocol, PyObjectRef, PyResult, TryFromBorrowedObject, TryFromObject, TypeProtocol, VirtualMachine, @@ -561,13 +561,12 @@ fn try_update_quantity_from_tuple<'a, I: Iterator>( match q { Some(CFormatQuantity::FromValuesTuple) => match elements.next() { Some(width_obj) => { - if !width_obj.isinstance(&vm.ctx.types.int_type) { - Err(vm.new_type_error("* wants int".to_owned())) - } else { - let i = int::get_value(width_obj); - let i = int::try_to_primitive::(i, vm)? as usize; + if let Some(i) = width_obj.payload::() { + let i = i.try_to_primitive::(vm)? as usize; *q = Some(CFormatQuantity::Amount(i)); Ok(()) + } else { + Err(vm.new_type_error("* wants int".to_owned())) } } None => Err(vm.new_type_error("not enough arguments for format string".to_owned())), diff --git a/vm/src/iterator.rs b/vm/src/iterator.rs index 3509ae410..0fb0fa938 100644 --- a/vm/src/iterator.rs +++ b/vm/src/iterator.rs @@ -3,11 +3,10 @@ */ use crate::{ - builtins::{int, PyBaseExceptionRef, PyInt}, + builtins::{PyBaseExceptionRef, PyInt}, protocol::{PyIter, PyIterReturn}, IdProtocol, PyObjectRef, PyResult, TypeProtocol, VirtualMachine, }; -use num_traits::Signed; pub fn try_map(vm: &VirtualMachine, iter: &PyIter, cap: usize, mut f: F) -> PyResult> where @@ -66,7 +65,7 @@ pub fn length_hint(vm: &VirtualMachine, iter: PyObjectRef) -> PyResult(vm) .ok_or_else(|| { vm.new_type_error(format!( @@ -74,12 +73,12 @@ pub fn length_hint(vm: &VirtualMachine, iter: PyObjectRef) -> PyResult= 0".to_owned())); + .try_to_primitive::(vm)?; + if hint.is_negative() { + Err(vm.new_value_error("__length_hint__() should return >= 0".to_owned())) + } else { + Ok(Some(hint as usize)) } - let hint = int::try_to_primitive(result, vm)?; - Ok(Some(hint)) } // pub fn seq_iter_method(obj: PyObjectRef) -> PySequenceIterator { diff --git a/vm/src/stdlib/builtins.rs b/vm/src/stdlib/builtins.rs index 5a0c88021..6315d77dd 100644 --- a/vm/src/stdlib/builtins.rs +++ b/vm/src/stdlib/builtins.rs @@ -11,7 +11,7 @@ mod builtins { use crate::builtins::{ enumerate::PyReverseSequenceIterator, function::{PyCellRef, PyFunctionRef}, - int::{self, PyIntRef}, + int::PyIntRef, iter::PyCallableIterator, list::{PyList, SortOptions}, IntoPyBool, PyByteArray, PyBytes, PyBytesRef, PyCode, PyDictRef, PyStr, PyStrRef, @@ -153,9 +153,7 @@ mod builtins { .map_err(|e| vm.new_unicode_decode_error(e.to_string()))?, }; - let flags = args - .flags - .map_or(Ok(0), |v| int::try_to_primitive(v.as_bigint(), vm))?; + let flags = args.flags.map_or(Ok(0), |v| v.try_to_primitive(vm))?; if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() { #[cfg(not(feature = "rustpython-compiler"))]