Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type_object: remove layout and base type from PyTypeInfo #1596

Merged
merged 1 commit into from
May 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,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