@@ -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.
242250pub struct PyClassItemsIter {
243251 /// Iteration state
@@ -305,7 +313,7 @@ impl Iterator for PyClassItemsIter {
305313macro_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 { }
13191336impl < ' 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]
13411366unsafe 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