Use PyBorrowFlagLayout to ensure the baseclass has a borrow flag

This commit is contained in:
kngwyu 2020-02-23 00:56:58 +09:00
parent 0e3f7cbc30
commit 68a3b15943
10 changed files with 55 additions and 39 deletions

View File

@ -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> }
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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)? };

View File

@ -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: (),
}

View File

@ -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;

View File

@ -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>>,
{

View File

@ -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>;

View File

@ -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,

View File

@ -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)*);