@@ -49,13 +49,29 @@ use crate::runtime::Sel;
49
49
/// - runtime, causing UB (unlikely)
50
50
///
51
51
/// The `"unstable-static-sel-inlined"` feature is the even more extreme
52
- /// version - it yields the best performance and is closest to real
52
+ /// version - it yield better performance and is closer to real
53
53
/// Objective-C code, but probably won't work unless your code and its
54
54
/// inlining is written in a very certain way.
55
55
///
56
56
/// Enabling LTO greatly increases the chance that these features work.
57
57
///
58
+ /// On Apple/Darwin targets, these limitations can be overcome with the
59
+ /// `"unstable-darwin-objc"` feature which uses the nightly-only `darwin_objc`
60
+ /// language feature. This experimental language feature implements the
61
+ /// Objective-C static selector ABI directly in the Rust compiler and should
62
+ /// work in more if not all cases. Using `"unstable-darwin-objc"` requires
63
+ /// `darwin_objc` to be enabled in every crate that uses this macro, which can
64
+ /// be achieved in `objc2` crates by enabling their own
65
+ /// `"unstable-darwin-objc"` features and in your own crates by adding
66
+ /// `#![feature(darwin_objc)]`.
67
+ ///
68
+ /// See [rust-lang/rust#145496] for the tracking issue for the feature.
69
+ ///
70
+ /// `"unstable-static-sel"` and `"unstable-static-sel-inlined"` take
71
+ /// precedence over `"unstable-darwin-objc"`.
72
+ ///
58
73
/// [rust-lang/rust#53929]: https://github.com/rust-lang/rust/issues/53929
74
+ /// [rust-lang/rust#145496]: https://github.com/rust-lang/rust/issues/145496
59
75
///
60
76
///
61
77
/// # Examples
@@ -177,9 +193,9 @@ macro_rules! __sel_helper {
177
193
// Base-case
178
194
{
179
195
( $( $parsed_sel: tt) * )
180
- } => ( {
196
+ } => {
181
197
$crate:: __sel_data!( $( $parsed_sel) * )
182
- } ) ;
198
+ } ;
183
199
// Single identifier
184
200
{
185
201
( )
@@ -219,20 +235,36 @@ macro_rules! __sel_data {
219
235
$crate:: __macros:: concat!(
220
236
$crate:: __macros:: stringify!( $first) ,
221
237
$( ':' , $( $( $crate:: __macros:: stringify!( $rest) , ) ? ':' , ) * ) ?
222
- '\0' ,
223
238
)
224
239
} ;
225
240
}
226
241
227
242
#[ doc( hidden) ]
228
243
#[ macro_export]
229
- #[ cfg( not( feature = "unstable-static-sel" ) ) ]
244
+ #[ cfg( not( any ( feature = "unstable-darwin-objc" , feature = "unstable- static-sel") ) ) ]
230
245
macro_rules! __sel_inner {
231
246
( $data: expr, $_hash: expr) => { {
232
247
static CACHED_SEL : $crate:: __macros:: CachedSel = $crate:: __macros:: CachedSel :: new( ) ;
233
248
#[ allow( unused_unsafe) ]
234
249
unsafe {
235
- CACHED_SEL . get( $data)
250
+ CACHED_SEL . get( $crate:: __macros:: concat!( $data, '\0' ) )
251
+ }
252
+ } } ;
253
+ }
254
+
255
+ #[ doc( hidden) ]
256
+ #[ macro_export]
257
+ #[ cfg( all(
258
+ feature = "unstable-darwin-objc" ,
259
+ not( feature = "unstable-static-sel" )
260
+ ) ) ]
261
+ macro_rules! __sel_inner {
262
+ ( $data: expr, $_hash: expr) => { {
263
+ let ptr = $crate:: __macros:: core_darwin_objc:: selector!( $data) ;
264
+ let ptr = ptr. cast_const( ) . cast:: <$crate:: __macros:: u8 >( ) ;
265
+ #[ allow( unused_unsafe) ]
266
+ unsafe {
267
+ $crate:: runtime:: Sel :: __internal_from_ptr( ptr)
236
268
}
237
269
} } ;
238
270
}
@@ -245,7 +277,7 @@ macro_rules! __statics_sel {
245
277
( $data: expr)
246
278
( $hash: expr)
247
279
} => {
248
- const X : & [ $crate:: __macros:: u8 ] = $data. as_bytes( ) ;
280
+ const X : & [ $crate:: __macros:: u8 ] = $crate :: __macros :: concat! ( $ data, '\0' ) . as_bytes( ) ;
249
281
250
282
/// Clang marks this with LLVM's `unnamed_addr`.
251
283
/// See rust-lang/rust#18297
@@ -425,30 +457,30 @@ impl CachedSel {
425
457
426
458
#[ inline]
427
459
pub fn alloc_sel ( ) -> Sel {
428
- __sel_inner ! ( "alloc\0 " , "alloc" )
460
+ __sel_inner ! ( "alloc" , "alloc" )
429
461
}
430
462
431
463
#[ inline]
432
464
pub fn init_sel ( ) -> Sel {
433
- __sel_inner ! ( "init\0 " , "init" )
465
+ __sel_inner ! ( "init" , "init" )
434
466
}
435
467
436
468
#[ inline]
437
469
pub fn new_sel ( ) -> Sel {
438
- __sel_inner ! ( "new\0 " , "new" )
470
+ __sel_inner ! ( "new" , "new" )
439
471
}
440
472
441
473
#[ inline]
442
474
pub fn dealloc_sel ( ) -> Sel {
443
- __sel_inner ! ( "dealloc\0 " , "dealloc" )
475
+ __sel_inner ! ( "dealloc" , "dealloc" )
444
476
}
445
477
446
478
/// An undocumented selector called by the Objective-C runtime when
447
479
/// initializing instance variables.
448
480
#[ inline]
449
481
#[ allow( dead_code) ] // May be useful in the future
450
482
fn cxx_construct_sel ( ) -> Sel {
451
- __sel_inner ! ( ".cxx_construct\0 " , ".cxx_construct" )
483
+ __sel_inner ! ( ".cxx_construct" , ".cxx_construct" )
452
484
}
453
485
454
486
/// Objective-C runtimes call `.cxx_destruct` as part of the final `dealloc`
@@ -485,7 +517,7 @@ fn cxx_construct_sel() -> Sel {
485
517
#[ inline]
486
518
#[ allow( dead_code) ] // May be useful in the future
487
519
fn cxx_destruct_sel ( ) -> Sel {
488
- __sel_inner ! ( ".cxx_destruct\0 " , ".cxx_destruct" )
520
+ __sel_inner ! ( ".cxx_destruct" , ".cxx_destruct" )
489
521
}
490
522
491
523
#[ cfg( test) ]
0 commit comments