@@ -121,6 +121,10 @@ use crate::{ffi, ClassType, DowncastTarget, Message};
121121#[ doc( alias = "id" ) ]
122122#[ doc( alias = "Id" ) ]
123123#[ doc( alias = "StrongPtr" ) ]
124+ #[ cfg_attr(
125+ feature = "unstable-coerce-pointee" ,
126+ derive( std:: marker:: CoercePointee )
127+ ) ]
124128// TODO: Add `ptr::Thin` bound on `T` to allow for only extern types
125129pub struct Retained < T : ?Sized > {
126130 /// A pointer to the contained object. The pointer is always retained.
@@ -1014,4 +1018,35 @@ mod tests {
10141018 let _: Retained < NSObject > = Into :: into ( obj_retained_ref) ;
10151019 let _: Retained < AnyObject > = Into :: into ( obj_retained_ref) ;
10161020 }
1021+
1022+ #[ test]
1023+ #[ cfg( feature = "unstable-coerce-pointee" ) ]
1024+ fn test_coercion ( ) {
1025+ use crate :: { extern_protocol, ProtocolType } ;
1026+
1027+ extern_protocol ! (
1028+ unsafe trait ExampleProtocol : NSObjectProtocol { }
1029+
1030+ unsafe impl ProtocolType for dyn ExampleProtocol { }
1031+ ) ;
1032+
1033+ unsafe impl ExampleProtocol for RcTestObject { }
1034+
1035+ let obj = RcTestObject :: new ( ) ;
1036+ let mut expected = ThreadTestData :: current ( ) ;
1037+
1038+ let obj: Retained < dyn ExampleProtocol > = obj;
1039+ expected. assert_current ( ) ;
1040+
1041+ let obj: Retained < dyn NSObjectProtocol > = obj;
1042+ expected. assert_current ( ) ;
1043+
1044+ // TODO: Allow calling methods on trait objects like this.
1045+ // let _ = obj.hash();
1046+
1047+ drop ( obj) ;
1048+ expected. release += 1 ;
1049+ expected. drop += 1 ;
1050+ expected. assert_current ( ) ;
1051+ }
10171052}
0 commit comments