Skip to content

Commit 4cba28d

Browse files
committed
add Sealed to pyclass traits
1 parent 86c48d3 commit 4cba28d

1 file changed

Lines changed: 30 additions & 5 deletions

File tree

src/impl_/pyclass.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,14 @@ pub trait PyClassImpl: Sized + 'static {
238238
fn lazy_type_object() -> &'static LazyTypeObject<Self>;
239239
}
240240

241+
mod generic_pyclass {
242+
use crate::PyClass;
243+
244+
pub trait Sealed {}
245+
246+
impl<T: PyClass> Sealed for T {}
247+
}
248+
241249
/// Iterator used to process all class items during type instantiation.
242250
pub struct PyClassItemsIter {
243251
/// Iteration state
@@ -305,7 +313,7 @@ impl Iterator for PyClassItemsIter {
305313
macro_rules! slot_fragment_trait {
306314
($trait_name:ident, $($default_method:tt)*) => {
307315
#[allow(non_camel_case_types, reason = "to match Python dunder names")]
308-
pub trait $trait_name<T>: Sized {
316+
pub trait $trait_name<T>: Sized + pymethods::Sealed {
309317
$($default_method)*
310318
}
311319

@@ -896,7 +904,7 @@ pub use generate_pyclass_richcompare_slot;
896904
///
897905
/// Do not implement this trait manually. Instead, use `#[pyclass(freelist = N)]`
898906
/// on a Rust struct to implement it.
899-
pub trait PyClassWithFreeList: PyClass {
907+
pub trait PyClassWithFreeList: PyClass + generic_pyclass::Sealed {
900908
fn get_free_list(py: Python<'_>) -> &'static Mutex<PyObjectFreeList>;
901909
}
902910

@@ -1003,7 +1011,7 @@ pub trait PyClassInventory: inventory::Collect {
10031011

10041012
// Items from #[pymethods] if not using inventory.
10051013
#[cfg(not(feature = "multiple-pymethods"))]
1006-
pub trait PyMethods<T> {
1014+
pub trait PyMethods<T>: pymethods::Sealed {
10071015
fn py_methods(self) -> &'static PyClassItems;
10081016
}
10091017

@@ -1017,6 +1025,15 @@ impl<T> PyMethods<T> for &'_ PyClassImplCollector<T> {
10171025
}
10181026
}
10191027

1028+
mod pymethods {
1029+
use crate::impl_::pyclass::PyClassImplCollector;
1030+
1031+
pub trait Sealed {}
1032+
1033+
impl<T> Sealed for &PyClassImplCollector<T> {}
1034+
impl<T> Sealed for PyClassImplCollector<T> {}
1035+
}
1036+
10201037
// Thread checkers
10211038

10221039
#[doc(hidden)]
@@ -1315,7 +1332,7 @@ where
13151332
label = "required by `#[pyo3(get)]` to create a readable property from a field of type `{Self}`",
13161333
note = "implement `IntoPyObject` for `&{Self}` or `IntoPyObject + Clone` for `{Self}` to define the conversion"
13171334
)]
1318-
pub trait PyO3GetField<'py>: IntoPyObject<'py> + Clone {}
1335+
pub trait PyO3GetField<'py>: IntoPyObject<'py> + Clone + pyo3_get_field::Sealed {}
13191336
impl<'py, T> PyO3GetField<'py> for T where T: IntoPyObject<'py> + Clone {}
13201337

13211338
/// Base case attempts to use IntoPyObject + Clone
@@ -1336,6 +1353,14 @@ impl<ClassT: PyClass, FieldT, const OFFSET: usize, const IMPLEMENTS_INTOPYOBJECT
13361353
}
13371354
}
13381355

1356+
mod pyo3_get_field {
1357+
use crate::IntoPyObject;
1358+
1359+
pub trait Sealed {}
1360+
1361+
impl<'py, T: IntoPyObject<'py>> Sealed for T {}
1362+
}
1363+
13391364
/// ensures `obj` is not mutably aliased
13401365
#[inline]
13411366
unsafe fn ensure_no_mutable_alias<'a, ClassT: PyClass>(
@@ -1453,7 +1478,7 @@ impl<const IMPLEMENTS_INTOPYOBJECT: bool> ConvertField<false, IMPLEMENTS_INTOPYO
14531478
}
14541479
}
14551480

1456-
pub trait ExtractPyClassWithClone {}
1481+
pub trait ExtractPyClassWithClone: generic_pyclass::Sealed {}
14571482

14581483
#[cfg(test)]
14591484
#[cfg(feature = "macros")]

0 commit comments

Comments
 (0)