@@ -471,7 +471,6 @@ cfg_if::cfg_if! {
471471 }
472472}
473473
474- #[ derive( Debug ) ]
475474#[ repr( transparent) ]
476475pub struct PyObject ( PyInner < Erased > ) ;
477476
@@ -522,7 +521,7 @@ impl PyObjectRef {
522521 #[ inline( always) ]
523522 pub fn downcast < T : PyObjectPayload > ( self ) -> Result < PyRef < T > , Self > {
524523 if self . payload_is :: < T > ( ) {
525- Ok ( unsafe { PyRef :: from_obj_unchecked ( self ) } )
524+ Ok ( unsafe { self . downcast_unchecked ( ) } )
526525 } else {
527526 Err ( self )
528527 }
@@ -539,6 +538,8 @@ impl PyObjectRef {
539538 }
540539 }
541540
541+ /// Force to downcast this reference to a subclass.
542+ ///
542543 /// # Safety
543544 /// T must be the exact payload type
544545 #[ inline( always) ]
@@ -637,13 +638,22 @@ impl PyObject {
637638 self . 0 . typeid == TypeId :: of :: < T > ( )
638639 }
639640
641+ /// Force to return payload as T.
642+ ///
643+ /// # Safety
644+ /// The actual payload type must be T.
645+ #[ inline( always) ]
646+ pub unsafe fn payload_unchecked < T : PyObjectPayload > ( & self ) -> & T {
647+ // we cast to a PyInner<T> first because we don't know T's exact offset because of
648+ // varying alignment, but once we get a PyInner<T> the compiler can get it for us
649+ let inner = unsafe { & * ( & self . 0 as * const PyInner < Erased > as * const PyInner < T > ) } ;
650+ & inner. payload
651+ }
652+
640653 #[ inline( always) ]
641654 pub fn payload < T : PyObjectPayload > ( & self ) -> Option < & T > {
642655 if self . payload_is :: < T > ( ) {
643- // we cast to a PyInner<T> first because we don't know T's exact offset because of
644- // varying alignment, but once we get a PyInner<T> the compiler can get it for us
645- let inner = unsafe { & * ( & self . 0 as * const PyInner < Erased > as * const PyInner < T > ) } ;
646- Some ( & inner. payload )
656+ Some ( unsafe { self . payload_unchecked ( ) } )
647657 } else {
648658 None
649659 }
@@ -854,14 +864,20 @@ impl Drop for PyObjectRef {
854864 }
855865}
856866
857- impl fmt:: Debug for PyObjectRef {
867+ impl fmt:: Debug for PyObject {
858868 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
859869 // SAFETY: the vtable contains functions that accept payload types that always match up
860870 // with the payload of the object
861871 unsafe { ( self . 0 . vtable . debug ) ( self , f) }
862872 }
863873}
864874
875+ impl fmt:: Debug for PyObjectRef {
876+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
877+ self . as_object ( ) . fmt ( f)
878+ }
879+ }
880+
865881#[ repr( transparent) ]
866882pub struct Py < T : PyObjectPayload > ( PyInner < T > ) ;
867883
0 commit comments