objc2/macros/
define_class.rs

1/// Create a new Objective-C class.
2///
3/// This is useful in many cases since Objective-C frameworks tend to favour a
4/// design pattern using "delegates", where to hook into a piece of
5/// functionality in a class, you implement that class' delegate protocol in
6/// a custom class.
7///
8/// This macro is the declarative way of creating classes, in contrast with
9/// [`ClassBuilder`], which allows creating classes in an imperative fashion.
10/// It is highly recommended that you use this macro though, since it contains
11/// a lot of extra debug assertions and niceties that help ensure the
12/// soundness of your code.
13///
14/// The class is guaranteed to have been created and registered with the
15/// Objective-C runtime after the [`ClassType::class`] function has been
16/// called.
17///
18/// See [Apple's documentation] on defining classes for a more in-depth
19/// introduction.
20///
21/// [Apple's documentation]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/DefiningClasses/DefiningClasses.html
22/// [`ClassBuilder`]: crate::runtime::ClassBuilder
23/// [`ClassType::class`]: crate::ClassType::class
24///
25///
26/// # Specification
27///
28/// This macro consists of the following parts:
29/// - The type definition, along with special attributes.
30/// - Any number of inherent implementations.
31/// - Any number of protocol implementations.
32///
33/// With the syntax generally resembling a combination of that in
34/// [`extern_class!`] and [`extern_methods!`].
35///
36/// This macro creates an opaque struct with implementations in [a similar
37/// manner as the `extern_class!` macro][ec_spec]. Additionally, it implements
38/// the [`DefinedClass`] trait, as well as any protocols specified in the
39/// protocol implementations.
40///
41/// If the type implements [`Drop`], the macro will generate a `dealloc`
42/// method for you, which will call `drop` automatically.
43///
44/// The macro does not support generic types.
45///
46/// [`extern_class!`]: crate::extern_class
47/// [`extern_methods!`]: crate::extern_methods
48/// [ec_spec]: crate::extern_class#specification
49/// [`DefinedClass`]: crate::DefinedClass
50///
51///
52/// ## Attributes
53///
54/// You can add most normal attributes to the class, including `#[cfg(...)]`,
55/// `#[allow(...)]` and doc comments.
56///
57/// Exceptions and special attributes are noted below.
58///
59///
60/// ### `#[unsafe(super(...))]` (required)
61///
62/// Same [as in `extern_class!`](crate::extern_class#unsafesuper-required).
63///
64///
65/// ### `#[thread_kind = ...]` (optional)
66///
67/// Same [as in `extern_class!`](crate::extern_class#thread_kind---optional).
68///
69///
70/// ### `#[name = "..."]` (optional)
71///
72/// Specify the runtime-name for the class. Must be unique across the entire
73/// application. This is useful if the name of a class is used elsewhere, such
74/// as when defining a delegate that needs to be named in e.g. `Info.plist`.
75///
76/// If not set, this will default to:
77/// ```ignore
78/// concat!(module_path!(), "::", $class, env!("CARGO_PKG_VERSION"));
79/// ```
80///
81/// E.g. for example `"my_crate::my_module::MyClass0.1.0"`.
82///
83/// If you're developing a library, it is recommended that you do not set
84/// this, and instead rely on the default naming, since that usually works
85/// better with users having multiple SemVer-incompatible versions of your
86/// library in the same binary.
87///
88///
89/// ### `#[ivars = ...]` (optional)
90///
91/// Controls [the instance variables] of the class; this is the intended way
92/// to specify the data your class stores. If you don't set this attribute,
93/// the macro will default to [`()`][unit].
94///
95/// It is recommended that you wrap your instance variables in [`Cell`],
96/// [`RefCell`], atomics or other similar interior mutability abstractions to
97/// allow mutating your instance variables. See [the docs on interior
98/// mutability][interior_mutability] for further details.
99///
100/// Beware that if you want to use the class' inherited initializers (such as
101/// `init`), you must override the subclass' designated initializers, and
102/// initialize your ivars properly in there.
103///
104/// [the instance variables]: crate::DefinedClass::Ivars
105/// [`Cell`]: core::cell::Cell
106/// [`RefCell`]: core::cell::RefCell
107/// [interior_mutability]: crate::topics::interior_mutability
108///
109///
110/// ### `#[derive(...)]`
111///
112/// This is overridden, and only works with [`PartialEq`], [`Eq`], [`Hash`]
113/// and [`Debug`].
114///
115/// The implementations delegate to the superclass' implementation, so if you
116/// want to change how they work, you should override the [`isEqual:`] and
117/// [`hash`] methods instead.
118///
119/// The `Debug` implementation currently also debug print your ivars, but that
120/// may change in the future. Prefer to override [`description`] (and
121/// potentially [`debugDescription`]) instead.
122///
123/// [`Hash`]: std::hash::Hash
124/// [`Debug`]: std::fmt::Debug
125/// [`isEqual:`]: crate::runtime::NSObjectProtocol::isEqual
126/// [`hash`]: crate::runtime::NSObjectProtocol::hash
127/// [`description`]: crate::runtime::NSObjectProtocol::description
128/// [`debugDescription`]: crate::runtime::NSObjectProtocol::debugDescription
129///
130///
131/// ### `#[cfg_attr(..., ...)]`
132///
133/// Same [as in `extern_class!`](crate::extern_class#cfg_attr-).
134///
135///
136/// ### `#[repr(...)]`
137///
138/// Same [as in `extern_class!`](crate::extern_class#repr).
139///
140///
141/// ## Inherent method definitions
142///
143/// Within the `impl` block you can define two types of functions;
144/// ["associated functions"] and ["methods"]. These are then mapped to the
145/// Objective-C equivalents "class methods" and "instance methods". In
146/// particular, if you use `self` or the special name `this` (or `_this`),
147/// your method will be registered as an instance method, and if you don't it
148/// will be registered as a class method.
149///
150/// On instance methods, you can freely choose between different types of
151/// receivers, e.g. `&self`, `self: *const Self`, `this: *const Self`, and so
152/// on. Note that using `&mut self` is not possible, if you need mutation of
153/// your class' instance variables, consider using [`Cell`] or similar
154/// instead.
155///
156/// The desired selector can be specified using the
157/// `#[unsafe(method(my:selector:))]` or `#[unsafe(method_id(my:selector:))]`
158/// attributes, similar to the [`extern_methods!`] macro.
159///
160/// If the `#[unsafe(method_id(...))]` attribute is used, the return type must
161/// be `Option<Retained<T>>` or `Retained<T>`. Additionally, if the selector
162/// is in the "init"-family, the `self`/`this` parameter must be
163/// `Allocated<Self>`.
164///
165/// Putting other attributes on the method such as `cfg`, `allow`, `doc`,
166/// `deprecated` and so on is supported. However, note that `cfg_attr` may not
167/// work correctly, due to implementation difficulty - if you have a concrete
168/// use-case, please [open an issue], then we can discuss it.
169///
170/// A transformation step is performed on the functions (to make them have the
171/// correct ABI) and hence they shouldn't really be called manually. (You
172/// can't mark them as `pub` for the same reason). Instead, use the
173/// [`extern_methods!`] macro to create a Rust interface to the methods.
174///
175/// If the parameter or return type is [`bool`], a conversion is performed to
176/// make it behave similarly to the Objective-C `BOOL`. Use [`runtime::Bool`]
177/// if you want to control this manually.
178///
179/// Note that `&mut Retained<_>` and other such out parameters are not yet
180/// supported, and may generate a panic at runtime.
181///
182/// ["associated functions"]: https://doc.rust-lang.org/reference/items/associated-items.html#methods
183/// ["methods"]: https://doc.rust-lang.org/reference/items/associated-items.html#methods
184/// [`Cell`]: core::cell::Cell
185/// [open an issue]: https://github.com/madsmtm/objc2/issues/new
186/// [`msg_send!`]: crate::msg_send
187/// [`runtime::Bool`]: crate::runtime::Bool
188///
189///
190/// ## Protocol implementations
191///
192/// You can specify protocols that the class should implement, along with any
193/// required/optional methods for said protocols.
194///
195/// The protocol must have been previously defined with [`extern_protocol!`].
196///
197/// The methods work exactly as normal, they're only put "under" the protocol
198/// definition to make things easier to read.
199///
200/// Putting attributes on the `impl` item such as `cfg`, `allow`, `doc`,
201/// `deprecated` and so on is supported.
202///
203/// [`extern_protocol!`]: crate::extern_protocol
204///
205///
206/// # Panics
207///
208/// The implemented `ClassType::class` method may panic in a few cases, such
209/// as if:
210/// - A class with the specified name already exists.
211/// - Debug assertions are enabled, and an overridden method's signature is not
212///   equal to the one on the superclass.
213/// - Debug assertions are enabled, and the protocol's required methods are not
214///   implemented.
215///
216/// And possibly more similar cases in the future.
217///
218///
219/// # Safety
220///
221/// Using this macro requires writing a lot of `unsafe` markers:
222///
223/// When writing `#[unsafe(super(...))]`, you must ensure that:
224/// - Any invariants that the superclass [`ClassType::Super`] may have must be
225///   upheld.
226/// - If your type implements `Drop`, the implementation must abide by the
227///   following rules:
228///   - It must not call any overridden methods.
229///   - It must not `retain` the object past the lifetime of the drop.
230///   - It must not `retain` in the same scope that `&mut self` is active.
231///   - TODO: And probably a few more. [Open an issue] if you would like
232///     guidance on whether your implementation is correct.
233///
234/// `#[unsafe(method(...))]` asserts that the types match those that are
235/// expected when the method is invoked from Objective-C. Note that unlike
236/// with [`extern_methods!`], there are no safe-guards here; you can write
237/// `i8`, but if Objective-C thinks it's an `u32`, it will cause UB when
238/// called!
239///
240/// `unsafe impl P for T { ... }` requires that all required methods of the
241/// specified protocol is implemented, and that any extra requirements
242/// (implicit or explicit) that the protocol has are upheld.
243///
244/// [`ClassType::Super`]: crate::ClassType::Super
245/// [Open an issue]: https://github.com/madsmtm/objc2/issues/new
246///
247///
248/// # Thread safety
249///
250/// The Objective-C runtime is thread-safe, so any classes you create yourself
251/// will automatically be [`Send`] and [`Sync`] (via auto traits) provided
252/// that:
253/// 1. The superclass is thread-safe, or is [`NSObject`].
254/// 2. The ivars are thread-safe.
255/// 3. The thread kind is not [`MainThreadOnly`].
256///
257/// Note though that in many cases, [the frameworks] you will be interacting
258/// with will not be thread-safe, and so in many cases it will make sense to
259/// [use interior mutability] in your custom classes.
260///
261/// [`NSObject`]: crate::runtime::NSObject
262/// [`MainThreadOnly`]: crate::MainThreadOnly
263/// [the frameworks]: crate::topics::about_generated
264/// [use interior mutability]: crate::topics::interior_mutability
265///
266///
267/// # Examples
268///
269/// Define a class `MyCustomObject` that inherits `NSObject`, has a few
270/// instance variables and methods, and implements the `NSCopying` protocol.
271///
272/// ```
273/// use std::ffi::c_int;
274///
275/// use objc2_foundation::{CopyingHelper, NSCopying, NSObject, NSObjectProtocol, NSZone};
276/// use objc2::rc::{Allocated, Retained};
277/// use objc2::{
278///     define_class, extern_methods, extern_protocol, msg_send, AnyThread,
279///     ClassType, DefinedClass, ProtocolType,
280/// };
281///
282/// #[derive(Clone)]
283/// struct Ivars {
284///     foo: u8,
285///     bar: c_int,
286///     object: Retained<NSObject>,
287/// }
288///
289/// define_class!(
290///     // SAFETY:
291///     // - The superclass NSObject does not have any subclassing requirements.
292///     // - `MyCustomObject` does not implement `Drop`.
293///     #[unsafe(super(NSObject))]
294///
295///     // If we were implementing delegate methods like `NSApplicationDelegate`,
296///     // we would specify the object to only be usable on the main thread:
297///     // #[thread_kind = MainThreadOnly]
298///
299///     // If we needed to refer to the class from elsewhere, we'd give it a
300///     // name here explicitly.
301///     // #[name = "MyCustomObject"]
302///
303///     // Specify the instance variables this class has.
304///     #[ivars = Ivars]
305///     struct MyCustomObject;
306///
307///     impl MyCustomObject {
308///         #[unsafe(method(foo))]
309///         fn __get_foo(&self) -> u8 {
310///             self.ivars().foo
311///         }
312///
313///         #[unsafe(method_id(object))]
314///         fn __get_object(&self) -> Retained<NSObject> {
315///             self.ivars().object.clone()
316///         }
317///
318///         #[unsafe(method(myClassMethod))]
319///         fn __my_class_method() -> bool {
320///             true
321///         }
322///     }
323///
324///     unsafe impl NSObjectProtocol for MyCustomObject {}
325///
326///     unsafe impl NSCopying for MyCustomObject {
327///         #[unsafe(method_id(copyWithZone:))]
328///         fn copyWithZone(&self, _zone: *const NSZone) -> Retained<Self> {
329///             let new = Self::alloc().set_ivars(self.ivars().clone());
330///             unsafe { msg_send![super(new), init] }
331///         }
332///
333///         // If we have tried to add other methods here, or had forgotten
334///         // to implement the method, we would have gotten an error.
335///     }
336/// );
337///
338/// // Specially required for `NSCopying`, but otherwise not needed.
339/// unsafe impl CopyingHelper for MyCustomObject {
340///     type Result = Self;
341/// }
342///
343/// // Add creation method.
344/// impl MyCustomObject {
345///     fn new(foo: u8) -> Retained<Self> {
346///         // Initialize instance variables.
347///         let this = Self::alloc().set_ivars(Ivars {
348///             foo,
349///             bar: 42,
350///             object: NSObject::new(),
351///         });
352///         // Call `NSObject`'s `init` method.
353///         unsafe { msg_send![super(this), init] }
354///     }
355/// }
356///
357/// // Make an interface to the methods we defined.
358/// impl MyCustomObject {
359///     extern_methods!(
360///         #[unsafe(method(foo))]
361///         pub fn get_foo(&self) -> u8;
362///
363///         #[unsafe(method(object))]
364///         pub fn get_object(&self) -> Retained<NSObject>;
365///
366///         #[unsafe(method(myClassMethod))]
367///         pub fn my_class_method() -> bool;
368///     );
369/// }
370///
371/// # // Intentionally use `fn main` for clarity
372/// fn main() {
373///     let obj = MyCustomObject::new(3);
374///     assert_eq!(obj.ivars().foo, 3);
375///     assert_eq!(obj.ivars().bar, 42);
376///     assert!(obj.ivars().object.isKindOfClass(NSObject::class()));
377///
378///     let obj = obj.copy();
379///
380///     assert_eq!(obj.get_foo(), 3);
381///     assert!(obj.get_object().isKindOfClass(NSObject::class()));
382///
383///     assert!(MyCustomObject::my_class_method());
384/// }
385/// ```
386///
387/// Approximately equivalent to the following ARC-enabled Objective-C code.
388///
389/// ```text
390/// #import <Foundation/Foundation.h>
391///
392/// @interface MyCustomObject: NSObject <NSCopying>
393/// - (instancetype)initWithFoo:(uint8_t)foo;
394/// - (uint8_t)foo;
395/// - (NSObject*)object;
396/// + (BOOL)myClassMethod;
397/// @end
398///
399///
400/// @implementation MyCustomObject {
401///     // Instance variables
402///     uint8_t foo;
403///     int bar;
404///     NSObject* _Nonnull object;
405/// }
406///
407/// - (instancetype)initWithFoo:(uint8_t)foo_arg {
408///     self = [super init];
409///     if (self) {
410///         self->foo = foo_arg;
411///         self->bar = 42;
412///         self->object = [NSObject new];
413///     }
414///     return self;
415/// }
416///
417/// - (uint8_t)foo {
418///     return self->foo;
419/// }
420///
421/// - (NSObject*)object {
422///     return self->object;
423/// }
424///
425/// + (BOOL)myClassMethod {
426///     return YES;
427/// }
428///
429/// // NSCopying
430///
431/// - (id)copyWithZone:(NSZone *)_zone {
432///     MyCustomObject* new = [[MyCustomObject alloc] initWithFoo: self->foo];
433///     new->bar = self->bar;
434///     new->obj = self->obj;
435///     return new;
436/// }
437///
438/// @end
439/// ```
440#[doc(alias = "@interface")]
441#[doc(alias = "@implementation")]
442#[macro_export]
443macro_rules! define_class {
444    {
445        // The following special attributes are supported:
446        // - #[unsafe(super($($superclasses:path),*))]
447        // - #[unsafe(super = $superclass:path)]
448        // - #[thread_kind = $thread_kind:path]
449        // - #[name = $name:literal]
450        // - #[ivars = $ivars:path]
451        $(#[$($attrs:tt)*])*
452        $v:vis struct $class:ident;
453
454        // unsafe impl Protocol for $class { ... }
455        // impl $class { ... }
456        $($impls:tt)*
457    } => {
458        // Struct and various impls.
459        $crate::__extract_struct_attributes! {
460            ($(#[$($attrs)*])*)
461
462            ($crate::__define_class_inner)
463            ($v)
464            ($class)
465            ($($impls)*)
466        }
467
468        // Methods.
469        $crate::__define_class_output_impls! {
470            $($impls)*
471        }
472    };
473}
474
475#[doc(hidden)]
476#[macro_export]
477macro_rules! declare_class {
478    {
479        $(#[$m:meta])*
480        $v:vis struct $name:ident;
481
482        unsafe impl ClassType for $for_class:ty {
483            $(#[inherits($($inheritance_rest:ty),+)])?
484            type Super = $superclass:ty;
485
486            type Mutability = $mutability:ty;
487
488            const NAME: &'static str = $name_const:expr;
489        }
490
491        impl DefinedClass for $for_defined:ty {
492            $(type Ivars = $ivars:ty;)?
493        }
494
495        $($impls:tt)*
496    } => {
497        // For slightly better diagnostics
498        $(#[$m])*
499        $v struct $name;
500
501        $crate::__macro_helpers::compile_error!("declare_class! has been renamed to define_class!, and the syntax has changed")
502    }
503}
504
505#[doc(hidden)]
506#[macro_export]
507macro_rules! __define_class_inner {
508    (
509        ($v:vis)
510        ($class:ident)
511        ($($impls:tt)*)
512
513        ($($safety:tt $superclass:path $(, $superclasses:path)* $(,)?)?)
514        ($($($thread_kind:tt)+)?)
515        ($($name:tt)*)
516        ($($ivars:tt)*)
517        ($($derives:tt)*)
518        ($($attr_struct:tt)*)
519        ($($attr_impl:tt)*)
520    ) => {
521        // Ensure that the type has the same layout as the superclass.
522        // #[repr(transparent)] doesn't work because the superclass is a ZST.
523        #[repr(C)]
524        $($attr_struct)*
525        $v struct $class {
526            // Superclasses are deallocated by calling `[super dealloc]`.
527            //
528            // Auto traits are taken from `__SubclassingType` (which is
529            // usually the super class).
530            __superclass: $crate::__macro_helpers::ManuallyDrop<$crate::__fallback_if_not_set! {
531                ($(<$superclass as $crate::ClassType>::__SubclassingType)?)
532                // For better diagnostics, see also __extern_class_inner!
533                ($crate::runtime::NSObject)
534            }>,
535            __phantom: $crate::__macro_helpers::PhantomData<(
536                // Include ivars for auto traits.
537                <Self as $crate::DefinedClass>::Ivars,
538                // Translate thread kind to appropriate auto traits.
539                $crate::__macro_helpers::ThreadKindAutoTraits<<Self as $crate::ClassType>::ThreadKind>,
540            )>,
541        }
542
543        $crate::__extern_class_impl_traits! {
544            ($($attr_impl)*)
545            (unsafe impl)
546            ($class)
547            ($($superclass, $($superclasses,)*)? $crate::runtime::AnyObject)
548        }
549
550        $crate::__define_class_derives! {
551            ($($attr_impl)*)
552            ($class)
553            ($($derives)*)
554        }
555
556        // Anonymous block to hide the shared statics
557        $($attr_impl)*
558        const _: () = {
559            static __OBJC2_CLASS: $crate::__macro_helpers::SyncUnsafeCell<
560                $crate::__macro_helpers::MaybeUninit<&'static $crate::runtime::AnyClass>
561            > = $crate::__macro_helpers::SyncUnsafeCell::new($crate::__macro_helpers::MaybeUninit::uninit());
562            static __OBJC2_IVAR_OFFSET: $crate::__macro_helpers::SyncUnsafeCell<
563                $crate::__macro_helpers::MaybeUninit<$crate::__macro_helpers::isize>
564            > = $crate::__macro_helpers::SyncUnsafeCell::new($crate::__macro_helpers::MaybeUninit::uninit());
565            static __OBJC2_DROP_FLAG_OFFSET: $crate::__macro_helpers::SyncUnsafeCell<
566                $crate::__macro_helpers::MaybeUninit<$crate::__macro_helpers::isize>
567            > = $crate::__macro_helpers::SyncUnsafeCell::new($crate::__macro_helpers::MaybeUninit::uninit());
568
569            // Creation
570            unsafe impl $crate::ClassType for $class {
571                type Super = $crate::__fallback_if_not_set! {
572                    ($($superclass)?)
573                    // For better diagnostics, see also __extern_class_inner!
574                    ($crate::runtime::NSObject)
575                };
576
577                type ThreadKind = $crate::__fallback_if_not_set! {
578                    ($(dyn ($($thread_kind)+))?)
579                    // Default to the super class' thread kind
580                    (<<Self as $crate::ClassType>::Super as $crate::ClassType>::ThreadKind)
581                };
582
583                const NAME: &'static $crate::__macro_helpers::str = $crate::__fallback_if_not_set! {
584                    ($($name)*)
585                    (
586                        $crate::__macro_helpers::concat!(
587                            // Module path includes crate name when in library.
588                            $crate::__macro_helpers::module_path!(),
589                            "::",
590                            $crate::__macro_helpers::stringify!($class),
591                            $crate::__macro_helpers::env!("CARGO_PKG_VERSION"),
592                        )
593                    )
594                };
595
596                fn class() -> &'static $crate::runtime::AnyClass {
597                    let _ = <Self as $crate::__macro_helpers::ValidThreadKind<Self::ThreadKind>>::check;
598                    let _ = <Self as $crate::__macro_helpers::MainThreadOnlyDoesNotImplSendSync<_>>::check;
599
600                    // TODO: Use `std::sync::OnceLock`
601                    static REGISTER_CLASS: $crate::__macro_helpers::Once = $crate::__macro_helpers::Once::new();
602
603                    REGISTER_CLASS.call_once(|| {
604                        let mut __objc2_builder = $crate::__macro_helpers::ClassBuilderHelper::<Self>::new();
605
606                        // Implement protocols and methods
607                        $crate::__define_class_register_impls! {
608                            (__objc2_builder)
609                            $($impls)*
610                        }
611
612                        let (__objc2_cls, __objc2_ivar_offset, __objc2_drop_flag_offset) = __objc2_builder.register();
613
614                        // SAFETY: Modification is ensured by `Once` to happen
615                        // before any access to the variables.
616                        unsafe {
617                            __OBJC2_CLASS.get().write($crate::__macro_helpers::MaybeUninit::new(__objc2_cls));
618                            if <Self as $crate::__macro_helpers::DefinedIvarsHelper>::HAS_IVARS {
619                                __OBJC2_IVAR_OFFSET.get().write($crate::__macro_helpers::MaybeUninit::new(__objc2_ivar_offset));
620                            }
621                            if <Self as $crate::__macro_helpers::DefinedIvarsHelper>::HAS_DROP_FLAG {
622                                __OBJC2_DROP_FLAG_OFFSET.get().write($crate::__macro_helpers::MaybeUninit::new(__objc2_drop_flag_offset));
623                            }
624                        }
625                    });
626
627                    // SAFETY: We just registered the class, so is now available
628                    unsafe { __OBJC2_CLASS.get().read().assume_init() }
629                }
630
631                #[inline]
632                fn as_super(&self) -> &Self::Super {
633                    &*self.__superclass
634                }
635
636                const __INNER: () = ();
637
638                type __SubclassingType = Self;
639            }
640
641            impl $crate::DefinedClass for $class {
642                type Ivars = $crate::__select_ivars!($($ivars)?);
643
644                #[inline]
645                fn __ivars_offset() -> $crate::__macro_helpers::isize {
646                    // Only access ivar offset if we have an ivar.
647                    //
648                    // This makes the offset not be included in the final
649                    // executable if it's not needed.
650                    if <Self as $crate::__macro_helpers::DefinedIvarsHelper>::HAS_IVARS {
651                        // SAFETY: Accessing the offset is guaranteed to only be
652                        // done after the class has been initialized.
653                        unsafe { __OBJC2_IVAR_OFFSET.get().read().assume_init() }
654                    } else {
655                        // Fall back to an offset of zero.
656                        //
657                        // This is fine, since any reads here will only be via zero-sized
658                        // ivars, where the actual pointer doesn't matter.
659                        0
660                    }
661                }
662
663                #[inline]
664                fn __drop_flag_offset() -> $crate::__macro_helpers::isize {
665                    if <Self as $crate::__macro_helpers::DefinedIvarsHelper>::HAS_DROP_FLAG {
666                        // SAFETY: Same as above.
667                        unsafe { __OBJC2_DROP_FLAG_OFFSET.get().read().assume_init() }
668                    } else {
669                        // Fall back to an offset of zero.
670                        //
671                        // This is fine, since the drop flag is never actually used in the
672                        // cases where it was not added.
673                        0
674                    }
675                }
676
677                // SAFETY: The offsets are implemented correctly
678                const __UNSAFE_OFFSETS_CORRECT: () = ();
679            }
680        };
681
682        // SAFETY: This macro only allows non-generic classes and non-generic
683        // classes are always valid downcast targets.
684        $($attr_impl)*
685        unsafe impl $crate::DowncastTarget for $class {}
686
687        $($attr_impl)*
688        $crate::__extern_class_check_super_unsafe!($($safety $superclass)?);
689    };
690}
691
692/// Mirror of [`crate::__extern_class_derives`].
693#[doc(hidden)]
694#[macro_export]
695macro_rules! __define_class_derives {
696    // Base case
697    (
698        ($($attr_impl:tt)*)
699        ($for:path)
700        ($(,)*)
701    ) => {};
702
703    // Debug
704    (
705        ($($attr_impl:tt)*)
706        ($for:path)
707        (
708            $(,)*
709            Debug
710            $($rest:tt)*
711        )
712    ) => {
713        $($attr_impl)*
714        #[automatically_derived]
715        impl $crate::__macro_helpers::fmt::Debug for $for {
716            fn fmt(&self, f: &mut $crate::__macro_helpers::fmt::Formatter<'_>) -> $crate::__macro_helpers::fmt::Result {
717                f.debug_struct($crate::__macro_helpers::stringify!($for))
718                    .field("super", &**self.__superclass)
719                    .field("ivars", <Self as $crate::DefinedClass>::ivars(self))
720                    .finish()
721            }
722        }
723
724        $crate::__define_class_derives! {
725            ($($attr_impl)*)
726            ($for)
727            ($($rest)*)
728        }
729    };
730
731    // PartialEq
732    (
733        ($($attr_impl:tt)*)
734        ($for:path)
735        (
736            $(,)*
737            PartialEq
738            $($rest:tt)*
739        )
740    ) => {
741        $($attr_impl)*
742        #[automatically_derived]
743        impl $crate::__macro_helpers::PartialEq for $for {
744            #[inline]
745            fn eq(&self, other: &Self) -> $crate::__macro_helpers::bool {
746                // Delegate to the superclass (referential equality)
747                $crate::__macro_helpers::PartialEq::eq(&self.__superclass, &other.__superclass)
748            }
749        }
750
751        $crate::__define_class_derives! {
752            ($($attr_impl)*)
753            ($for)
754            ($($rest)*)
755        }
756    };
757
758    // Eq
759    (
760        ($($attr_impl:tt)*)
761        ($for:path)
762        (
763            $(,)*
764            Eq
765            $($rest:tt)*
766        )
767    ) => {
768        $($attr_impl)*
769        #[automatically_derived]
770        impl $crate::__macro_helpers::Eq for $for {}
771
772        $crate::__define_class_derives! {
773            ($($attr_impl)*)
774            ($for)
775            ($($rest)*)
776        }
777    };
778
779    // Hash
780    (
781        ($($attr_impl:tt)*)
782        ($for:path)
783        (
784            $(,)*
785            Hash
786            $($rest:tt)*
787        )
788    ) => {
789        $($attr_impl)*
790        #[automatically_derived]
791        impl $crate::__macro_helpers::Hash for $for {
792            #[inline]
793            fn hash<H: $crate::__macro_helpers::Hasher>(&self, state: &mut H) {
794                // Delegate to the superclass (which hashes the reference)
795                $crate::__macro_helpers::Hash::hash(&self.__superclass, state)
796            }
797        }
798
799        $crate::__define_class_derives! {
800            ($($attr_impl)*)
801            ($for)
802            ($($rest)*)
803        }
804    };
805
806    // Unhandled derive
807    (
808        ($($attr_impl:tt)*)
809        ($for:path)
810        (
811            $(,)*
812            $derive:path
813            $(, $($rest:tt)*)?
814        )
815    ) => {
816        const _: () = {
817            // For better diagnostics.
818            #[derive($derive)]
819            struct Derive;
820        };
821        $crate::__macro_helpers::compile_error!($crate::__macro_helpers::stringify!(
822            #[derive($derive)] is not supported in define_class!
823        ));
824
825        $crate::__define_class_derives! {
826            ($($attr_impl)*)
827            ($for)
828            ($($($rest)*)?)
829        }
830    };
831}
832
833#[doc(hidden)]
834#[macro_export]
835macro_rules! __select_ivars {
836    ($ivars:ty) => {
837        $ivars
838    };
839    () => {
840        // Default ivars to unit
841        ()
842    };
843}
844
845#[doc(hidden)]
846#[macro_export]
847macro_rules! __define_class_output_impls {
848    // Base-case
849    () => {};
850
851    // With protocol
852    (
853        $(#[$m:meta])*
854        unsafe impl $protocol:ident for $for:ty {
855            $($methods:tt)*
856        }
857
858        $($rest:tt)*
859    ) => {
860        // SAFETY: Upheld by caller
861        $(#[$m])*
862        unsafe impl $protocol for $for {}
863
864        $(#[$m])*
865        impl $for {
866            $crate::__define_class_output_methods! {
867                $($methods)*
868            }
869        }
870
871        $crate::__define_class_output_impls!{
872            $($rest)*
873        }
874    };
875
876    // Without protocol
877    (
878        $(#[$m:meta])*
879        impl $for:ty {
880            $($methods:tt)*
881        }
882
883        $($rest:tt)*
884    ) => {
885        $(#[$m])*
886        impl $for {
887            $crate::__define_class_output_methods! {
888                $($methods)*
889            }
890        }
891
892        $crate::__define_class_output_impls! {
893            $($rest)*
894        }
895    };
896}
897
898#[doc(hidden)]
899#[macro_export]
900macro_rules! __define_class_output_methods {
901    // Base case
902    {} => {};
903
904    // Unsafe variant
905    {
906        $(#[$($m:tt)*])*
907        unsafe fn $name:ident($($params:tt)*) $(-> $ret:ty)? $body:block
908
909        $($rest:tt)*
910    } => {
911        $crate::__rewrite_self_param! {
912            ($($params)*)
913
914            ($crate::__extract_method_attributes)
915            ($(#[$($m)*])*)
916
917            ($crate::__define_class_method_out)
918            (unsafe)
919            ($name)
920            ($($ret)?)
921            ($body)
922        }
923
924        $crate::__define_class_output_methods! {
925            $($rest)*
926        }
927    };
928
929    // Safe variant
930    {
931        $(#[$($m:tt)*])*
932        fn $name:ident($($params:tt)*) $(-> $ret:ty)? $body:block
933
934        $($rest:tt)*
935    } => {
936        $crate::__rewrite_self_param! {
937            ($($params)*)
938
939            ($crate::__extract_method_attributes)
940            ($(#[$($m)*])*)
941
942            ($crate::__define_class_method_out)
943            ()
944            ($name)
945            ($($ret)?)
946            ($body)
947        }
948
949        $crate::__define_class_output_methods! {
950            $($rest)*
951        }
952    };
953}
954
955#[doc(hidden)]
956#[macro_export]
957macro_rules! __define_class_register_impls {
958    // Base-case
959    (
960        ($builder:ident)
961    ) => {};
962
963    // With protocol
964    (
965        ($builder:ident)
966
967        $(#[$($m:tt)*])*
968        unsafe impl $protocol:ident for $for:ty {
969            $($methods:tt)*
970        }
971
972        $($rest:tt)*
973    ) => {
974        $crate::__extract_and_apply_cfg_attributes! {
975            ($(#[$($m)*])*)
976
977            // Implement protocol
978            #[allow(unused_mut)]
979            let mut __objc2_protocol_builder = $builder.add_protocol_methods::<dyn $protocol>();
980
981            // In case the user's function is marked `deprecated`
982            #[allow(deprecated)]
983            // In case the user did not specify any methods
984            #[allow(unused_unsafe)]
985            // SAFETY: Upheld by caller
986            unsafe {
987                $crate::__define_class_register_methods! {
988                    (__objc2_protocol_builder)
989
990                    $($methods)*
991                }
992            }
993
994            // Finished creating protocol; get error message if any
995            __objc2_protocol_builder.finish();
996        }
997
998        $crate::__define_class_register_impls! {
999            ($builder)
1000            $($rest)*
1001        }
1002    };
1003
1004    // Without protocol
1005    (
1006        ($builder:ident)
1007
1008        $(#[$($m:tt)*])*
1009        impl $for:ty {
1010            $($methods:tt)*
1011        }
1012
1013        $($rest:tt)*
1014    ) => {
1015        $crate::__extract_and_apply_cfg_attributes! {
1016            ($(#[$($m)*])*)
1017
1018            // In case the user's function is marked `deprecated`
1019            #[allow(deprecated)]
1020            // In case the user did not specify any methods
1021            #[allow(unused_unsafe)]
1022            // SAFETY: Upheld by caller
1023            unsafe {
1024                $crate::__define_class_register_methods! {
1025                    ($builder)
1026
1027                    $($methods)*
1028                }
1029            }
1030        }
1031
1032        $crate::__define_class_register_impls! {
1033            ($builder)
1034            $($rest)*
1035        }
1036    };
1037}
1038
1039#[doc(hidden)]
1040#[macro_export]
1041macro_rules! __define_class_register_methods {
1042    // Base case
1043    {
1044        ($builder:ident)
1045    } => {};
1046
1047    // Unsafe variant
1048    {
1049        ($builder:ident)
1050
1051        $(#[$($m:tt)*])*
1052        unsafe fn $name:ident($($params:tt)*) $(-> $ret:ty)? $body:block
1053
1054        $($rest:tt)*
1055    } => {
1056        $crate::__rewrite_self_param! {
1057            ($($params)*)
1058
1059            ($crate::__extract_method_attributes)
1060            ($(#[$($m)*])*)
1061
1062            ($crate::__define_class_register_out)
1063            ($builder)
1064            (unsafe)
1065            ($name)
1066            ($($ret)?)
1067            ($body)
1068        }
1069
1070        $crate::__define_class_register_methods! {
1071            ($builder)
1072
1073            $($rest)*
1074        }
1075    };
1076
1077    // Safe variant
1078    {
1079        ($builder:ident)
1080
1081        $(#[$($m:tt)*])*
1082        fn $name:ident($($params:tt)*) $(-> $ret:ty)? $body:block
1083
1084        $($rest:tt)*
1085    } => {
1086        $crate::__rewrite_self_param! {
1087            ($($params)*)
1088
1089            ($crate::__extract_method_attributes)
1090            ($(#[$($m)*])*)
1091
1092            ($crate::__define_class_register_out)
1093            ($builder)
1094            ()
1095            ($name)
1096            ($($ret)?)
1097            ($body)
1098        }
1099
1100        $crate::__define_class_register_methods! {
1101            ($builder)
1102
1103            $($rest)*
1104        }
1105    };
1106
1107    // Consume associated items for better UI.
1108    //
1109    // This will still fail inside __define_class_output_methods!
1110    {
1111        ($builder:ident)
1112
1113        $_associated_item:item
1114
1115        $($rest:tt)*
1116    } => {
1117        $crate::__define_class_output_methods! {
1118            ($builder)
1119
1120            $($rest)*
1121        }
1122    }
1123}
1124
1125#[doc(hidden)]
1126#[macro_export]
1127macro_rules! __define_class_method_out {
1128    {
1129        ($($qualifiers:tt)*)
1130        ($name:ident)
1131        ($($ret:ty)?)
1132        ($body:block)
1133
1134        ($builder_method:ident)
1135        ($receiver:expr)
1136        ($receiver_ty:ty)
1137        ($($params_prefix:tt)*)
1138        ($($params_rest:tt)*)
1139
1140        ($($m_method:tt)*)
1141        ($($method_family:tt)*)
1142        ($($optional:tt)*)
1143        ($($attr_method:tt)*)
1144        ($($attr_use:tt)*)
1145    } => {
1146        $crate::__define_class_rewrite_params! {
1147            ($($params_rest)*)
1148            ()
1149            ()
1150
1151            ($crate::__define_class_method_out_inner)
1152
1153            ($($qualifiers)*)
1154            ($name)
1155            ($($ret)?)
1156            ($body)
1157
1158            ($builder_method)
1159            ($receiver)
1160            ($receiver_ty)
1161            ($($params_prefix)*)
1162
1163            ($($m_method)*)
1164            ($($method_family)*)
1165            ($($optional)*)
1166            ($($attr_method)*)
1167            ($($attr_use)*)
1168        }
1169    };
1170}
1171
1172#[doc(hidden)]
1173#[macro_export]
1174macro_rules! __define_class_rewrite_params {
1175    // Convert _
1176    {
1177        (_ : $param_ty:ty $(, $($params_rest:tt)*)?)
1178        ($($params_converted:tt)*)
1179        ($($body_prefix:tt)*)
1180
1181        ($out_macro:path)
1182        $($macro_args:tt)*
1183    } => {
1184        $crate::__define_class_rewrite_params! {
1185            ($($($params_rest)*)?)
1186            ($($params_converted)* _ : <$param_ty as $crate::__macro_helpers::ConvertArgument>::__Inner,)
1187            ($($body_prefix)*)
1188
1189            ($out_macro)
1190            $($macro_args)*
1191        }
1192    };
1193    // Convert mut
1194    {
1195        (mut $param:ident : $param_ty:ty $(, $($params_rest:tt)*)?)
1196        ($($params_converted:tt)*)
1197        ($($body_prefix:tt)*)
1198
1199        ($out_macro:path)
1200        $($macro_args:tt)*
1201    } => {
1202        $crate::__define_class_rewrite_params! {
1203            ($($($params_rest)*)?)
1204            ($($params_converted)* $param : <$param_ty as $crate::__macro_helpers::ConvertArgument>::__Inner,)
1205            (
1206                $($body_prefix)*
1207                let mut $param = <$param_ty as $crate::__macro_helpers::ConvertArgument>::__from_defined_param($param);
1208            )
1209
1210            ($out_macro)
1211            $($macro_args)*
1212        }
1213    };
1214    // Convert
1215    {
1216        ($param:ident : $param_ty:ty $(, $($params_rest:tt)*)?)
1217        ($($params_converted:tt)*)
1218        ($($body_prefix:tt)*)
1219
1220        ($out_macro:path)
1221        $($macro_args:tt)*
1222    } => {
1223        $crate::__define_class_rewrite_params! {
1224            ($($($params_rest)*)?)
1225            ($($params_converted)* $param : <$param_ty as $crate::__macro_helpers::ConvertArgument>::__Inner,)
1226            (
1227                $($body_prefix)*
1228                let $param = <$param_ty as $crate::__macro_helpers::ConvertArgument>::__from_defined_param($param);
1229            )
1230
1231            ($out_macro)
1232            $($macro_args)*
1233        }
1234    };
1235    // Output result
1236    {
1237        ()
1238        ($($params_converted:tt)*)
1239        ($($body_prefix:tt)*)
1240
1241        ($out_macro:path)
1242        $($macro_args:tt)*
1243    } => {
1244        $out_macro! {
1245            $($macro_args)*
1246
1247            ($($params_converted)*)
1248            ($($body_prefix)*)
1249        }
1250    };
1251}
1252
1253#[doc(hidden)]
1254#[macro_export]
1255macro_rules! __define_class_method_out_inner {
1256    // #[unsafe(method(...))]
1257    {
1258        ($($qualifiers:tt)*)
1259        ($name:ident)
1260        ($($ret:ty)?)
1261        ($body:block)
1262
1263        ($__builder_method:ident)
1264        ($__receiver:expr)
1265        ($__receiver_ty:ty)
1266        ($($params_prefix:tt)*)
1267
1268        (method($($__sel:tt)*))
1269        ($($method_family:tt)*)
1270        ($($optional:tt)*)
1271        ($($attr_method:tt)*)
1272        ($($attr_use:tt)*)
1273
1274        ($($params_converted:tt)*)
1275        ($($body_prefix:tt)*)
1276    } => {
1277        $($attr_method)*
1278        #[allow(clippy::diverging_sub_expression)]
1279        $($qualifiers)* extern "C-unwind" fn $name(
1280            $($params_prefix)*
1281            $($params_converted)*
1282        ) $(-> <$ret as $crate::__macro_helpers::ConvertReturn<()>>::Inner)? {
1283            $crate::__define_class_no_method_family!($($method_family)*);
1284            $($body_prefix)*
1285            $crate::__convert_result! {
1286                $body $(; $ret)?
1287            }
1288        }
1289    };
1290
1291    // #[unsafe(method_id(...))]
1292    {
1293        ($($qualifiers:tt)*)
1294        ($name:ident)
1295        ($ret:ty)
1296        ($body:block)
1297
1298        ($__builder_method:ident)
1299        ($__receiver:expr)
1300        ($receiver_ty:ty)
1301        ($($params_prefix:tt)*)
1302
1303        (method_id($($sel:tt)*))
1304        ($($method_family:tt)*)
1305        ($($optional:tt)*)
1306        ($($attr_method:tt)*)
1307        ($($attr_use:tt)*)
1308
1309        ($($params_converted:tt)*)
1310        ($($body_prefix:tt)*)
1311    } => {
1312        $($attr_method)*
1313        #[allow(clippy::diverging_sub_expression)]
1314        $($qualifiers)* extern "C-unwind" fn $name(
1315            $($params_prefix)*
1316            $($params_converted)*
1317        ) -> $crate::__macro_helpers::RetainedReturnValue {
1318            // TODO: Somehow tell the compiler that `this: Allocated<Self>` is non-null.
1319
1320            $($body_prefix)*
1321
1322            let __objc2_result = $body;
1323
1324            #[allow(unreachable_code)]
1325            <$crate::__method_family!(($($method_family)*) ($($sel)*)) as $crate::__macro_helpers::MessageReceiveRetained<
1326                $receiver_ty,
1327                $ret,
1328            >>::into_return(__objc2_result)
1329        }
1330    };
1331
1332    {
1333        ($($qualifiers:tt)*)
1334        ($name:ident)
1335        ()
1336        ($body:block)
1337
1338        ($__builder_method:ident)
1339        ($__receiver:expr)
1340        ($__receiver_ty:ty)
1341        ($($params_prefix:tt)*)
1342
1343        (method_id($($sel:tt)*))
1344        ($($method_family:tt)*)
1345        ($($optional:tt)*)
1346        ($($attr_method:tt)*)
1347        ($($attr_use:tt)*)
1348
1349        ($($params_converted:tt)*)
1350        ($($body_prefix:tt)*)
1351    } => {
1352        $($attr_method)*
1353        $($qualifiers)* extern "C-unwind" fn $name() {
1354            $crate::__macro_helpers::compile_error!("`#[unsafe(method_id(...))]` must have a return type")
1355        }
1356    };
1357}
1358
1359#[doc(hidden)]
1360#[macro_export]
1361macro_rules! __convert_result {
1362    ($body:block) => {
1363        $body
1364    };
1365    ($body:block; $ret:ty) => {
1366        let __objc2_result = $body;
1367        #[allow(unreachable_code)]
1368        <$ret as $crate::__macro_helpers::ConvertReturn<()>>::convert_defined_return(__objc2_result)
1369    };
1370}
1371
1372#[doc(hidden)]
1373#[macro_export]
1374macro_rules! __define_class_register_out {
1375    {
1376        ($builder:ident)
1377        ($($qualifiers:tt)*)
1378        ($name:ident)
1379        ($($__ret:ty)?)
1380        ($__body:block)
1381
1382        ($builder_method:ident)
1383        ($__receiver:expr)
1384        ($__receiver_ty:ty)
1385        ($($__params_prefix:tt)*)
1386        ($($params_rest:tt)*)
1387
1388        ($method_or_method_id:ident($($sel:tt)*))
1389        ($($method_family:tt)*)
1390        ($($optional:tt)*)
1391        ($($attr_method:tt)*)
1392        ($($attr_use:tt)*)
1393    } => {
1394        $($attr_use)*
1395        {
1396            $crate::__define_class_invalid_selectors!($method_or_method_id($($sel)*));
1397            $crate::__define_class_no_optional!($($optional)*);
1398
1399            $builder.$builder_method(
1400                $crate::sel!($($sel)*),
1401                Self::$name as $crate::__fn_ptr! {
1402                    ($($qualifiers)*)
1403                    (_, _,)
1404                    $($params_rest)*
1405                },
1406            );
1407        }
1408    };
1409}
1410
1411#[doc(hidden)]
1412#[macro_export]
1413macro_rules! __define_class_invalid_selectors {
1414    (method(dealloc)) => {
1415        $crate::__macro_helpers::compile_error!(
1416            "`#[unsafe(method(dealloc))]` is not supported. Implement `Drop` for the type instead"
1417        )
1418    };
1419    (method_id(dealloc)) => {
1420        $crate::__macro_helpers::compile_error!(
1421            "`#[unsafe(method_id(dealloc))]` is not supported. Implement `Drop` for the type instead"
1422        )
1423    };
1424    (method_id(alloc)) => {
1425        $crate::__macro_helpers::compile_error!($crate::__macro_helpers::concat!(
1426            "`#[unsafe(method_id(alloc))]` is not supported. ",
1427            "Use `#[unsafe(method(alloc))]` and do the memory management yourself",
1428        ))
1429    };
1430    (method_id(retain)) => {
1431        $crate::__macro_helpers::compile_error!($crate::__macro_helpers::concat!(
1432            "`#[unsafe(method_id(retain))]` is not supported. ",
1433            "Use `#[unsafe(method(retain))]` and do the memory management yourself",
1434        ))
1435    };
1436    (method_id(release)) => {
1437        $crate::__macro_helpers::compile_error!($crate::__macro_helpers::concat!(
1438            "`#[unsafe(method_id(release))]` is not supported. ",
1439            "Use `#[unsafe(method(release))]` and do the memory management yourself",
1440        ))
1441    };
1442    (method_id(autorelease)) => {
1443        $crate::__macro_helpers::compile_error!($crate::__macro_helpers::concat!(
1444            "`#[unsafe(method_id(autorelease))]` is not supported. ",
1445            "Use `#[unsafe(method(autorelease))]` and do the memory management yourself",
1446        ))
1447    };
1448    ($method_or_method_id:ident($($sel:tt)*)) => {};
1449}
1450
1451#[doc(hidden)]
1452#[macro_export]
1453macro_rules! __define_class_no_method_family {
1454    () => {};
1455    ($($t:tt)+) => {
1456        $crate::__macro_helpers::compile_error!(
1457            "`#[unsafe(method_family = ...)]` is not yet supported in `define_class!` together with `#[unsafe(method(...))]`"
1458        )
1459    };
1460}
1461
1462#[doc(hidden)]
1463#[macro_export]
1464macro_rules! __define_class_no_optional {
1465    () => {};
1466    (#[optional]) => {
1467        $crate::__macro_helpers::compile_error!(
1468            "`#[optional]` is only supported in `extern_protocol!`"
1469        )
1470    };
1471}
1472
1473/// Create function pointer type with inferred parameters.
1474#[doc(hidden)]
1475#[macro_export]
1476macro_rules! __fn_ptr {
1477    (
1478        ($($qualifiers:tt)*)
1479        ($($output:tt)*)
1480        $(,)?
1481    ) => {
1482        $($qualifiers)* extern "C-unwind" fn($($output)*) -> _
1483    };
1484    (
1485        ($($qualifiers:tt)*)
1486        ($($output:tt)*)
1487        _ : $param_ty:ty $(, $($rest:tt)*)?
1488    ) => {
1489        $crate::__fn_ptr! {
1490            ($($qualifiers)*)
1491            ($($output)* _,)
1492            $($($rest)*)?
1493        }
1494    };
1495    (
1496        ($($qualifiers:tt)*)
1497        ($($output:tt)*)
1498        mut $param:ident : $param_ty:ty $(, $($rest:tt)*)?
1499    ) => {
1500        $crate::__fn_ptr! {
1501            ($($qualifiers)*)
1502            ($($output)* _,)
1503            $($($rest)*)?
1504        }
1505    };
1506    (
1507        ($($qualifiers:tt)*)
1508        ($($output:tt)*)
1509        $param:ident : $param_ty:ty $(, $($rest:tt)*)?
1510    ) => {
1511        $crate::__fn_ptr! {
1512            ($($qualifiers)*)
1513            ($($output)* _,)
1514            $($($rest)*)?
1515        }
1516    };
1517}