@@ -155,7 +155,7 @@ unsafe impl Sync for PyClassItems {}
155155///
156156/// Users are discouraged from implementing this trait manually; it is a PyO3 implementation detail
157157/// and may be changed at any time.
158- pub trait PyClassImpl : Sized + ' static {
158+ pub trait PyClassImpl : Sized + ' static + generic_pyclass :: Sealed {
159159 /// Module which the class will be associated with.
160160 ///
161161 /// (Currently defaults to `builtins` if unset, this will likely be improved in the future, it
@@ -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) ]
@@ -1109,7 +1126,7 @@ impl<T> PyClassThreadChecker<T> for ThreadCheckerImpl {
11091126 note = "`{Self}` must have `#[pyclass(subclass)]` to be eligible for subclassing" ,
11101127 )
11111128) ]
1112- pub trait PyClassBaseType : Sized {
1129+ pub trait PyClassBaseType : Sized + pyclass_base_type :: Sealed {
11131130 type LayoutAsBase : PyClassObjectBaseLayout < Self > ;
11141131 type BaseNativeType ;
11151132 type Initializer : PyObjectInit < Self > ;
@@ -1118,6 +1135,14 @@ pub trait PyClassBaseType: Sized {
11181135 type Layout < T : PyClassImpl > ;
11191136}
11201137
1138+ mod pyclass_base_type {
1139+ use crate :: impl_:: pyclass:: PyClassBaseType ;
1140+
1141+ pub trait Sealed { }
1142+
1143+ impl < T : PyClassBaseType > Sealed for T { }
1144+ }
1145+
11211146/// Implementation of tp_dealloc for pyclasses without gc
11221147pub ( crate ) unsafe extern "C" fn tp_dealloc < T : PyClass > ( obj : * mut ffi:: PyObject ) {
11231148 unsafe { crate :: impl_:: trampoline:: dealloc ( obj, <T as PyClassImpl >:: Layout :: tp_dealloc) }
@@ -1303,7 +1328,7 @@ where
13031328 label = "required by `#[pyo3(get)]` to create a readable property from a field of type `{Self}`" ,
13041329 note = "implement `IntoPyObject` for `&{Self}` or `IntoPyObject + Clone` for `{Self}` to define the conversion"
13051330) ]
1306- pub trait PyO3GetField < ' py > : IntoPyObject < ' py > + Clone { }
1331+ pub trait PyO3GetField < ' py > : IntoPyObject < ' py > + Clone + pyo3_get_field :: Sealed { }
13071332impl < ' py , T > PyO3GetField < ' py > for T where T : IntoPyObject < ' py > + Clone { }
13081333
13091334/// Base case attempts to use IntoPyObject + Clone
@@ -1324,6 +1349,14 @@ impl<ClassT: PyClass, FieldT, const OFFSET: usize, const IMPLEMENTS_INTOPYOBJECT
13241349 }
13251350}
13261351
1352+ mod pyo3_get_field {
1353+ use crate :: IntoPyObject ;
1354+
1355+ pub trait Sealed { }
1356+
1357+ impl < ' py , T : IntoPyObject < ' py > > Sealed for T { }
1358+ }
1359+
13271360/// ensures `obj` is not mutably aliased
13281361#[ inline]
13291362unsafe fn ensure_no_mutable_alias < ' a , ClassT : PyClass > (
@@ -1441,7 +1474,7 @@ impl<const IMPLEMENTS_INTOPYOBJECT: bool> ConvertField<false, IMPLEMENTS_INTOPYO
14411474 }
14421475}
14431476
1444- pub trait ExtractPyClassWithClone { }
1477+ pub trait ExtractPyClassWithClone : generic_pyclass :: Sealed { }
14451478
14461479#[ cfg( test) ]
14471480#[ cfg( feature = "macros" ) ]
0 commit comments