@@ -6,8 +6,8 @@ use core::mem;
6
6
use core:: ops:: Deref ;
7
7
use core:: ptr:: NonNull ;
8
8
9
- use crate :: runtime:: { self , Object } ;
10
9
use super :: Owned ;
10
+ use crate :: runtime:: { self , Object } ;
11
11
12
12
/// A smart pointer that strongly references an object, ensuring it won't be
13
13
/// deallocated.
@@ -64,29 +64,33 @@ unsafe impl<T: Sync + Send> Send for Retained<T> {}
64
64
// SAFETY: TODO
65
65
unsafe impl < T : Sync + Send > Sync for Retained < T > { }
66
66
67
-
68
67
impl < T > Retained < T > {
69
68
/// Constructs a `Retained<T>` to an object that already has a +1 retain
70
69
/// count. This will not retain the object.
71
70
///
72
71
/// When dropped, the object will be released.
73
72
///
73
+ /// See also [`Owned::new`] for the common case of creating objects.
74
+ ///
74
75
/// # Safety
75
76
///
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.
78
82
///
79
83
/// TODO: Something about there not being any mutable references.
80
84
#[ inline]
81
- pub unsafe fn new ( ptr : NonNull < T > ) -> Self {
85
+ pub unsafe fn new ( obj : & T ) -> Self {
82
86
Self {
83
- ptr,
87
+ ptr : obj . into ( ) ,
84
88
phantom : PhantomData ,
85
89
}
86
90
}
87
91
88
92
#[ inline]
89
- pub fn as_ptr ( & self ) -> * mut T {
93
+ pub fn as_ptr ( & self ) -> * const T {
90
94
self . ptr . as_ptr ( )
91
95
}
92
96
@@ -96,16 +100,28 @@ impl<T> Retained<T> {
96
100
///
97
101
/// # Safety
98
102
///
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
+ // ```
100
116
#[ 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 {
104
120
// 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 ) ;
107
123
Self {
108
- ptr,
124
+ ptr : obj . into ( ) ,
109
125
phantom : PhantomData ,
110
126
}
111
127
}
@@ -119,6 +135,8 @@ impl<T> Retained<T> {
119
135
#[ doc( alias = "objc_autorelease" ) ]
120
136
#[ must_use = "If you don't intend to use the object any more, just drop it as usual" ]
121
137
#[ inline]
138
+ // TODO: Get a lifetime relating to the pool, so that we can return a
139
+ // reference instead of a pointer.
122
140
pub fn autorelease ( self ) -> NonNull < T > {
123
141
let ptr = mem:: ManuallyDrop :: new ( self ) . ptr ;
124
142
// SAFETY: The `ptr` is guaranteed to be valid and have at least one
@@ -159,7 +177,7 @@ impl<T> Clone for Retained<T> {
159
177
#[ inline]
160
178
fn clone ( & self ) -> Self {
161
179
// SAFETY: The `ptr` is guaranteed to be valid
162
- unsafe { Self :: retain ( self . ptr ) }
180
+ unsafe { Self :: retain ( & * self ) }
163
181
}
164
182
}
165
183
@@ -230,7 +248,7 @@ impl<T> Unpin for Retained<T> {}
230
248
impl < T > From < Owned < T > > for Retained < T > {
231
249
fn from ( obj : Owned < T > ) -> Self {
232
250
// SAFETY: TODO
233
- unsafe { Self :: new ( obj. ptr ) }
251
+ unsafe { Self :: new ( & * obj) }
234
252
}
235
253
}
236
254
@@ -259,8 +277,8 @@ mod tests {
259
277
#[ test]
260
278
fn test_clone ( ) {
261
279
// 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) } ;
264
282
assert ! ( obj. retain_count( ) == 1 ) ;
265
283
266
284
let cloned = obj. clone ( ) ;
0 commit comments