Skip to content

Commit 68a3b15

Browse files
committed
Use PyBorrowFlagLayout to ensure the baseclass has a borrow flag
1 parent 0e3f7cb commit 68a3b15

File tree

10 files changed

+55
-39
lines changed

10 files changed

+55
-39
lines changed

pyo3-derive-backend/src/pyclass.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ fn impl_class(
362362
quote! { 0 }
363363
};
364364
let base_layout = if attr.has_extends {
365-
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::Layout }
365+
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::LayoutAsBase }
366366
} else {
367367
quote! { pyo3::pycell::PyCellBase<pyo3::types::PyAny> }
368368
};

src/derive_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,13 +223,13 @@ impl GetPropertyValue for PyObject {
223223
pub trait PyBaseTypeUtils {
224224
type Dict;
225225
type WeakRef;
226-
type Layout;
226+
type LayoutAsBase;
227227
type BaseNativeType;
228228
}
229229

230230
impl<T: PyClass> PyBaseTypeUtils for T {
231231
type Dict = T::Dict;
232232
type WeakRef = T::WeakRef;
233-
type Layout = crate::pycell::PyCellInner<T>;
233+
type LayoutAsBase = crate::pycell::PyCellInner<T>;
234234
type BaseNativeType = T::BaseNativeType;
235235
}

src/freelist.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
use crate::ffi;
66
use crate::pyclass::{tp_free_fallback, PyClassAlloc};
7-
use crate::type_object::{PyObjectLayout, PyTypeInfo};
7+
use crate::type_object::{PyLayout, PyTypeInfo};
88
use crate::Python;
99
use std::mem;
1010
use std::os::raw::c_void;

src/instance.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::err::{PyErr, PyResult};
33
use crate::gil;
44
use crate::object::PyObject;
55
use crate::objectprotocol::ObjectProtocol;
6-
use crate::type_object::PyDowncastImpl;
6+
use crate::type_object::{PyBorrowFlagLayout, PyDowncastImpl};
77
use crate::types::PyAny;
88
use crate::{
99
ffi, AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, PyCell, PyClass, PyClassInitializer,
@@ -39,7 +39,7 @@ impl<T> Py<T> {
3939
pub fn new(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<Py<T>>
4040
where
4141
T: PyClass,
42-
T::BaseLayout: crate::type_object::PyObjectSizedLayout<T::BaseType>,
42+
T::BaseLayout: PyBorrowFlagLayout<T::BaseType>,
4343
{
4444
let initializer = value.into();
4545
let obj = unsafe { initializer.create_cell(py)? };

src/pycell.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject};
33
use crate::pyclass_init::PyClassInitializer;
44
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
5-
use crate::type_object::{PyDowncastImpl, PyObjectLayout, PyObjectSizedLayout, PyTypeInfo};
5+
use crate::type_object::{PyBorrowFlagLayout, PyDowncastImpl, PyLayout, PySizedLayout, PyTypeInfo};
66
use crate::types::PyAny;
77
use crate::{ffi, FromPy, PyClass, PyErr, PyNativeType, PyObject, PyResult, Python};
88
use std::cell::{Cell, UnsafeCell};
@@ -17,10 +17,10 @@ pub struct PyCellBase<T: PyTypeInfo> {
1717
borrow_flag: Cell<BorrowFlag>,
1818
}
1919

20-
unsafe impl<T> PyObjectLayout<T> for PyCellBase<T>
20+
unsafe impl<T> PyLayout<T> for PyCellBase<T>
2121
where
2222
T: PyTypeInfo + PyNativeType,
23-
T::Layout: PyObjectSizedLayout<T>,
23+
T::Layout: PySizedLayout<T>,
2424
{
2525
const IS_NATIVE_TYPE: bool = true;
2626
unsafe fn unchecked_ref(&self) -> &T {
@@ -31,11 +31,18 @@ where
3131
}
3232
}
3333

34-
// This impl ensures `PyCellBase` can be a base type.
35-
impl<T> PyObjectSizedLayout<T> for PyCellBase<T>
34+
// Thes impls ensures `PyCellBase` can be a base type.
35+
impl<T> PySizedLayout<T> for PyCellBase<T>
3636
where
3737
T: PyTypeInfo + PyNativeType,
38-
T::Layout: PyObjectSizedLayout<T>,
38+
T::Layout: PySizedLayout<T>,
39+
{
40+
}
41+
42+
unsafe impl<T> PyBorrowFlagLayout<T> for PyCellBase<T>
43+
where
44+
T: PyTypeInfo + PyNativeType,
45+
T::Layout: PySizedLayout<T>,
3946
{
4047
}
4148

@@ -56,7 +63,7 @@ impl<T: PyClass> AsPyPointer for PyCellInner<T> {
5663
}
5764
}
5865

59-
unsafe impl<T: PyClass> PyObjectLayout<T> for PyCellInner<T> {
66+
unsafe impl<T: PyClass> PyLayout<T> for PyCellInner<T> {
6067
const IS_NATIVE_TYPE: bool = false;
6168
fn get_super_or(&mut self) -> Option<&mut T::BaseLayout> {
6269
Some(&mut self.ob_base)
@@ -76,8 +83,9 @@ unsafe impl<T: PyClass> PyObjectLayout<T> for PyCellInner<T> {
7683
}
7784
}
7885

79-
// This impl ensures `PyCellInner` can be a base type.
80-
impl<T: PyClass> PyObjectSizedLayout<T> for PyCellInner<T> {}
86+
// Thes impls ensures `PyCellInner` can be a base type.
87+
impl<T: PyClass> PySizedLayout<T> for PyCellInner<T> {}
88+
unsafe impl<T: PyClass> PyBorrowFlagLayout<T> for PyCellInner<T> {}
8189

8290
impl<T: PyClass> PyCellInner<T> {
8391
fn get_borrow_flag(&self) -> BorrowFlag {
@@ -164,7 +172,7 @@ impl<T: PyClass> PyCell<T> {
164172
///
165173
pub fn new(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&Self>
166174
where
167-
T::BaseLayout: crate::type_object::PyObjectSizedLayout<T::BaseType>,
175+
T::BaseLayout: PyBorrowFlagLayout<T::BaseType>,
168176
{
169177
unsafe {
170178
let initializer = value.into();
@@ -325,9 +333,12 @@ impl<T: PyClass> PyCell<T> {
325333
std::mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut())
326334
}
327335

336+
/// Allocates new PyCell without initilizing value.
337+
/// Requires `T::BaseLayout: PyBorrowFlagLayout<T::BaseType>` to ensure that
338+
/// this layout has a borrow flag.
328339
pub(crate) unsafe fn internal_new(py: Python) -> PyResult<*mut Self>
329340
where
330-
T::BaseLayout: crate::type_object::PyObjectSizedLayout<T::BaseType>,
341+
T::BaseLayout: PyBorrowFlagLayout<T::BaseType>,
331342
{
332343
let base = T::alloc(py);
333344
if base.is_null() {
@@ -342,7 +353,7 @@ impl<T: PyClass> PyCell<T> {
342353
}
343354
}
344355

345-
unsafe impl<T: PyClass> PyObjectLayout<T> for PyCell<T> {
356+
unsafe impl<T: PyClass> PyLayout<T> for PyCell<T> {
346357
const IS_NATIVE_TYPE: bool = false;
347358
fn get_super_or(&mut self) -> Option<&mut T::BaseLayout> {
348359
Some(&mut self.inner.ob_base)
@@ -598,6 +609,7 @@ impl BorrowFlag {
598609
}
599610
}
600611

612+
/// An error returned by [`PyCell::try_borrow`](struct.PyCell.html#method.try_borrow).
601613
pub struct PyBorrowError {
602614
_private: (),
603615
}
@@ -614,6 +626,7 @@ impl fmt::Display for PyBorrowError {
614626
}
615627
}
616628

629+
/// An error returned by [`PyCell::try_borrow_mut`](struct.PyCell.html#method.try_borrow_mut).
617630
pub struct PyBorrowMutError {
618631
_private: (),
619632
}

src/pyclass.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! `PyClass` trait
22
use crate::class::methods::{PyMethodDefType, PyMethodsProtocol};
33
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
4-
use crate::type_object::{type_flags, PyObjectLayout};
4+
use crate::type_object::{type_flags, PyLayout};
55
use crate::{class, ffi, gil, PyCell, PyErr, PyNativeType, PyResult, PyTypeInfo, Python};
66
use std::ffi::CString;
77
use std::os::raw::c_void;

src/pyclass_init.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Initialization utilities for `#[pyclass]`.
2-
use crate::type_object::{PyObjectLayout, PyObjectSizedLayout, PyTypeInfo};
2+
use crate::type_object::{PyBorrowFlagLayout, PyLayout, PySizedLayout, PyTypeInfo};
33
use crate::{PyCell, PyClass, PyResult, Python};
44
use std::marker::PhantomData;
55

@@ -8,15 +8,15 @@ use std::marker::PhantomData;
88
/// This trait is intended to use internally for distinguishing `#[pyclass]` and
99
/// Python native types.
1010
pub trait PyObjectInit<T: PyTypeInfo>: Sized {
11-
fn init_class<L: PyObjectLayout<T>>(self, layout: &mut L);
11+
fn init_class<L: PyLayout<T>>(self, layout: &mut L);
1212
private_decl! {}
1313
}
1414

1515
/// Initializer for Python native type, like `PyDict`.
1616
pub struct PyNativeTypeInitializer<T: PyTypeInfo>(PhantomData<T>);
1717

1818
impl<T: PyTypeInfo> PyObjectInit<T> for PyNativeTypeInitializer<T> {
19-
fn init_class<L: PyObjectLayout<T>>(self, _layout: &mut L) {}
19+
fn init_class<L: PyLayout<T>>(self, _layout: &mut L) {}
2020
private_impl! {}
2121
}
2222

@@ -108,17 +108,18 @@ impl<T: PyClass> PyClassInitializer<T> {
108108
pub fn add_subclass<S>(self, subclass_value: S) -> PyClassInitializer<S>
109109
where
110110
S: PyClass + PyTypeInfo<BaseType = T>,
111-
S::BaseLayout: PyObjectSizedLayout<T>,
111+
S::BaseLayout: PySizedLayout<T>,
112112
S::BaseType: PyTypeInfo<Initializer = Self>,
113113
{
114114
PyClassInitializer::new(subclass_value, self)
115115
}
116116

117+
// Create a new PyCell + initialize it
117118
#[doc(hidden)]
118119
pub unsafe fn create_cell(self, py: Python) -> PyResult<*mut PyCell<T>>
119120
where
120121
T: PyClass,
121-
T::BaseLayout: PyObjectSizedLayout<T::BaseType>,
122+
T::BaseLayout: PyBorrowFlagLayout<T::BaseType>,
122123
{
123124
let cell = PyCell::internal_new(py)?;
124125
self.init_class(&mut *cell);
@@ -127,7 +128,7 @@ impl<T: PyClass> PyClassInitializer<T> {
127128
}
128129

129130
impl<T: PyClass> PyObjectInit<T> for PyClassInitializer<T> {
130-
fn init_class<L: PyObjectLayout<T>>(self, layout: &mut L) {
131+
fn init_class<L: PyLayout<T>>(self, layout: &mut L) {
131132
let Self { init, super_init } = self;
132133
unsafe {
133134
layout.py_init(init);
@@ -152,7 +153,7 @@ where
152153
impl<S, B> From<(S, B)> for PyClassInitializer<S>
153154
where
154155
S: PyClass + PyTypeInfo<BaseType = B>,
155-
S::BaseLayout: PyObjectSizedLayout<B>,
156+
S::BaseLayout: PySizedLayout<B>,
156157
B: PyClass + PyTypeInfo<Initializer = PyClassInitializer<B>>,
157158
B::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<B::BaseType>>,
158159
{

src/type_object.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ use std::cell::UnsafeCell;
99
use std::ptr::NonNull;
1010
use std::sync::atomic::{AtomicBool, Ordering};
1111

12-
/// `T: PyObjectLayout<U>` represents that `T` is a concrete representaion of `U` in Python heap.
12+
/// `T: PyLayout<U>` represents that `T` is a concrete representaion of `U` in Python heap.
1313
/// E.g., `PyCell` is a concrete representaion of all `pyclass`es, and `ffi::PyObject`
1414
/// is of `PyAny`.
1515
///
1616
/// This trait is intended to be used internally.
17-
pub unsafe trait PyObjectLayout<T: PyTypeInfo> {
17+
pub unsafe trait PyLayout<T: PyTypeInfo> {
1818
const IS_NATIVE_TYPE: bool = true;
1919
fn get_super_or(&mut self) -> Option<&mut T::BaseLayout> {
2020
None
@@ -26,12 +26,14 @@ pub unsafe trait PyObjectLayout<T: PyTypeInfo> {
2626
unsafe fn unchecked_mut(&self) -> &mut T;
2727
}
2828

29-
/// `T: PyObjectSizedLayout<U>` represents `T` is not a instance of
29+
/// `T: PySizedLayout<U>` represents `T` is not a instance of
3030
/// [`PyVarObject`](https://docs.python.org/3.8/c-api/structures.html?highlight=pyvarobject#c.PyVarObject).
3131
/// , in addition that `T` is a concrete representaion of `U`.
32-
///
33-
/// `pyclass`es need this trait for their base class.
34-
pub trait PyObjectSizedLayout<T: PyTypeInfo>: PyObjectLayout<T> + Sized {}
32+
pub trait PySizedLayout<T: PyTypeInfo>: PyLayout<T> + Sized {}
33+
34+
/// Marker type indicates that `Self` can be a baselayout of PyClass.
35+
/// This trait assumes a certain layout and thus is unsafe.
36+
pub unsafe trait PyBorrowFlagLayout<T: PyTypeInfo>: PyLayout<T> + Sized {}
3537

3638
/// Our custom type flags
3739
#[doc(hidden)]
@@ -99,10 +101,10 @@ pub unsafe trait PyTypeInfo: Sized {
99101
type BaseType: PyTypeInfo + PyTypeObject;
100102

101103
/// Layout
102-
type Layout: PyObjectLayout<Self>;
104+
type Layout: PyLayout<Self>;
103105

104106
/// Layout of Basetype.
105-
type BaseLayout: PyObjectLayout<Self::BaseType>;
107+
type BaseLayout: PySizedLayout<Self::BaseType>;
106108

107109
/// Initializer for layout
108110
type Initializer: PyObjectInit<Self>;

src/types/any.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ use crate::{ffi, PyObject};
2323
/// ```
2424
#[repr(transparent)]
2525
pub struct PyAny(PyObject, Unsendable);
26-
unsafe impl crate::type_object::PyObjectLayout<PyAny> for ffi::PyObject {
26+
unsafe impl crate::type_object::PyLayout<PyAny> for ffi::PyObject {
2727
unsafe fn unchecked_ref(&self) -> &PyAny {
2828
&*((&self) as *const &Self as *const _)
2929
}
3030
unsafe fn unchecked_mut(&self) -> &mut PyAny {
3131
&mut *((&self) as *const &Self as *const _ as *mut _)
3232
}
3333
}
34-
impl crate::type_object::PyObjectSizedLayout<PyAny> for ffi::PyObject {}
34+
impl crate::type_object::PySizedLayout<PyAny> for ffi::PyObject {}
3535
pyobject_native_type_named!(PyAny);
3636
pyobject_native_type_convert!(
3737
PyAny,

src/types/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ macro_rules! pyobject_native_type_named (
5858

5959
macro_rules! impl_layout {
6060
($name: ty, $layout: path) => {
61-
unsafe impl $crate::type_object::PyObjectLayout<$name> for $layout {
61+
unsafe impl $crate::type_object::PyLayout<$name> for $layout {
6262
unsafe fn unchecked_ref(&self) -> &$name {
6363
&*((&self) as *const &Self as *const _)
6464
}
@@ -73,11 +73,11 @@ macro_rules! impl_layout {
7373
macro_rules! pyobject_native_type {
7474
($name: ty, $layout: path, $typeobject: expr, $module: expr, $checkfunction: path $(,$type_param: ident)*) => {
7575
impl_layout!($name, $layout);
76-
impl $crate::type_object::PyObjectSizedLayout<$name> for $layout {}
76+
impl $crate::type_object::PySizedLayout<$name> for $layout {}
7777
impl $crate::derive_utils::PyBaseTypeUtils for $name {
7878
type Dict = $crate::pyclass_slots::PyClassDummySlot;
7979
type WeakRef = $crate::pyclass_slots::PyClassDummySlot;
80-
type Layout = $crate::pycell::PyCellBase<$name>;
80+
type LayoutAsBase = $crate::pycell::PyCellBase<$name>;
8181
type BaseNativeType = $name;
8282
}
8383
pyobject_native_type_named!($name $(,$type_param)*);

0 commit comments

Comments
 (0)