@@ -49,13 +49,26 @@ 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
+ ///
58
70
/// [rust-lang/rust#53929]: https://github.com/rust-lang/rust/issues/53929
71
+ /// [rust-lang/rust#145496]: https://github.com/rust-lang/rust/issues/145496
59
72
///
60
73
///
61
74
/// # Examples
@@ -177,9 +190,9 @@ macro_rules! __sel_helper {
177
190
// Base-case
178
191
{
179
192
( $( $parsed_sel: tt) * )
180
- } => ( {
193
+ } => {
181
194
$crate:: __sel_data!( $( $parsed_sel) * )
182
- } ) ;
195
+ } ;
183
196
// Single identifier
184
197
{
185
198
( )
@@ -219,7 +232,6 @@ macro_rules! __sel_data {
219
232
$crate:: __macros:: concat!(
220
233
$crate:: __macros:: stringify!( $first) ,
221
234
$( ':' , $( $( $crate:: __macros:: stringify!( $rest) , ) ? ':' , ) * ) ?
222
- '\0' ,
223
235
)
224
236
} ;
225
237
}
@@ -232,7 +244,21 @@ macro_rules! __sel_inner {
232
244
static CACHED_SEL : $crate:: __macros:: CachedSel = $crate:: __macros:: CachedSel :: new( ) ;
233
245
#[ allow( unused_unsafe) ]
234
246
unsafe {
235
- CACHED_SEL . get( $data)
247
+ CACHED_SEL . get( $crate:: __macros:: concat!( $data, '\0' ) )
248
+ }
249
+ } } ;
250
+ }
251
+
252
+ #[ doc( hidden) ]
253
+ #[ macro_export]
254
+ #[ cfg( all( feature = "unstable-static-sel" , feature = "unstable-darwin-objc" ) ) ]
255
+ macro_rules! __sel_inner {
256
+ ( $data: expr, $_hash: expr) => { {
257
+ let ptr = $crate:: __macros:: core_darwin_objc:: selector!( $data) ;
258
+ let ptr = ptr. cast_const( ) . cast:: <$crate:: __macros:: u8 >( ) ;
259
+ #[ allow( unused_unsafe) ]
260
+ unsafe {
261
+ $crate:: runtime:: Sel :: __internal_from_ptr( ptr)
236
262
}
237
263
} } ;
238
264
}
@@ -245,7 +271,7 @@ macro_rules! __statics_sel {
245
271
( $data: expr)
246
272
( $hash: expr)
247
273
} => {
248
- const X : & [ $crate:: __macros:: u8 ] = $data. as_bytes( ) ;
274
+ const X : & [ $crate:: __macros:: u8 ] = $crate :: __macros :: concat! ( $ data, '\0' ) . as_bytes( ) ;
249
275
250
276
/// Clang marks this with LLVM's `unnamed_addr`.
251
277
/// See rust-lang/rust#18297
@@ -321,7 +347,8 @@ macro_rules! __statics_sel {
321
347
#[ macro_export]
322
348
#[ cfg( all(
323
349
feature = "unstable-static-sel" ,
324
- not( feature = "unstable-static-sel-inlined" )
350
+ not( feature = "unstable-darwin-objc" ) ,
351
+ not( feature = "unstable-static-sel-inlined" ) ,
325
352
) ) ]
326
353
macro_rules! __sel_inner {
327
354
( $data: expr, $hash: expr) => { {
@@ -353,7 +380,11 @@ macro_rules! __sel_inner {
353
380
354
381
#[ doc( hidden) ]
355
382
#[ macro_export]
356
- #[ cfg( feature = "unstable-static-sel-inlined" ) ]
383
+ #[ cfg( all(
384
+ feature = "unstable-static-sel" ,
385
+ not( feature = "unstable-darwin-objc" ) ,
386
+ feature = "unstable-static-sel-inlined" ,
387
+ ) ) ]
357
388
macro_rules! __sel_inner {
358
389
( $data: expr, $hash: expr) => { {
359
390
$crate:: __statics_sel! {
@@ -425,30 +456,30 @@ impl CachedSel {
425
456
426
457
#[ inline]
427
458
pub fn alloc_sel ( ) -> Sel {
428
- __sel_inner ! ( "alloc\0 " , "alloc" )
459
+ __sel_inner ! ( "alloc" , "alloc" )
429
460
}
430
461
431
462
#[ inline]
432
463
pub fn init_sel ( ) -> Sel {
433
- __sel_inner ! ( "init\0 " , "init" )
464
+ __sel_inner ! ( "init" , "init" )
434
465
}
435
466
436
467
#[ inline]
437
468
pub fn new_sel ( ) -> Sel {
438
- __sel_inner ! ( "new\0 " , "new" )
469
+ __sel_inner ! ( "new" , "new" )
439
470
}
440
471
441
472
#[ inline]
442
473
pub fn dealloc_sel ( ) -> Sel {
443
- __sel_inner ! ( "dealloc\0 " , "dealloc" )
474
+ __sel_inner ! ( "dealloc" , "dealloc" )
444
475
}
445
476
446
477
/// An undocumented selector called by the Objective-C runtime when
447
478
/// initializing instance variables.
448
479
#[ inline]
449
480
#[ allow( dead_code) ] // May be useful in the future
450
481
fn cxx_construct_sel ( ) -> Sel {
451
- __sel_inner ! ( ".cxx_construct\0 " , ".cxx_construct" )
482
+ __sel_inner ! ( ".cxx_construct" , ".cxx_construct" )
452
483
}
453
484
454
485
/// Objective-C runtimes call `.cxx_destruct` as part of the final `dealloc`
@@ -485,7 +516,7 @@ fn cxx_construct_sel() -> Sel {
485
516
#[ inline]
486
517
#[ allow( dead_code) ] // May be useful in the future
487
518
fn cxx_destruct_sel ( ) -> Sel {
488
- __sel_inner ! ( ".cxx_destruct\0 " , ".cxx_destruct" )
519
+ __sel_inner ! ( ".cxx_destruct" , ".cxx_destruct" )
489
520
}
490
521
491
522
#[ cfg( test) ]
0 commit comments