diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index ad3fc5697..eca839910 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -10,8 +10,10 @@ use super::objtype::PyClassRef; use crate::format::FormatSpec; use crate::function::{OptionalArg, OptionalOption}; use crate::pyobject::{ - BorrowValue, IntoPyObject, IntoPyResult, PyArithmaticValue::*, PyClassImpl, PyComparisonValue, - PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, + BorrowValue, IntoPyObject, + PyArithmaticValue::{self, *}, + PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; use rustpython_common::{float_ops, hash}; @@ -234,13 +236,18 @@ impl PyFloat { } #[inline] - fn simple_op(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult + fn simple_op( + &self, + other: PyObjectRef, + op: F, + vm: &VirtualMachine, + ) -> PyResult> where F: Fn(f64, f64) -> PyResult, { try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| op(self.value, other).into_pyresult(vm), + || Ok(NotImplemented), + |other| Ok(Implemented(op(self.value, other)?)), ) } @@ -251,34 +258,30 @@ impl PyFloat { { try_float(&other, vm)?.map_or_else( || Ok(vm.ctx.not_implemented()), - |other| op(self.value, other).into_pyresult(vm), + |other| op(self.value, other), ) } #[inline] - fn tuple_op(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult + fn tuple_op( + &self, + other: PyObjectRef, + op: F, + vm: &VirtualMachine, + ) -> PyResult> where F: Fn(f64, f64) -> PyResult<(f64, f64)>, { try_float(&other, vm)?.map_or_else( - || Ok(vm.ctx.not_implemented()), - |other| { - let (r1, r2) = op(self.value, other)?; - Ok(vm - .ctx - .new_tuple(vec![vm.ctx.new_float(r1), vm.ctx.new_float(r2)])) - }, + || Ok(NotImplemented), + |other| Ok(Implemented(op(self.value, other)?)), ) } #[pymethod(name = "__add__")] - fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - self.simple_op(other, |a, b| Ok(a + b), vm) - } - #[pymethod(name = "__radd__")] - fn radd(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - self.add(other, vm) + fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult> { + self.simple_op(other, |a, b| Ok(a + b), vm) } #[pymethod(name = "__bool__")] @@ -287,32 +290,48 @@ impl PyFloat { } #[pymethod(name = "__divmod__")] - fn divmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn divmod( + &self, + other: PyObjectRef, + vm: &VirtualMachine, + ) -> PyResult> { self.tuple_op(other, |a, b| inner_divmod(a, b, vm), vm) } #[pymethod(name = "__rdivmod__")] - fn rdivmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn rdivmod( + &self, + other: PyObjectRef, + vm: &VirtualMachine, + ) -> PyResult> { self.tuple_op(other, |a, b| inner_divmod(b, a, vm), vm) } #[pymethod(name = "__floordiv__")] - fn floordiv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn floordiv( + &self, + other: PyObjectRef, + vm: &VirtualMachine, + ) -> PyResult> { self.simple_op(other, |a, b| inner_floordiv(a, b, vm), vm) } #[pymethod(name = "__rfloordiv__")] - fn rfloordiv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn rfloordiv( + &self, + other: PyObjectRef, + vm: &VirtualMachine, + ) -> PyResult> { self.simple_op(other, |a, b| inner_floordiv(b, a, vm), vm) } #[pymethod(name = "__mod__")] - fn mod_(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn mod_(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult> { self.simple_op(other, |a, b| inner_mod(a, b, vm), vm) } #[pymethod(name = "__rmod__")] - fn rmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn rmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult> { self.simple_op(other, |a, b| inner_mod(b, a, vm), vm) } @@ -337,12 +356,12 @@ impl PyFloat { } #[pymethod(name = "__sub__")] - fn sub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn sub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult> { self.simple_op(other, |a, b| Ok(a - b), vm) } #[pymethod(name = "__rsub__")] - fn rsub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn rsub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult> { self.simple_op(other, |a, b| Ok(b - a), vm) } @@ -352,23 +371,23 @@ impl PyFloat { } #[pymethod(name = "__truediv__")] - fn truediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn truediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult> { self.simple_op(other, |a, b| inner_div(a, b, vm), vm) } #[pymethod(name = "__rtruediv__")] - fn rtruediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn rtruediv( + &self, + other: PyObjectRef, + vm: &VirtualMachine, + ) -> PyResult> { self.simple_op(other, |a, b| inner_div(b, a, vm), vm) } #[pymethod(name = "__mul__")] - fn mul(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - self.simple_op(other, |a, b| Ok(a * b), vm) - } - #[pymethod(name = "__rmul__")] - fn rmul(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult { - self.mul(other, vm) + fn mul(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult> { + self.simple_op(other, |a, b| Ok(a * b), vm) } #[pymethod(name = "__trunc__")] @@ -379,7 +398,7 @@ impl PyFloat { #[pymethod(name = "__round__")] fn round(&self, ndigits: OptionalOption, vm: &VirtualMachine) -> PyResult { let ndigits = ndigits.flatten(); - if let Some(ndigits) = ndigits { + let value = if let Some(ndigits) = ndigits { let ndigits = ndigits.borrow_value(); if ndigits.is_zero() { let fract = self.value.fract(); @@ -392,7 +411,7 @@ impl PyFloat { } else { self.value.round() }; - Ok(vm.ctx.new_float(value)) + vm.ctx.new_float(value) } else { let ndigits = match ndigits { ndigits if *ndigits > i32::max_value().to_bigint().unwrap() => i32::max_value(), @@ -405,17 +424,17 @@ impl PyFloat { return Ok(vm.ctx.new_float(self.value)); } if ndigits >= 0i32 { - Ok(vm.ctx.new_float( + vm.ctx.new_float( (self.value * pow(10.0, ndigits as usize)).round() / pow(10.0, ndigits as usize), - )) + ) } else { let result = (self.value / pow(10.0, (-ndigits) as usize)).round() * pow(10.0, (-ndigits) as usize); if result.is_nan() { return Ok(vm.ctx.new_float(0.0)); } - Ok(vm.ctx.new_float(result)) + vm.ctx.new_float(result) } } } else { @@ -430,8 +449,9 @@ impl PyFloat { self.value.round() }; let int = try_bigint(value, vm)?; - Ok(vm.ctx.new_int(int)) - } + vm.ctx.new_int(int) + }; + Ok(value) } #[pymethod(name = "__int__")] @@ -472,13 +492,14 @@ impl PyFloat { #[pymethod(name = "as_integer_ratio")] fn as_integer_ratio(&self, vm: &VirtualMachine) -> PyResult { let value = self.value; - if value.is_infinite() { - return Err( + if !value.is_finite() { + return Err(if value.is_infinite() { vm.new_overflow_error("cannot convert Infinity to integer ratio".to_owned()) - ); - } - if value.is_nan() { - return Err(vm.new_value_error("cannot convert NaN to integer ratio".to_owned())); + } else if value.is_nan() { + vm.new_value_error("cannot convert NaN to integer ratio".to_owned()) + } else { + unreachable!("it must be finite") + }); } let ratio = Ratio::from_float(value).unwrap();