From f314328294d9be04a1fe0629292fa3ff65ddbc5e Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Thu, 16 Mar 2023 00:20:54 +0900 Subject: [PATCH] lifetime bounded TryFromBorrwoedObject --- examples/call_between_rust_and_python.rs | 4 +-- stdlib/src/mmap.rs | 4 +-- stdlib/src/resource.rs | 4 +-- stdlib/src/unicodedata.rs | 4 +-- stdlib/src/zlib.rs | 4 +-- vm/src/builtins/bool.rs | 4 +-- vm/src/builtins/bytes.rs | 4 +-- vm/src/builtins/int.rs | 4 +-- vm/src/builtins/str.rs | 4 +-- vm/src/bytesinner.rs | 4 +-- vm/src/convert/try_from.rs | 31 ++++++++++++++++++------ vm/src/function/buffer.rs | 8 +++--- vm/src/function/mod.rs | 4 +-- vm/src/protocol/buffer.rs | 4 +-- vm/src/stdlib/time.rs | 4 +-- 15 files changed, 53 insertions(+), 38 deletions(-) diff --git a/examples/call_between_rust_and_python.rs b/examples/call_between_rust_and_python.rs index c139309e8..98fb434fa 100644 --- a/examples/call_between_rust_and_python.rs +++ b/examples/call_between_rust_and_python.rs @@ -86,8 +86,8 @@ python_person.name: {}", name: String, } - impl TryFromBorrowedObject for PythonPerson { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { + impl<'a> TryFromBorrowedObject<'a> for PythonPerson { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { let name = obj.get_attr("name", vm)?.try_into_value::(vm)?; Ok(PythonPerson { name }) } diff --git a/stdlib/src/mmap.rs b/stdlib/src/mmap.rs index 06cc37d31..b0a72562e 100644 --- a/stdlib/src/mmap.rs +++ b/stdlib/src/mmap.rs @@ -72,8 +72,8 @@ mod mmap { Copy = 3, } - impl TryFromBorrowedObject for AccessMode { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { + impl<'a> TryFromBorrowedObject<'a> for AccessMode { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { let i = u32::try_from_borrowed_object(vm, obj)?; Ok(match i { 0 => Self::Default, diff --git a/stdlib/src/resource.rs b/stdlib/src/resource.rs index 1d3513f47..51f2fd785 100644 --- a/stdlib/src/resource.rs +++ b/stdlib/src/resource.rs @@ -129,8 +129,8 @@ mod resource { } struct Limits(libc::rlimit); - impl TryFromBorrowedObject for Limits { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { + impl<'a> TryFromBorrowedObject<'a> for Limits { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { let seq: Vec = obj.try_to_value(vm)?; match *seq { [cur, max] => Ok(Self(libc::rlimit { diff --git a/stdlib/src/unicodedata.rs b/stdlib/src/unicodedata.rs index c8332740b..be7859843 100644 --- a/stdlib/src/unicodedata.rs +++ b/stdlib/src/unicodedata.rs @@ -41,8 +41,8 @@ enum NormalizeForm { Nfkd, } -impl TryFromBorrowedObject for NormalizeForm { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { +impl<'a> TryFromBorrowedObject<'a> for NormalizeForm { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { obj.try_value_with( |form: &PyStr| { Ok(match form.as_str() { diff --git a/stdlib/src/zlib.rs b/stdlib/src/zlib.rs index f7df60185..fd3efa28b 100644 --- a/stdlib/src/zlib.rs +++ b/stdlib/src/zlib.rs @@ -581,8 +581,8 @@ mod zlib { } } - impl TryFromBorrowedObject for Level { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { + impl<'a> TryFromBorrowedObject<'a> for Level { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { let int: i32 = obj.try_index(vm)?.try_to_primitive(vm)?; Ok(Self::new(int)) } diff --git a/vm/src/builtins/bool.rs b/vm/src/builtins/bool.rs index 4da54113f..e8d506827 100644 --- a/vm/src/builtins/bool.rs +++ b/vm/src/builtins/bool.rs @@ -19,8 +19,8 @@ impl ToPyObject for bool { } } -impl TryFromBorrowedObject for bool { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { +impl<'a> TryFromBorrowedObject<'a> for bool { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { if obj.fast_isinstance(vm.ctx.types.int_type) { Ok(get_value(obj)) } else { diff --git a/vm/src/builtins/bytes.rs b/vm/src/builtins/bytes.rs index 1d1cdfabb..f32f78422 100644 --- a/vm/src/builtins/bytes.rs +++ b/vm/src/builtins/bytes.rs @@ -742,8 +742,8 @@ impl IterNext for PyBytesIterator { } } -impl TryFromBorrowedObject for PyBytes { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { +impl<'a> TryFromBorrowedObject<'a> for PyBytes { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { PyBytesInner::try_from_borrowed_object(vm, obj).map(|x| x.into()) } } diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index 9193bb793..46b81de56 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -72,8 +72,8 @@ impl_into_pyobject_int!(isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 BigI macro_rules! impl_try_from_object_int { ($(($t:ty, $to_prim:ident),)*) => {$( - impl TryFromBorrowedObject for $t { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { + impl<'a> TryFromBorrowedObject<'a> for $t { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { obj.try_value_with(|int: &PyInt| { int.try_to_primitive(vm) }, vm) diff --git a/vm/src/builtins/str.rs b/vm/src/builtins/str.rs index 8b6d61c37..32b86f0e6 100644 --- a/vm/src/builtins/str.rs +++ b/vm/src/builtins/str.rs @@ -42,8 +42,8 @@ use unic_ucd_category::GeneralCategory; use unic_ucd_ident::{is_xid_continue, is_xid_start}; use unicode_casing::CharExt; -impl TryFromBorrowedObject for String { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { +impl<'a> TryFromBorrowedObject<'a> for String { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { obj.try_value_with(|pystr: &PyStr| Ok(pystr.as_str().to_owned()), vm) } } diff --git a/vm/src/bytesinner.rs b/vm/src/bytesinner.rs index f2a0a7f35..4f07058a5 100644 --- a/vm/src/bytesinner.rs +++ b/vm/src/bytesinner.rs @@ -30,8 +30,8 @@ impl From> for PyBytesInner { } } -impl TryFromBorrowedObject for PyBytesInner { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { +impl<'a> TryFromBorrowedObject<'a> for PyBytesInner { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { bytes_from_object(vm, obj).map(Self::from) } } diff --git a/vm/src/convert/try_from.rs b/vm/src/convert/try_from.rs index 42ab0d320..c1f51ebb5 100644 --- a/vm/src/convert/try_from.rs +++ b/vm/src/convert/try_from.rs @@ -1,7 +1,7 @@ use crate::{ builtins::PyFloat, object::{AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult}, - vm::VirtualMachine, + Py, VirtualMachine, }; use num_traits::ToPrimitive; @@ -15,7 +15,7 @@ pub trait TryFromObject: Sized { } /// Rust-side only version of TryFromObject to reduce unnecessary Rc::clone -impl TryFromObject for T { +impl TryFromBorrowedObject<'a>> TryFromObject for T { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { TryFromBorrowedObject::try_from_borrowed_object(vm, &obj) } @@ -31,9 +31,9 @@ impl PyObjectRef { } impl PyObject { - pub fn try_to_value(&self, vm: &VirtualMachine) -> PyResult + pub fn try_to_value<'a, T: 'a>(&'a self, vm: &VirtualMachine) -> PyResult where - T: TryFromBorrowedObject, + T: TryFromBorrowedObject<'a>, { T::try_from_borrowed_object(vm, self) } @@ -55,9 +55,12 @@ impl PyObject { } /// Lower-cost variation of `TryFromObject` -pub trait TryFromBorrowedObject: Sized { +pub trait TryFromBorrowedObject<'a>: Sized +where + Self: 'a, +{ /// Attempt to convert a Python object to a value of this type. - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult; + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult; } impl TryFromObject for PyRef @@ -93,12 +96,24 @@ impl TryFromObject for Option { } } -impl TryFromBorrowedObject for Vec { - fn try_from_borrowed_object(vm: &VirtualMachine, value: &PyObject) -> PyResult { +impl<'a, T: 'a + TryFromObject> TryFromBorrowedObject<'a> for Vec { + fn try_from_borrowed_object(vm: &VirtualMachine, value: &'a PyObject) -> PyResult { vm.extract_elements_with(value, |obj| T::try_from_object(vm, obj)) } } +impl<'a, T: PyPayload> TryFromBorrowedObject<'a> for &'a Py { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { + let class = T::class(vm); + if obj.fast_isinstance(class) { + obj.downcast_ref() + .ok_or_else(|| vm.new_downcast_runtime_error(class, &obj)) + } else { + Err(vm.new_downcast_type_error(class, &obj)) + } + } +} + impl TryFromObject for std::time::Duration { fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { use std::time::Duration; diff --git a/vm/src/function/buffer.rs b/vm/src/function/buffer.rs index 81e5e104c..2938e915e 100644 --- a/vm/src/function/buffer.rs +++ b/vm/src/function/buffer.rs @@ -65,8 +65,8 @@ impl From for PyBuffer { } } -impl TryFromBorrowedObject for ArgBytesLike { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { +impl<'a> TryFromBorrowedObject<'a> for ArgBytesLike { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { let buffer = PyBuffer::try_from_borrowed_object(vm, obj)?; if buffer.desc.is_contiguous() { Ok(Self(buffer)) @@ -107,8 +107,8 @@ impl From for PyBuffer { } } -impl TryFromBorrowedObject for ArgMemoryBuffer { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { +impl<'a> TryFromBorrowedObject<'a> for ArgMemoryBuffer { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { let buffer = PyBuffer::try_from_borrowed_object(vm, obj)?; if !buffer.desc.is_contiguous() { Err(vm.new_type_error("non-contiguous buffer is not a bytes-like object".to_owned())) diff --git a/vm/src/function/mod.rs b/vm/src/function/mod.rs index 5b4d2bdd7..b6199ab1e 100644 --- a/vm/src/function/mod.rs +++ b/vm/src/function/mod.rs @@ -28,8 +28,8 @@ pub enum ArgByteOrder { Little, } -impl TryFromBorrowedObject for ArgByteOrder { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { +impl<'a> TryFromBorrowedObject<'a> for ArgByteOrder { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { obj.try_value_with( |s: &PyStr| match s.as_str() { "big" => Ok(Self::Big), diff --git a/vm/src/protocol/buffer.rs b/vm/src/protocol/buffer.rs index 9ba0c0160..1450c837c 100644 --- a/vm/src/protocol/buffer.rs +++ b/vm/src/protocol/buffer.rs @@ -136,8 +136,8 @@ impl PyBuffer { } } -impl TryFromBorrowedObject for PyBuffer { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { +impl<'a> TryFromBorrowedObject<'a> for PyBuffer { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { let cls = obj.class(); let as_buffer = cls.mro_find_map(|cls| cls.slots.as_buffer); if let Some(f) = as_buffer { diff --git a/vm/src/stdlib/time.rs b/vm/src/stdlib/time.rs index 474d51d75..793a03c6d 100644 --- a/vm/src/stdlib/time.rs +++ b/vm/src/stdlib/time.rs @@ -435,8 +435,8 @@ mod unix { #[pyattr] use libc::{CLOCK_PROF, CLOCK_UPTIME}; - impl TryFromBorrowedObject for ClockId { - fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult { + impl<'a> TryFromBorrowedObject<'a> for ClockId { + fn try_from_borrowed_object(vm: &VirtualMachine, obj: &'a PyObject) -> PyResult { obj.try_to_value(vm).map(ClockId::from_raw) } }