@@ -11,9 +11,9 @@ use crate::impl_::pyclass::{
1111 PyClassBaseType , PyClassDict , PyClassImpl , PyClassThreadChecker , PyClassWeakRef , PyObjectOffset ,
1212} ;
1313use crate :: internal:: get_slot:: { TP_DEALLOC , TP_FREE } ;
14- use crate :: type_object:: { PyLayout , PySizedLayout } ;
14+ use crate :: type_object:: { PyLayout , PySizedLayout , PyTypeInfo } ;
1515use crate :: types:: PyType ;
16- use crate :: { ffi, PyClass , PyTypeInfo , Python } ;
16+ use crate :: { ffi, PyClass , Python } ;
1717
1818use crate :: types:: PyTypeMethods ;
1919
@@ -477,21 +477,31 @@ pub struct PyVariableClassObject<T: PyClassImpl> {
477477}
478478
479479#[ cfg( Py_3_12 ) ]
480- impl < T : PyClassImpl < Layout = Self > > PyVariableClassObject < T > {
481- fn get_contents_of_obj ( obj : * mut ffi:: PyObject ) -> * mut PyClassObjectContents < T > {
482- // https://peps.python.org/pep-0697/
483- let type_obj = unsafe { ffi:: Py_TYPE ( obj) } ;
480+ impl < T : PyClass < Layout = Self > > PyVariableClassObject < T > {
481+ /// # Safety
482+ /// - `obj` must have the layout that the implementation is expecting
483+ /// - thread must be attached to the interpreter
484+ unsafe fn get_contents_of_obj (
485+ obj : * mut ffi:: PyObject ,
486+ ) -> * mut MaybeUninit < PyClassObjectContents < T > > {
487+ // TODO: it would be nice to eventually avoid coupling to the PyO3 statics here, maybe using
488+ // 3.14's PyType_GetBaseByToken, to support PEP 587 / multiple interpreters better
489+ // SAFETY: caller guarantees attached to the interpreter
490+ let type_obj = T :: type_object_raw ( unsafe { Python :: assume_attached ( ) } ) ;
484491 let pointer = unsafe { ffi:: PyObject_GetTypeData ( obj, type_obj) } ;
485492 pointer. cast ( )
486493 }
487494
488495 fn get_contents_ptr ( & self ) -> * mut PyClassObjectContents < T > {
489- Self :: get_contents_of_obj ( self as * const PyVariableClassObject < T > as * mut ffi:: PyObject )
496+ unsafe {
497+ Self :: get_contents_of_obj ( self as * const PyVariableClassObject < T > as * mut ffi:: PyObject )
498+ }
499+ . cast ( )
490500 }
491501}
492502
493503#[ cfg( Py_3_12 ) ]
494- impl < T : PyClassImpl < Layout = Self > > PyClassObjectLayout < T > for PyVariableClassObject < T > {
504+ impl < T : PyClass < Layout = Self > > PyClassObjectLayout < T > for PyVariableClassObject < T > {
495505 /// Gets the offset of the contents from the start of the struct in bytes.
496506 const CONTENTS_OFFSET : PyObjectOffset = PyObjectOffset :: Relative ( 0 ) ;
497507 const BASIC_SIZE : ffi:: Py_ssize_t = {
@@ -514,7 +524,7 @@ impl<T: PyClassImpl<Layout = Self>> PyClassObjectLayout<T> for PyVariableClassOb
514524 unsafe fn contents_uninit (
515525 obj : * mut ffi:: PyObject ,
516526 ) -> * mut MaybeUninit < PyClassObjectContents < T > > {
517- Self :: get_contents_of_obj ( obj) . cast ( )
527+ unsafe { Self :: get_contents_of_obj ( obj) }
518528 }
519529
520530 fn get_ptr ( & self ) -> * mut T {
@@ -543,7 +553,7 @@ impl<T: PyClassImpl<Layout = Self>> PyClassObjectLayout<T> for PyVariableClassOb
543553unsafe impl < T : PyClassImpl > PyLayout < T > for PyVariableClassObject < T > { }
544554
545555#[ cfg( Py_3_12 ) ]
546- impl < T : PyClassImpl < Layout = Self > > PyClassObjectBaseLayout < T > for PyVariableClassObject < T >
556+ impl < T : PyClass < Layout = Self > > PyClassObjectBaseLayout < T > for PyVariableClassObject < T >
547557where
548558 <T :: BaseType as PyClassBaseType >:: LayoutAsBase : PyClassObjectBaseLayout < T :: BaseType > ,
549559{
0 commit comments