@@ -478,7 +478,6 @@ cfg_if::cfg_if! {
478478 }
479479}
480480
481- #[ derive( Debug ) ]
482481#[ repr( transparent) ]
483482pub struct PyObject ( PyInner < Erased > ) ;
484483
@@ -529,7 +528,7 @@ impl PyObjectRef {
529528 #[ inline( always) ]
530529 pub fn downcast < T : PyObjectPayload > ( self ) -> Result < PyRef < T > , Self > {
531530 if self . payload_is :: < T > ( ) {
532- Ok ( unsafe { PyRef :: from_obj_unchecked ( self ) } )
531+ Ok ( unsafe { self . downcast_unchecked ( ) } )
533532 } else {
534533 Err ( self )
535534 }
@@ -546,6 +545,8 @@ impl PyObjectRef {
546545 }
547546 }
548547
548+ /// Force to downcast this reference to a subclass.
549+ ///
549550 /// # Safety
550551 /// T must be the exact payload type
551552 #[ inline( always) ]
@@ -644,13 +645,22 @@ impl PyObject {
644645 self . 0 . typeid == TypeId :: of :: < T > ( )
645646 }
646647
648+ /// Force to return payload as T.
649+ ///
650+ /// # Safety
651+ /// The actual payload type must be T.
652+ #[ inline( always) ]
653+ pub unsafe fn payload_unchecked < T : PyObjectPayload > ( & self ) -> & T {
654+ // we cast to a PyInner<T> first because we don't know T's exact offset because of
655+ // varying alignment, but once we get a PyInner<T> the compiler can get it for us
656+ let inner = unsafe { & * ( & self . 0 as * const PyInner < Erased > as * const PyInner < T > ) } ;
657+ & inner. payload
658+ }
659+
647660 #[ inline( always) ]
648661 pub fn payload < T : PyObjectPayload > ( & self ) -> Option < & T > {
649662 if self . payload_is :: < T > ( ) {
650- // we cast to a PyInner<T> first because we don't know T's exact offset because of
651- // varying alignment, but once we get a PyInner<T> the compiler can get it for us
652- let inner = unsafe { & * ( & self . 0 as * const PyInner < Erased > as * const PyInner < T > ) } ;
653- Some ( & inner. payload )
663+ Some ( unsafe { self . payload_unchecked ( ) } )
654664 } else {
655665 None
656666 }
@@ -861,14 +871,20 @@ impl Drop for PyObjectRef {
861871 }
862872}
863873
864- impl fmt:: Debug for PyObjectRef {
874+ impl fmt:: Debug for PyObject {
865875 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
866876 // SAFETY: the vtable contains functions that accept payload types that always match up
867877 // with the payload of the object
868878 unsafe { ( self . 0 . vtable . debug ) ( self , f) }
869879 }
870880}
871881
882+ impl fmt:: Debug for PyObjectRef {
883+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
884+ self . as_object ( ) . fmt ( f)
885+ }
886+ }
887+
872888#[ repr( transparent) ]
873889pub struct Py < T : PyObjectPayload > ( PyInner < T > ) ;
874890
0 commit comments