@@ -6,8 +6,8 @@ use core::mem;
66use core:: ops:: Deref ;
77use core:: ptr:: NonNull ;
88
9- use crate :: runtime:: { self , Object } ;
109use super :: Owned ;
10+ use crate :: runtime:: { self , Object } ;
1111
1212/// A smart pointer that strongly references an object, ensuring it won't be
1313/// deallocated.
@@ -64,29 +64,33 @@ unsafe impl<T: Sync + Send> Send for Retained<T> {}
6464// SAFETY: TODO
6565unsafe impl < T : Sync + Send > Sync for Retained < T > { }
6666
67-
6867impl < T > Retained < T > {
6968 /// Constructs a `Retained<T>` to an object that already has a +1 retain
7069 /// count. This will not retain the object.
7170 ///
7271 /// When dropped, the object will be released.
7372 ///
73+ /// See also [`Owned::new`] for the common case of creating objects.
74+ ///
7475 /// # Safety
7576 ///
76- /// The caller must ensure the given object pointer is valid, and has +1
77- /// retain count.
77+ /// The caller must ensure the given object reference has +1 retain count
78+ /// (that is, a retain count that has been handed off from somewhere else,
79+ /// usually Objective-C methods with the `ns_returns_retained` attribute).
80+ ///
81+ /// Additionally, there must be no [`Owned`] pointers to the same object.
7882 ///
7983 /// TODO: Something about there not being any mutable references.
8084 #[ inline]
81- pub unsafe fn new ( ptr : NonNull < T > ) -> Self {
85+ pub unsafe fn new ( obj : & T ) -> Self {
8286 Self {
83- ptr,
87+ ptr : obj . into ( ) ,
8488 phantom : PhantomData ,
8589 }
8690 }
8791
8892 #[ inline]
89- pub fn as_ptr ( & self ) -> * mut T {
93+ pub fn as_ptr ( & self ) -> * const T {
9094 self . ptr . as_ptr ( )
9195 }
9296
@@ -96,16 +100,28 @@ impl<T> Retained<T> {
96100 ///
97101 /// # Safety
98102 ///
99- /// The caller must ensure the given object pointer is valid.
103+ /// The caller must ensure that there are no [`Owned`] pointers to the
104+ /// same object.
105+ //
106+ // So this would be illegal:
107+ // ```rust
108+ // let owned: Owned<T> = ...;
109+ // // Lifetime information is discarded
110+ // let retained = Retained::retain(&*owned);
111+ // // Which means we can still mutate `Owned`:
112+ // let x: &mut T = &mut *owned;
113+ // // While we have an immutable reference
114+ // let y: &T = &*retained;
115+ // ```
100116 #[ doc( alias = "objc_retain" ) ]
101- # [ inline ]
102- // TODO: Maybe just take a normal reference, and then this can be safe?
103- pub unsafe fn retain ( ptr : NonNull < T > ) -> Self {
117+ // Inlined since it's `objc_retain` that does the work.
118+ # [ cfg_attr ( debug_assertions , inline ) ]
119+ pub unsafe fn retain ( obj : & T ) -> Self {
104120 // SAFETY: The caller upholds that the pointer is valid
105- let rtn = runtime:: objc_retain ( ptr . as_ptr ( ) as * mut Object ) ;
106- debug_assert_eq ! ( rtn, ptr . as_ptr ( ) as * mut Object ) ;
121+ let rtn = runtime:: objc_retain ( obj as * const T as * mut Object ) ;
122+ debug_assert_eq ! ( rtn, obj as * const T as * mut Object ) ;
107123 Self {
108- ptr,
124+ ptr : obj . into ( ) ,
109125 phantom : PhantomData ,
110126 }
111127 }
@@ -119,6 +135,8 @@ impl<T> Retained<T> {
119135 #[ doc( alias = "objc_autorelease" ) ]
120136 #[ must_use = "If you don't intend to use the object any more, just drop it as usual" ]
121137 #[ inline]
138+ // TODO: Get a lifetime relating to the pool, so that we can return a
139+ // reference instead of a pointer.
122140 pub fn autorelease ( self ) -> NonNull < T > {
123141 let ptr = mem:: ManuallyDrop :: new ( self ) . ptr ;
124142 // SAFETY: The `ptr` is guaranteed to be valid and have at least one
@@ -159,7 +177,7 @@ impl<T> Clone for Retained<T> {
159177 #[ inline]
160178 fn clone ( & self ) -> Self {
161179 // SAFETY: The `ptr` is guaranteed to be valid
162- unsafe { Self :: retain ( self . ptr ) }
180+ unsafe { Self :: retain ( & * self ) }
163181 }
164182}
165183
@@ -230,7 +248,7 @@ impl<T> Unpin for Retained<T> {}
230248impl < T > From < Owned < T > > for Retained < T > {
231249 fn from ( obj : Owned < T > ) -> Self {
232250 // SAFETY: TODO
233- unsafe { Self :: new ( obj. ptr ) }
251+ unsafe { Self :: new ( & * obj) }
234252 }
235253}
236254
@@ -259,8 +277,8 @@ mod tests {
259277 #[ test]
260278 fn test_clone ( ) {
261279 // TODO: Maybe make a way to return `Retained` directly?
262- let obj: * mut Object = unsafe { msg_send ! [ class!( NSObject ) , new] } ;
263- let obj: Retained < Object > = unsafe { Retained :: new ( NonNull :: new ( obj) . unwrap ( ) ) } ;
280+ let obj: & Object = unsafe { msg_send ! [ class!( NSObject ) , new] } ;
281+ let obj: Retained < Object > = unsafe { Retained :: new ( obj) } ;
264282 assert ! ( obj. retain_count( ) == 1 ) ;
265283
266284 let cloned = obj. clone ( ) ;
0 commit comments