Use PyBorrowFlagLayout to ensure the baseclass has a borrow flag
This commit is contained in:
parent
0e3f7cbc30
commit
68a3b15943
|
@ -362,7 +362,7 @@ fn impl_class(
|
|||
quote! { 0 }
|
||||
};
|
||||
let base_layout = if attr.has_extends {
|
||||
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::Layout }
|
||||
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::LayoutAsBase }
|
||||
} else {
|
||||
quote! { pyo3::pycell::PyCellBase<pyo3::types::PyAny> }
|
||||
};
|
||||
|
|
|
@ -223,13 +223,13 @@ impl GetPropertyValue for PyObject {
|
|||
pub trait PyBaseTypeUtils {
|
||||
type Dict;
|
||||
type WeakRef;
|
||||
type Layout;
|
||||
type LayoutAsBase;
|
||||
type BaseNativeType;
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyBaseTypeUtils for T {
|
||||
type Dict = T::Dict;
|
||||
type WeakRef = T::WeakRef;
|
||||
type Layout = crate::pycell::PyCellInner<T>;
|
||||
type LayoutAsBase = crate::pycell::PyCellInner<T>;
|
||||
type BaseNativeType = T::BaseNativeType;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<T> Py<T> {
|
|||
pub fn new(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<Py<T>>
|
||||
where
|
||||
T: PyClass,
|
||||
T::BaseLayout: crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
T::BaseLayout: PyBorrowFlagLayout<T::BaseType>,
|
||||
{
|
||||
let initializer = value.into();
|
||||
let obj = unsafe { initializer.create_cell(py)? };
|
||||
|
|
|
@ -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<T: PyTypeInfo> {
|
|||
borrow_flag: Cell<BorrowFlag>,
|
||||
}
|
||||
|
||||
unsafe impl<T> PyObjectLayout<T> for PyCellBase<T>
|
||||
unsafe impl<T> PyLayout<T> for PyCellBase<T>
|
||||
where
|
||||
T: PyTypeInfo + PyNativeType,
|
||||
T::Layout: PyObjectSizedLayout<T>,
|
||||
T::Layout: PySizedLayout<T>,
|
||||
{
|
||||
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<T> PyObjectSizedLayout<T> for PyCellBase<T>
|
||||
// Thes impls ensures `PyCellBase` can be a base type.
|
||||
impl<T> PySizedLayout<T> for PyCellBase<T>
|
||||
where
|
||||
T: PyTypeInfo + PyNativeType,
|
||||
T::Layout: PyObjectSizedLayout<T>,
|
||||
T::Layout: PySizedLayout<T>,
|
||||
{
|
||||
}
|
||||
|
||||
unsafe impl<T> PyBorrowFlagLayout<T> for PyCellBase<T>
|
||||
where
|
||||
T: PyTypeInfo + PyNativeType,
|
||||
T::Layout: PySizedLayout<T>,
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -56,7 +63,7 @@ impl<T: PyClass> AsPyPointer for PyCellInner<T> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: PyClass> PyObjectLayout<T> for PyCellInner<T> {
|
||||
unsafe impl<T: PyClass> PyLayout<T> for PyCellInner<T> {
|
||||
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<T: PyClass> PyObjectLayout<T> for PyCellInner<T> {
|
|||
}
|
||||
}
|
||||
|
||||
// This impl ensures `PyCellInner` can be a base type.
|
||||
impl<T: PyClass> PyObjectSizedLayout<T> for PyCellInner<T> {}
|
||||
// Thes impls ensures `PyCellInner` can be a base type.
|
||||
impl<T: PyClass> PySizedLayout<T> for PyCellInner<T> {}
|
||||
unsafe impl<T: PyClass> PyBorrowFlagLayout<T> for PyCellInner<T> {}
|
||||
|
||||
impl<T: PyClass> PyCellInner<T> {
|
||||
fn get_borrow_flag(&self) -> BorrowFlag {
|
||||
|
@ -164,7 +172,7 @@ impl<T: PyClass> PyCell<T> {
|
|||
///
|
||||
pub fn new(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&Self>
|
||||
where
|
||||
T::BaseLayout: crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
T::BaseLayout: PyBorrowFlagLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into();
|
||||
|
@ -325,9 +333,12 @@ impl<T: PyClass> PyCell<T> {
|
|||
std::mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut())
|
||||
}
|
||||
|
||||
/// Allocates new PyCell without initilizing value.
|
||||
/// Requires `T::BaseLayout: PyBorrowFlagLayout<T::BaseType>` 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::BaseType>,
|
||||
T::BaseLayout: PyBorrowFlagLayout<T::BaseType>,
|
||||
{
|
||||
let base = T::alloc(py);
|
||||
if base.is_null() {
|
||||
|
@ -342,7 +353,7 @@ impl<T: PyClass> PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: PyClass> PyObjectLayout<T> for PyCell<T> {
|
||||
unsafe impl<T: PyClass> PyLayout<T> for PyCell<T> {
|
||||
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: (),
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<T: PyTypeInfo>: Sized {
|
||||
fn init_class<L: PyObjectLayout<T>>(self, layout: &mut L);
|
||||
fn init_class<L: PyLayout<T>>(self, layout: &mut L);
|
||||
private_decl! {}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ pub trait PyObjectInit<T: PyTypeInfo>: Sized {
|
|||
pub struct PyNativeTypeInitializer<T: PyTypeInfo>(PhantomData<T>);
|
||||
|
||||
impl<T: PyTypeInfo> PyObjectInit<T> for PyNativeTypeInitializer<T> {
|
||||
fn init_class<L: PyObjectLayout<T>>(self, _layout: &mut L) {}
|
||||
fn init_class<L: PyLayout<T>>(self, _layout: &mut L) {}
|
||||
private_impl! {}
|
||||
}
|
||||
|
||||
|
@ -108,17 +108,18 @@ impl<T: PyClass> PyClassInitializer<T> {
|
|||
pub fn add_subclass<S>(self, subclass_value: S) -> PyClassInitializer<S>
|
||||
where
|
||||
S: PyClass + PyTypeInfo<BaseType = T>,
|
||||
S::BaseLayout: PyObjectSizedLayout<T>,
|
||||
S::BaseLayout: PySizedLayout<T>,
|
||||
S::BaseType: PyTypeInfo<Initializer = Self>,
|
||||
{
|
||||
PyClassInitializer::new(subclass_value, self)
|
||||
}
|
||||
|
||||
// Create a new PyCell + initialize it
|
||||
#[doc(hidden)]
|
||||
pub unsafe fn create_cell(self, py: Python) -> PyResult<*mut PyCell<T>>
|
||||
where
|
||||
T: PyClass,
|
||||
T::BaseLayout: PyObjectSizedLayout<T::BaseType>,
|
||||
T::BaseLayout: PyBorrowFlagLayout<T::BaseType>,
|
||||
{
|
||||
let cell = PyCell::internal_new(py)?;
|
||||
self.init_class(&mut *cell);
|
||||
|
@ -127,7 +128,7 @@ impl<T: PyClass> PyClassInitializer<T> {
|
|||
}
|
||||
|
||||
impl<T: PyClass> PyObjectInit<T> for PyClassInitializer<T> {
|
||||
fn init_class<L: PyObjectLayout<T>>(self, layout: &mut L) {
|
||||
fn init_class<L: PyLayout<T>>(self, layout: &mut L) {
|
||||
let Self { init, super_init } = self;
|
||||
unsafe {
|
||||
layout.py_init(init);
|
||||
|
@ -152,7 +153,7 @@ where
|
|||
impl<S, B> From<(S, B)> for PyClassInitializer<S>
|
||||
where
|
||||
S: PyClass + PyTypeInfo<BaseType = B>,
|
||||
S::BaseLayout: PyObjectSizedLayout<B>,
|
||||
S::BaseLayout: PySizedLayout<B>,
|
||||
B: PyClass + PyTypeInfo<Initializer = PyClassInitializer<B>>,
|
||||
B::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<B::BaseType>>,
|
||||
{
|
||||
|
|
|
@ -9,12 +9,12 @@ use std::cell::UnsafeCell;
|
|||
use std::ptr::NonNull;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
/// `T: PyObjectLayout<U>` represents that `T` is a concrete representaion of `U` in Python heap.
|
||||
/// `T: PyLayout<U>` 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<T: PyTypeInfo> {
|
||||
pub unsafe trait PyLayout<T: PyTypeInfo> {
|
||||
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<T: PyTypeInfo> {
|
|||
unsafe fn unchecked_mut(&self) -> &mut T;
|
||||
}
|
||||
|
||||
/// `T: PyObjectSizedLayout<U>` represents `T` is not a instance of
|
||||
/// `T: PySizedLayout<U>` 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<T: PyTypeInfo>: PyObjectLayout<T> + Sized {}
|
||||
pub trait PySizedLayout<T: PyTypeInfo>: PyLayout<T> + 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<T: PyTypeInfo>: PyLayout<T> + Sized {}
|
||||
|
||||
/// Our custom type flags
|
||||
#[doc(hidden)]
|
||||
|
@ -99,10 +101,10 @@ pub unsafe trait PyTypeInfo: Sized {
|
|||
type BaseType: PyTypeInfo + PyTypeObject;
|
||||
|
||||
/// Layout
|
||||
type Layout: PyObjectLayout<Self>;
|
||||
type Layout: PyLayout<Self>;
|
||||
|
||||
/// Layout of Basetype.
|
||||
type BaseLayout: PyObjectLayout<Self::BaseType>;
|
||||
type BaseLayout: PySizedLayout<Self::BaseType>;
|
||||
|
||||
/// Initializer for layout
|
||||
type Initializer: PyObjectInit<Self>;
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::{ffi, PyObject};
|
|||
/// ```
|
||||
#[repr(transparent)]
|
||||
pub struct PyAny(PyObject, Unsendable);
|
||||
unsafe impl crate::type_object::PyObjectLayout<PyAny> for ffi::PyObject {
|
||||
unsafe impl crate::type_object::PyLayout<PyAny> 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<PyAny> for ffi::PyObject {
|
|||
&mut *((&self) as *const &Self as *const _ as *mut _)
|
||||
}
|
||||
}
|
||||
impl crate::type_object::PyObjectSizedLayout<PyAny> for ffi::PyObject {}
|
||||
impl crate::type_object::PySizedLayout<PyAny> for ffi::PyObject {}
|
||||
pyobject_native_type_named!(PyAny);
|
||||
pyobject_native_type_convert!(
|
||||
PyAny,
|
||||
|
|
|
@ -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)*);
|
||||
|
|
Loading…
Reference in New Issue