1
1
use crate :: rc:: { Id , Ownership } ;
2
2
use crate :: runtime:: { Class , Sel } ;
3
- use crate :: { Message , MessageArguments , MessageError , MessageReceiver } ;
3
+ use crate :: { Message , MessageArguments , MessageReceiver } ;
4
4
5
5
pub use crate :: cache:: CachedClass ;
6
6
pub use crate :: cache:: CachedSel ;
7
7
8
8
pub use core:: cell:: UnsafeCell ;
9
9
pub use core:: option:: Option :: { self , None , Some } ;
10
10
pub use core:: primitive:: { bool, str, u8} ;
11
- pub use core:: result:: Result :: { Err , Ok } ;
12
11
pub use core:: { compile_error, concat, panic, stringify} ;
13
12
#[ cfg( feature = "objc2-proc-macros" ) ]
14
13
pub use objc2_proc_macros:: __hash_idents;
@@ -48,24 +47,24 @@ pub struct RetainSemantics<
48
47
> { }
49
48
50
49
pub trait MsgSendId < T , U > {
51
- unsafe fn send_message_id < A : MessageArguments > (
52
- obj : T ,
53
- sel : Sel ,
54
- args : A ,
55
- ) -> Result < Option < U > , MessageError > ;
50
+ unsafe fn send_message_id < A : MessageArguments > ( obj : T , sel : Sel , args : A ) -> Option < U > ;
56
51
}
57
52
58
53
// `new`
59
54
impl < T : ?Sized + Message , O : Ownership > MsgSendId < & ' _ Class , Id < T , O > >
60
55
for RetainSemantics < true , false , false , false >
61
56
{
62
57
#[ inline]
58
+ #[ track_caller]
63
59
unsafe fn send_message_id < A : MessageArguments > (
64
60
obj : & Class ,
65
61
sel : Sel ,
66
62
args : A ,
67
- ) -> Result < Option < Id < T , O > > , MessageError > {
68
- unsafe { MessageReceiver :: send_message ( obj, sel, args) . map ( |r| Id :: new ( r) ) }
63
+ ) -> Option < Id < T , O > > {
64
+ // SAFETY: Checked by caller
65
+ let obj = unsafe { MessageReceiver :: send_message ( obj, sel, args) } ;
66
+ // SAFETY: The selector is `new`, so this has +1 retain count
67
+ unsafe { Id :: new ( obj) }
69
68
}
70
69
}
71
70
@@ -74,12 +73,16 @@ impl<T: ?Sized + Message, O: Ownership> MsgSendId<&'_ Class, Id<T, O>>
74
73
for RetainSemantics < false , true , false , false >
75
74
{
76
75
#[ inline]
76
+ #[ track_caller]
77
77
unsafe fn send_message_id < A : MessageArguments > (
78
78
cls : & Class ,
79
79
sel : Sel ,
80
80
args : A ,
81
- ) -> Result < Option < Id < T , O > > , MessageError > {
82
- unsafe { MessageReceiver :: send_message ( cls, sel, args) . map ( |r| Id :: new ( r) ) }
81
+ ) -> Option < Id < T , O > > {
82
+ // SAFETY: Checked by caller
83
+ let obj = unsafe { MessageReceiver :: send_message ( cls, sel, args) } ;
84
+ // SAFETY: The selector is `alloc`, so this has +1 retain count
85
+ unsafe { Id :: new ( obj) }
83
86
}
84
87
}
85
88
@@ -88,19 +91,22 @@ impl<T: ?Sized + Message, O: Ownership> MsgSendId<Option<Id<T, O>>, Id<T, O>>
88
91
for RetainSemantics < false , false , true , false >
89
92
{
90
93
#[ inline]
94
+ #[ track_caller]
91
95
unsafe fn send_message_id < A : MessageArguments > (
92
96
obj : Option < Id < T , O > > ,
93
97
sel : Sel ,
94
98
args : A ,
95
- ) -> Result < Option < Id < T , O > > , MessageError > {
99
+ ) -> Option < Id < T , O > > {
96
100
let ptr = Id :: option_into_ptr ( obj) ;
97
101
// SAFETY: `ptr` may be null here, but that's fine since the return
98
102
// is `*mut T`, which is one of the few types where messages to nil is
99
103
// allowed.
100
104
//
101
105
// We do this for efficiency, to avoid having a branch after every
102
106
// `alloc`, that the user did not intend.
103
- unsafe { MessageReceiver :: send_message ( ptr, sel, args) . map ( |r| Id :: new ( r) ) }
107
+ let obj = unsafe { MessageReceiver :: send_message ( ptr, sel, args) } ;
108
+ // SAFETY: The selector is `init`, so this has +1 retain count
109
+ unsafe { Id :: new ( obj) }
104
110
}
105
111
}
106
112
@@ -109,12 +115,13 @@ impl<T: MessageReceiver, U: ?Sized + Message, O: Ownership> MsgSendId<T, Id<U, O
109
115
for RetainSemantics < false , false , false , true >
110
116
{
111
117
#[ inline]
112
- unsafe fn send_message_id < A : MessageArguments > (
113
- obj : T ,
114
- sel : Sel ,
115
- args : A ,
116
- ) -> Result < Option < Id < U , O > > , MessageError > {
117
- unsafe { MessageReceiver :: send_message ( obj, sel, args) . map ( |r| Id :: new ( r) ) }
118
+ #[ track_caller]
119
+ unsafe fn send_message_id < A : MessageArguments > ( obj : T , sel : Sel , args : A ) -> Option < Id < U , O > > {
120
+ // SAFETY: Checked by caller
121
+ let obj = unsafe { MessageReceiver :: send_message ( obj, sel, args) } ;
122
+ // SAFETY: The selector is `copy` or `mutableCopy`, so this has +1
123
+ // retain count
124
+ unsafe { Id :: new ( obj) }
118
125
}
119
126
}
120
127
@@ -123,14 +130,16 @@ impl<T: MessageReceiver, U: Message, O: Ownership> MsgSendId<T, Id<U, O>>
123
130
for RetainSemantics < false , false , false , false >
124
131
{
125
132
#[ inline]
126
- unsafe fn send_message_id < A : MessageArguments > (
127
- obj : T ,
128
- sel : Sel ,
129
- args : A ,
130
- ) -> Result < Option < Id < U , O > > , MessageError > {
133
+ #[ track_caller]
134
+ unsafe fn send_message_id < A : MessageArguments > ( obj : T , sel : Sel , args : A ) -> Option < Id < U , O > > {
135
+ // SAFETY: Checked by caller
136
+ let obj = unsafe { MessageReceiver :: send_message ( obj, sel, args) } ;
131
137
// All code between the message send and the `retain_autoreleased`
132
138
// must be able to be optimized away for this to work.
133
- unsafe { MessageReceiver :: send_message ( obj, sel, args) . map ( |r| Id :: retain_autoreleased ( r) ) }
139
+
140
+ // SAFETY: The selector is not `new`, `alloc`, `init`, `copy` nor
141
+ // `mutableCopy`, so the object must be manually retained.
142
+ unsafe { Id :: retain_autoreleased ( obj) }
134
143
}
135
144
}
136
145
0 commit comments