diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index 0cf99099d43..a36bcd2f0b0 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -362,7 +362,7 @@ fn impl_class( quote! { 0 } }; let base_layout = if attr.has_extends { - quote! { ::Layout } + quote! { ::LayoutAsBase } } else { quote! { pyo3::pycell::PyCellBase } }; diff --git a/src/derive_utils.rs b/src/derive_utils.rs index 1f0387f91d6..7b66675402e 100644 --- a/src/derive_utils.rs +++ b/src/derive_utils.rs @@ -223,13 +223,13 @@ impl GetPropertyValue for PyObject { pub trait PyBaseTypeUtils { type Dict; type WeakRef; - type Layout; + type LayoutAsBase; type BaseNativeType; } impl PyBaseTypeUtils for T { type Dict = T::Dict; type WeakRef = T::WeakRef; - type Layout = crate::pycell::PyCellInner; + type LayoutAsBase = crate::pycell::PyCellInner; type BaseNativeType = T::BaseNativeType; } diff --git a/src/freelist.rs b/src/freelist.rs index e40dfdcc175..d3a4ae4e413 100644 --- a/src/freelist.rs +++ b/src/freelist.rs @@ -4,7 +4,7 @@ use crate::ffi; use crate::pyclass::{tp_free_fallback, PyClassAlloc}; -use crate::type_object::{PyObjectLayout, PyTypeInfo}; +use crate::type_object::{PyLayout, PyTypeInfo}; use crate::Python; use std::mem; use std::os::raw::c_void; diff --git a/src/instance.rs b/src/instance.rs index dda3a56afb0..8a541710570 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -3,7 +3,7 @@ use crate::err::{PyErr, PyResult}; use crate::gil; use crate::object::PyObject; use crate::objectprotocol::ObjectProtocol; -use crate::type_object::PyDowncastImpl; +use crate::type_object::{PyBorrowFlagLayout, PyDowncastImpl}; use crate::types::PyAny; use crate::{ ffi, AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, PyCell, PyClass, PyClassInitializer, @@ -39,7 +39,7 @@ impl Py { pub fn new(py: Python, value: impl Into>) -> PyResult> where T: PyClass, - T::BaseLayout: crate::type_object::PyObjectSizedLayout, + T::BaseLayout: PyBorrowFlagLayout, { let initializer = value.into(); let obj = unsafe { initializer.create_cell(py)? }; diff --git a/src/pycell.rs b/src/pycell.rs index 7d03bb917e5..bf6d4b5883e 100644 --- a/src/pycell.rs +++ b/src/pycell.rs @@ -2,7 +2,7 @@ use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject}; use crate::pyclass_init::PyClassInitializer; use crate::pyclass_slots::{PyClassDict, PyClassWeakRef}; -use crate::type_object::{PyDowncastImpl, PyObjectLayout, PyObjectSizedLayout, PyTypeInfo}; +use crate::type_object::{PyBorrowFlagLayout, PyDowncastImpl, PyLayout, PySizedLayout, PyTypeInfo}; use crate::types::PyAny; use crate::{ffi, FromPy, PyClass, PyErr, PyNativeType, PyObject, PyResult, Python}; use std::cell::{Cell, UnsafeCell}; @@ -17,10 +17,10 @@ pub struct PyCellBase { borrow_flag: Cell, } -unsafe impl PyObjectLayout for PyCellBase +unsafe impl PyLayout for PyCellBase where T: PyTypeInfo + PyNativeType, - T::Layout: PyObjectSizedLayout, + T::Layout: PySizedLayout, { const IS_NATIVE_TYPE: bool = true; unsafe fn unchecked_ref(&self) -> &T { @@ -31,11 +31,18 @@ where } } -// This impl ensures `PyCellBase` can be a base type. -impl PyObjectSizedLayout for PyCellBase +// Thes impls ensures `PyCellBase` can be a base type. +impl PySizedLayout for PyCellBase where T: PyTypeInfo + PyNativeType, - T::Layout: PyObjectSizedLayout, + T::Layout: PySizedLayout, +{ +} + +unsafe impl PyBorrowFlagLayout for PyCellBase +where + T: PyTypeInfo + PyNativeType, + T::Layout: PySizedLayout, { } @@ -56,7 +63,7 @@ impl AsPyPointer for PyCellInner { } } -unsafe impl PyObjectLayout for PyCellInner { +unsafe impl PyLayout for PyCellInner { const IS_NATIVE_TYPE: bool = false; fn get_super_or(&mut self) -> Option<&mut T::BaseLayout> { Some(&mut self.ob_base) @@ -76,8 +83,9 @@ unsafe impl PyObjectLayout for PyCellInner { } } -// This impl ensures `PyCellInner` can be a base type. -impl PyObjectSizedLayout for PyCellInner {} +// Thes impls ensures `PyCellInner` can be a base type. +impl PySizedLayout for PyCellInner {} +unsafe impl PyBorrowFlagLayout for PyCellInner {} impl PyCellInner { fn get_borrow_flag(&self) -> BorrowFlag { @@ -164,7 +172,7 @@ impl PyCell { /// pub fn new(py: Python, value: impl Into>) -> PyResult<&Self> where - T::BaseLayout: crate::type_object::PyObjectSizedLayout, + T::BaseLayout: PyBorrowFlagLayout, { unsafe { let initializer = value.into(); @@ -325,9 +333,12 @@ impl PyCell { std::mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut()) } + /// Allocates new PyCell without initilizing value. + /// Requires `T::BaseLayout: PyBorrowFlagLayout` to ensure that + /// this layout has a borrow flag. pub(crate) unsafe fn internal_new(py: Python) -> PyResult<*mut Self> where - T::BaseLayout: crate::type_object::PyObjectSizedLayout, + T::BaseLayout: PyBorrowFlagLayout, { let base = T::alloc(py); if base.is_null() { @@ -342,7 +353,7 @@ impl PyCell { } } -unsafe impl PyObjectLayout for PyCell { +unsafe impl PyLayout for PyCell { const IS_NATIVE_TYPE: bool = false; fn get_super_or(&mut self) -> Option<&mut T::BaseLayout> { Some(&mut self.inner.ob_base) @@ -598,6 +609,7 @@ impl BorrowFlag { } } +/// An error returned by [`PyCell::try_borrow`](struct.PyCell.html#method.try_borrow). pub struct PyBorrowError { _private: (), } @@ -614,6 +626,7 @@ impl fmt::Display for PyBorrowError { } } +/// An error returned by [`PyCell::try_borrow_mut`](struct.PyCell.html#method.try_borrow_mut). pub struct PyBorrowMutError { _private: (), } diff --git a/src/pyclass.rs b/src/pyclass.rs index c9fd8130036..fa06336c253 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -1,7 +1,7 @@ //! `PyClass` trait use crate::class::methods::{PyMethodDefType, PyMethodsProtocol}; use crate::pyclass_slots::{PyClassDict, PyClassWeakRef}; -use crate::type_object::{type_flags, PyObjectLayout}; +use crate::type_object::{type_flags, PyLayout}; use crate::{class, ffi, gil, PyCell, PyErr, PyNativeType, PyResult, PyTypeInfo, Python}; use std::ffi::CString; use std::os::raw::c_void; diff --git a/src/pyclass_init.rs b/src/pyclass_init.rs index 33654ecf3bf..14ced26c588 100644 --- a/src/pyclass_init.rs +++ b/src/pyclass_init.rs @@ -1,5 +1,5 @@ //! Initialization utilities for `#[pyclass]`. -use crate::type_object::{PyObjectLayout, PyObjectSizedLayout, PyTypeInfo}; +use crate::type_object::{PyBorrowFlagLayout, PyLayout, PySizedLayout, PyTypeInfo}; use crate::{PyCell, PyClass, PyResult, Python}; use std::marker::PhantomData; @@ -8,7 +8,7 @@ use std::marker::PhantomData; /// This trait is intended to use internally for distinguishing `#[pyclass]` and /// Python native types. pub trait PyObjectInit: Sized { - fn init_class>(self, layout: &mut L); + fn init_class>(self, layout: &mut L); private_decl! {} } @@ -16,7 +16,7 @@ pub trait PyObjectInit: Sized { pub struct PyNativeTypeInitializer(PhantomData); impl PyObjectInit for PyNativeTypeInitializer { - fn init_class>(self, _layout: &mut L) {} + fn init_class>(self, _layout: &mut L) {} private_impl! {} } @@ -108,17 +108,18 @@ impl PyClassInitializer { pub fn add_subclass(self, subclass_value: S) -> PyClassInitializer where S: PyClass + PyTypeInfo, - S::BaseLayout: PyObjectSizedLayout, + S::BaseLayout: PySizedLayout, S::BaseType: PyTypeInfo, { PyClassInitializer::new(subclass_value, self) } + // Create a new PyCell + initialize it #[doc(hidden)] pub unsafe fn create_cell(self, py: Python) -> PyResult<*mut PyCell> where T: PyClass, - T::BaseLayout: PyObjectSizedLayout, + T::BaseLayout: PyBorrowFlagLayout, { let cell = PyCell::internal_new(py)?; self.init_class(&mut *cell); @@ -127,7 +128,7 @@ impl PyClassInitializer { } impl PyObjectInit for PyClassInitializer { - fn init_class>(self, layout: &mut L) { + fn init_class>(self, layout: &mut L) { let Self { init, super_init } = self; unsafe { layout.py_init(init); @@ -152,7 +153,7 @@ where impl From<(S, B)> for PyClassInitializer where S: PyClass + PyTypeInfo, - S::BaseLayout: PyObjectSizedLayout, + S::BaseLayout: PySizedLayout, B: PyClass + PyTypeInfo>, B::BaseType: PyTypeInfo>, { diff --git a/src/type_object.rs b/src/type_object.rs index 1570c526150..59d90c1f8d7 100644 --- a/src/type_object.rs +++ b/src/type_object.rs @@ -9,12 +9,12 @@ use std::cell::UnsafeCell; use std::ptr::NonNull; use std::sync::atomic::{AtomicBool, Ordering}; -/// `T: PyObjectLayout` represents that `T` is a concrete representaion of `U` in Python heap. +/// `T: PyLayout` represents that `T` is a concrete representaion of `U` in Python heap. /// E.g., `PyCell` is a concrete representaion of all `pyclass`es, and `ffi::PyObject` /// is of `PyAny`. /// /// This trait is intended to be used internally. -pub unsafe trait PyObjectLayout { +pub unsafe trait PyLayout { const IS_NATIVE_TYPE: bool = true; fn get_super_or(&mut self) -> Option<&mut T::BaseLayout> { None @@ -26,12 +26,14 @@ pub unsafe trait PyObjectLayout { unsafe fn unchecked_mut(&self) -> &mut T; } -/// `T: PyObjectSizedLayout` represents `T` is not a instance of +/// `T: PySizedLayout` represents `T` is not a instance of /// [`PyVarObject`](https://docs.python.org/3.8/c-api/structures.html?highlight=pyvarobject#c.PyVarObject). /// , in addition that `T` is a concrete representaion of `U`. -/// -/// `pyclass`es need this trait for their base class. -pub trait PyObjectSizedLayout: PyObjectLayout + Sized {} +pub trait PySizedLayout: PyLayout + Sized {} + +/// Marker type indicates that `Self` can be a baselayout of PyClass. +/// This trait assumes a certain layout and thus is unsafe. +pub unsafe trait PyBorrowFlagLayout: PyLayout + Sized {} /// Our custom type flags #[doc(hidden)] @@ -99,10 +101,10 @@ pub unsafe trait PyTypeInfo: Sized { type BaseType: PyTypeInfo + PyTypeObject; /// Layout - type Layout: PyObjectLayout; + type Layout: PyLayout; /// Layout of Basetype. - type BaseLayout: PyObjectLayout; + type BaseLayout: PySizedLayout; /// Initializer for layout type Initializer: PyObjectInit; diff --git a/src/types/any.rs b/src/types/any.rs index 9a1cd113277..250e1f9f063 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -23,7 +23,7 @@ use crate::{ffi, PyObject}; /// ``` #[repr(transparent)] pub struct PyAny(PyObject, Unsendable); -unsafe impl crate::type_object::PyObjectLayout for ffi::PyObject { +unsafe impl crate::type_object::PyLayout for ffi::PyObject { unsafe fn unchecked_ref(&self) -> &PyAny { &*((&self) as *const &Self as *const _) } @@ -31,7 +31,7 @@ unsafe impl crate::type_object::PyObjectLayout for ffi::PyObject { &mut *((&self) as *const &Self as *const _ as *mut _) } } -impl crate::type_object::PyObjectSizedLayout for ffi::PyObject {} +impl crate::type_object::PySizedLayout for ffi::PyObject {} pyobject_native_type_named!(PyAny); pyobject_native_type_convert!( PyAny, diff --git a/src/types/mod.rs b/src/types/mod.rs index 1e7c247df35..7484132f120 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -58,7 +58,7 @@ macro_rules! pyobject_native_type_named ( macro_rules! impl_layout { ($name: ty, $layout: path) => { - unsafe impl $crate::type_object::PyObjectLayout<$name> for $layout { + unsafe impl $crate::type_object::PyLayout<$name> for $layout { unsafe fn unchecked_ref(&self) -> &$name { &*((&self) as *const &Self as *const _) } @@ -73,11 +73,11 @@ macro_rules! impl_layout { macro_rules! pyobject_native_type { ($name: ty, $layout: path, $typeobject: expr, $module: expr, $checkfunction: path $(,$type_param: ident)*) => { impl_layout!($name, $layout); - impl $crate::type_object::PyObjectSizedLayout<$name> for $layout {} + impl $crate::type_object::PySizedLayout<$name> for $layout {} impl $crate::derive_utils::PyBaseTypeUtils for $name { type Dict = $crate::pyclass_slots::PyClassDummySlot; type WeakRef = $crate::pyclass_slots::PyClassDummySlot; - type Layout = $crate::pycell::PyCellBase<$name>; + type LayoutAsBase = $crate::pycell::PyCellBase<$name>; type BaseNativeType = $name; } pyobject_native_type_named!($name $(,$type_param)*);