diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index 6a169cc2f2..b3e6b1c989 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -15,7 +15,7 @@ use crate::{ }, protocol::{PyNumber, PyNumberMethods}, types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable}, - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, + AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult, TryFromBorrowedObject, VirtualMachine, }; use num_bigint::{BigInt, Sign}; @@ -321,7 +321,7 @@ impl PyInt { #[pyclass( flags(BASETYPE), - with(Comparable, Hashable, Constructor, AsNumber, Representable) + with(PyRef, Comparable, Hashable, Constructor, AsNumber, Representable) )] impl PyInt { #[pymethod(name = "__radd__")] @@ -521,11 +521,6 @@ impl PyInt { Ok(zelf) } - #[pymethod(magic)] - fn int(zelf: PyRef) -> PyRef { - zelf - } - #[pymethod(magic)] fn pos(&self) -> BigInt { self.value.clone() @@ -537,23 +532,23 @@ impl PyInt { } #[pymethod(magic)] - fn trunc(zelf: PyRef, vm: &VirtualMachine) -> PyRef { - Self::clone_if_subclass(zelf, vm) + fn trunc(zelf: PyRef, vm: &VirtualMachine) -> PyRefExact { + zelf.int(vm) } #[pymethod(magic)] - fn floor(zelf: PyRef, vm: &VirtualMachine) -> PyRef { - Self::clone_if_subclass(zelf, vm) + fn floor(zelf: PyRef, vm: &VirtualMachine) -> PyRefExact { + zelf.int(vm) } #[pymethod(magic)] - fn ceil(zelf: PyRef, vm: &VirtualMachine) -> PyRef { - Self::clone_if_subclass(zelf, vm) + fn ceil(zelf: PyRef, vm: &VirtualMachine) -> PyRefExact { + zelf.int(vm) } #[pymethod(magic)] - fn index(zelf: PyRef) -> PyRef { - zelf + fn index(zelf: PyRef, vm: &VirtualMachine) -> PyRefExact { + zelf.int(vm) } #[pymethod(magic)] @@ -589,8 +584,8 @@ impl PyInt { } #[pymethod] - fn conjugate(zelf: PyRef, vm: &VirtualMachine) -> PyRef { - Self::clone_if_subclass(zelf, vm) + fn conjugate(zelf: PyRef, vm: &VirtualMachine) -> PyRefExact { + zelf.int(vm) } #[pyclassmethod] @@ -659,18 +654,9 @@ impl PyInt { Ok(bytes.into()) } - #[inline] - fn clone_if_subclass(zelf: PyRef, vm: &VirtualMachine) -> PyRef { - if zelf.class().is(vm.ctx.types.int_type) { - return zelf; - } - - vm.ctx.new_bigint(&zelf.value) - } - #[pygetset] - fn real(zelf: PyRef, vm: &VirtualMachine) -> PyRef { - Self::clone_if_subclass(zelf, vm) + fn real(zelf: PyRef, vm: &VirtualMachine) -> PyRefExact { + zelf.int(vm) } #[pygetset] @@ -679,8 +665,8 @@ impl PyInt { } #[pygetset] - fn numerator(zelf: PyRef, vm: &VirtualMachine) -> PyRef { - Self::clone_if_subclass(zelf, vm) + fn numerator(zelf: PyRef, vm: &VirtualMachine) -> PyRefExact { + zelf.int(vm) } #[pygetset] @@ -701,6 +687,17 @@ impl PyInt { } } +#[pyclass] +impl PyRef { + #[pymethod(magic)] + fn int(self, vm: &VirtualMachine) -> PyRefExact { + self.into_exact_or(&vm.ctx, |zelf| unsafe { + // TODO: this is actually safe. we need better interface + PyRefExact::new_unchecked(vm.ctx.new_bigint(&zelf.value)) + }) + } +} + impl Comparable for PyInt { fn cmp( zelf: &Py, diff --git a/vm/src/builtins/str.rs b/vm/src/builtins/str.rs index efd8e2a496..9e850ad2cb 100644 --- a/vm/src/builtins/str.rs +++ b/vm/src/builtins/str.rs @@ -364,6 +364,7 @@ impl PyStr { #[pyclass( flags(BASETYPE), with( + PyRef, AsMapping, AsNumber, AsSequence, @@ -481,11 +482,6 @@ impl PyStr { Self::repeat(zelf, value.into(), vm) } - #[pymethod(magic)] - fn str(zelf: PyRef) -> PyStrRef { - zelf - } - #[inline] pub(crate) fn repr(&self, vm: &VirtualMachine) -> PyResult { rustpython_common::str::repr(self.as_str()) @@ -1270,6 +1266,17 @@ impl PyStr { } } +#[pyclass] +impl PyRef { + #[pymethod(magic)] + fn str(self, vm: &VirtualMachine) -> PyRefExact { + self.into_exact_or(&vm.ctx, |zelf| unsafe { + // Creating a copy with same kind is safe + PyStr::new_str_unchecked(zelf.bytes.to_vec(), zelf.kind.kind()).into_exact_ref(&vm.ctx) + }) + } +} + impl PyStrRef { pub fn concat_in_place(&mut self, other: &str, vm: &VirtualMachine) { // TODO: call [A]Rc::get_mut on the str to try to mutate the data in place diff --git a/vm/src/object/ext.rs b/vm/src/object/ext.rs index 864ec76993..b8aa544fd9 100644 --- a/vm/src/object/ext.rs +++ b/vm/src/object/ext.rs @@ -9,6 +9,7 @@ use crate::common::{ use crate::{ builtins::{PyBaseExceptionRef, PyStrInterned, PyType}, convert::{IntoPyException, ToPyObject, ToPyResult, TryFromObject}, + vm::Context, VirtualMachine, }; use std::{borrow::Borrow, fmt, marker::PhantomData, ops::Deref, ptr::null_mut}; @@ -107,6 +108,20 @@ impl std::borrow::ToOwned for PyExact { } } +impl PyRef { + pub fn into_exact_or( + self, + ctx: &Context, + f: impl FnOnce(Self) -> PyRefExact, + ) -> PyRefExact { + if self.class().is(T::class(ctx)) { + unsafe { PyRefExact::new_unchecked(self) } + } else { + f(self) + } + } +} + /// PyRef but guaranteed not to be a subtype instance #[derive(Debug)] #[repr(transparent)]