Skip to content

Commit

Permalink
Merge pull request #1596 from davidhewitt/remove-pytypeinfo-layout
Browse files Browse the repository at this point in the history
type_object: remove layout and base type from PyTypeInfo
  • Loading branch information
davidhewitt authored May 7, 2021
2 parents eb251a2 + 7536554 commit 4613b3d
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 201 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `PyMethodDef_INIT` [#1426](https://github.com/PyO3/pyo3/pull/1426)
- `PyTypeObject_INIT` [#1429](https://github.com/PyO3/pyo3/pull/1429)
- `PyObject_Check`, `PySuper_Check`, and `FreeFunc` [#1438](https://github.com/PyO3/pyo3/pull/1438)
- Remove pyclass implementation details `Type`, `DESCRIPTION`, and `FLAGS` from `PyTypeInfo`. [#1456](https://github.com/PyO3/pyo3/pull/1456)
- Remove pyclass implementation details from `PyTypeInfo`:
- `Type`, `DESCRIPTION`, and `FLAGS` [#1456](https://github.com/PyO3/pyo3/pull/1456)
- `BaseType`, `BaseLayout`, `Layout`, `Initializer` [#1596](https://github.com/PyO3/pyo3/pull/1596)
- Remove `__doc__` from module's `__all__`. [#1509](https://github.com/PyO3/pyo3/pull/1509)
- Remove `PYO3_CROSS_INCLUDE_DIR` environment variable and the associated C header parsing functionality.

Expand Down
6 changes: 2 additions & 4 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -723,10 +723,6 @@ struct MyClass {
impl pyo3::pyclass::PyClassAlloc for MyClass {}

unsafe impl pyo3::PyTypeInfo for MyClass {
type BaseType = PyAny;
type BaseLayout = pyo3::pycell::PyCellBase<PyAny>;
type Layout = PyCell<Self>;
type Initializer = PyClassInitializer<Self>;
type AsRefTarget = PyCell<Self>;

const NAME: &'static str = "MyClass";
Expand Down Expand Up @@ -757,6 +753,8 @@ impl pyo3::class::impl_::PyClassImpl for MyClass {
const IS_GC: bool = false;
const IS_BASETYPE: bool = false;
const IS_SUBCLASS: bool = false;
type Layout = PyCell<MyClass>;
type BaseType = PyAny;
type ThreadChecker = pyo3::class::impl_::ThreadCheckerStub<MyClass>;

fn for_each_method_def(visitor: impl FnMut(&pyo3::class::PyMethodDefType)) {
Expand Down
19 changes: 6 additions & 13 deletions pyo3-macros-backend/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,14 +312,14 @@ fn impl_class(
let weakref = if attr.has_weaklist {
quote! { pyo3::pyclass_slots::PyClassWeakRefSlot }
} else if attr.has_extends {
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::WeakRef }
quote! { <Self::BaseType as pyo3::class::impl_::PyClassBaseType>::WeakRef }
} else {
quote! { pyo3::pyclass_slots::PyClassDummySlot }
};
let dict = if attr.has_dict {
quote! { pyo3::pyclass_slots::PyClassDictSlot }
} else if attr.has_extends {
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::Dict }
quote! { <Self::BaseType as pyo3::class::impl_::PyClassBaseType>::Dict }
} else {
quote! { pyo3::pyclass_slots::PyClassDummySlot }
};
Expand Down Expand Up @@ -358,13 +358,8 @@ fn impl_class(
};

let base = &attr.base;
let base_layout = if attr.has_extends {
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::LayoutAsBase }
} else {
quote! { pyo3::pycell::PyCellBase<pyo3::PyAny> }
};
let base_nativetype = if attr.has_extends {
quote! { <Self::BaseType as pyo3::derive_utils::PyBaseTypeUtils>::BaseNativeType }
quote! { <Self::BaseType as pyo3::class::impl_::PyClassBaseType>::BaseNativeType }
} else {
quote! { pyo3::PyAny }
};
Expand All @@ -386,7 +381,7 @@ fn impl_class(
quote! { pyo3::class::impl_::ThreadCheckerImpl<#cls> }
} else if attr.has_extends {
quote! {
pyo3::class::impl_::ThreadCheckerInherited<#cls, <#cls as pyo3::type_object::PyTypeInfo>::BaseType>
pyo3::class::impl_::ThreadCheckerInherited<#cls, <#cls as pyo3::class::impl_::PyClassImpl>::BaseType>
}
} else {
quote! { pyo3::class::impl_::ThreadCheckerStub<#cls> }
Expand All @@ -398,10 +393,6 @@ fn impl_class(

Ok(quote! {
unsafe impl pyo3::type_object::PyTypeInfo for #cls {
type BaseType = #base;
type Layout = pyo3::PyCell<Self>;
type BaseLayout = #base_layout;
type Initializer = pyo3::pyclass_init::PyClassInitializer<Self>;
type AsRefTarget = pyo3::PyCell<Self>;

const NAME: &'static str = #cls_name;
Expand Down Expand Up @@ -441,6 +432,8 @@ fn impl_class(
const IS_BASETYPE: bool = #is_basetype;
const IS_SUBCLASS: bool = #is_subclass;

type Layout = PyCell<Self>;
type BaseType = #base;
type ThreadChecker = #thread_checker;

fn for_each_method_def(visitor: impl FnMut(&pyo3::class::PyMethodDefType)) {
Expand Down
38 changes: 35 additions & 3 deletions src/class/impl_.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// Copyright (c) 2017-present PyO3 Project and Contributors

use crate::{derive_utils::PyBaseTypeUtils, ffi, PyMethodDefType, PyNativeType};
use crate::{
ffi,
pycell::PyCellLayout,
pyclass_init::PyObjectInit,
type_object::{PyLayout, PyTypeObject},
PyClass, PyMethodDefType, PyNativeType, PyTypeInfo,
};
use std::{marker::PhantomData, thread};

/// This type is used as a "dummy" type on which dtolnay specializations are
Expand Down Expand Up @@ -44,6 +50,12 @@ pub trait PyClassImpl: Sized {
/// #[pyclass(extends=...)]
const IS_SUBCLASS: bool = false;

/// Layout
type Layout: PyLayout<Self>;

/// Base class
type BaseType: PyTypeInfo + PyTypeObject + PyClassBaseType;

/// This handles following two situations:
/// 1. In case `T` is `Send`, stub `ThreadChecker` is used and does nothing.
/// This implementation is used by default. Compile fails if `T: !Send`.
Expand Down Expand Up @@ -241,9 +253,9 @@ impl<T> PyClassThreadChecker<T> for ThreadCheckerImpl<T> {
/// Thread checker for types that have `Send` and `extends=...`.
/// Ensures that `T: Send` and the parent is not accessed by another thread.
#[doc(hidden)]
pub struct ThreadCheckerInherited<T: Send, U: PyBaseTypeUtils>(PhantomData<T>, U::ThreadChecker);
pub struct ThreadCheckerInherited<T: Send, U: PyClassBaseType>(PhantomData<T>, U::ThreadChecker);

impl<T: Send, U: PyBaseTypeUtils> PyClassThreadChecker<T> for ThreadCheckerInherited<T, U> {
impl<T: Send, U: PyClassBaseType> PyClassThreadChecker<T> for ThreadCheckerInherited<T, U> {
fn ensure(&self) {
self.1.ensure();
}
Expand All @@ -252,3 +264,23 @@ impl<T: Send, U: PyBaseTypeUtils> PyClassThreadChecker<T> for ThreadCheckerInher
}
private_impl! {}
}

/// Trait denoting that this class is suitable to be used as a base type for PyClass.
pub trait PyClassBaseType: Sized {
type Dict;
type WeakRef;
type LayoutAsBase: PyCellLayout<Self>;
type BaseNativeType;
type ThreadChecker: PyClassThreadChecker<Self>;
type Initializer: PyObjectInit<Self>;
}

/// All PyClasses can be used as a base type.
impl<T: PyClass> PyClassBaseType for T {
type Dict = T::Dict;
type WeakRef = T::WeakRef;
type LayoutAsBase = crate::pycell::PyCellInner<T>;
type BaseNativeType = T::BaseNativeType;
type ThreadChecker = T::ThreadChecker;
type Initializer = crate::pyclass_init::PyClassInitializer<Self>;
}
19 changes: 0 additions & 19 deletions src/derive_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

//! Functionality for the code generated by the derive backend
use crate::class::impl_::PyClassThreadChecker;
use crate::err::{PyErr, PyResult};
use crate::exceptions::PyTypeError;
use crate::instance::PyNativeType;
Expand Down Expand Up @@ -326,24 +325,6 @@ impl ModuleDef {
}
}

/// Utilities for basetype
#[doc(hidden)]
pub trait PyBaseTypeUtils: Sized {
type Dict;
type WeakRef;
type LayoutAsBase;
type BaseNativeType;
type ThreadChecker: PyClassThreadChecker<Self>;
}

impl<T: PyClass> PyBaseTypeUtils for T {
type Dict = T::Dict;
type WeakRef = T::WeakRef;
type LayoutAsBase = crate::pycell::PyCellInner<T>;
type BaseNativeType = T::BaseNativeType;
type ThreadChecker = T::ThreadChecker;
}

/// Utility trait to enable &PyClass as a pymethod/function argument
#[doc(hidden)]
pub trait ExtractExt<'a> {
Expand Down
6 changes: 1 addition & 5 deletions src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use crate::conversion::{PyTryFrom, ToBorrowedObject};
use crate::err::{PyDowncastError, PyErr, PyResult};
use crate::gil;
use crate::pycell::{PyBorrowError, PyBorrowMutError, PyCell};
use crate::type_object::PyBorrowFlagLayout;
use crate::types::{PyDict, PyTuple};
use crate::{
ffi, AsPyPointer, FromPyObject, IntoPy, IntoPyPointer, PyAny, PyClass, PyClassInitializer,
Expand Down Expand Up @@ -59,10 +58,7 @@ where
T: PyClass,
{
/// Create a new instance `Py<T>` of a `#[pyclass]` on the Python heap.
pub fn new(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<Py<T>>
where
T::BaseLayout: PyBorrowFlagLayout<T::BaseType>,
{
pub fn new(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<Py<T>> {
let initializer = value.into();
let obj = initializer.create_cell(py)?;
let ob = unsafe { Py::from_owned_ptr(py, obj as _) };
Expand Down
Loading

0 comments on commit 4613b3d

Please sign in to comment.