@@ -210,13 +210,13 @@ macro_rules! __inner_declare_class {
210210/// either be able to be created using [`MaybeUninit::zeroed`], or be
211211/// properly initialized in an `init` method.
212212///
213- /// `unsafe impl { ... }` asserts that the types match those that are expected
214- /// when the method is invoked from Objective-C. Note that there are no
215- /// safe-guards here; you can easily write `i8`, but if Objective-C thinks
213+ /// `unsafe impl T { ... }` asserts that the types match those that are
214+ /// expected when the method is invoked from Objective-C. Note that there are
215+ /// no safe-guards here; you can easily write `i8`, but if Objective-C thinks
216216/// it's an `u32`, it will cause UB when called!
217217///
218- /// `unsafe impl protocol ... { ... }` requires that all required methods of
219- /// the specified protocol is implemented, and that any extra requirements
218+ /// `unsafe impl Protocol<P> for T { ... }` requires that all required methods
219+ /// of the specified protocol is implemented, and that any extra requirements
220220/// (implicit or explicit) that the protocol has are upheld. The methods in
221221/// this definition has the same safety requirements as above.
222222///
@@ -238,7 +238,7 @@ macro_rules! __inner_declare_class {
238238/// # #[cfg(feature = "gnustep-1-7")]
239239/// # unsafe { objc2::__gnustep_hack::get_class_to_force_linkage() };
240240///
241- /// declare_class! {
241+ /// declare_class!(
242242/// struct MyCustomObject {
243243/// foo: u8,
244244/// pub bar: c_int,
@@ -248,7 +248,7 @@ macro_rules! __inner_declare_class {
248248/// type Superclass = NSObject;
249249/// }
250250///
251- /// unsafe impl {
251+ /// unsafe impl MyCustomObject {
252252/// #[sel(initWithFoo:)]
253253/// fn init_with(&mut self, foo: u8) -> Option<&mut Self> {
254254/// let this: Option<&mut Self> = unsafe {
@@ -275,15 +275,15 @@ macro_rules! __inner_declare_class {
275275/// }
276276/// }
277277///
278- /// unsafe impl protocol NSCopying {
278+ /// unsafe impl Protocol< NSCopying> for MyCustomObject {
279279/// #[sel(copyWithZone:)]
280280/// fn copy_with_zone(&self, _zone: *const NSZone) -> *mut Self {
281281/// let mut obj = Self::new(*self.foo);
282282/// *obj.bar = *self.bar;
283283/// obj.autorelease_return()
284284/// }
285285/// }
286- /// }
286+ /// );
287287///
288288/// impl MyCustomObject {
289289/// pub fn new(foo: u8) -> Id<Self, Owned> {
@@ -385,12 +385,7 @@ macro_rules! declare_class {
385385 type Superclass = $superclass: ty;
386386 }
387387
388- $(
389- $( #[ $impl_m: meta] ) *
390- unsafe impl $( protocol $protocol: ident) ? {
391- $( $methods: tt) *
392- }
393- ) *
388+ $( $methods: tt) *
394389 } => {
395390 $(
396391 #[ allow( non_camel_case_types) ]
@@ -446,24 +441,11 @@ macro_rules! declare_class {
446441 builder. add_static_ivar:: <$ivar>( ) ;
447442 ) *
448443
449- $(
450- // Implement protocol if any specified
451- $(
452- let err_str = concat!( "could not find protocol " , stringify!( $protocol) ) ;
453- builder. add_protocol( $crate:: runtime:: Protocol :: get( stringify!( $protocol) ) . expect( err_str) ) ;
454- ) ?
455-
456- // Implement methods
457- // SAFETY: Upheld by caller
458- unsafe {
459- $crate:: __inner_declare_class! {
460- @rewrite_methods
461- @( register_out( builder) )
462-
463- $( $methods) *
464- }
465- }
466- ) *
444+ // Implement protocols and methods
445+ $crate:: __declare_class_methods!(
446+ @register_out( builder)
447+ $( $methods) *
448+ ) ;
467449
468450 let _cls = builder. register( ) ;
469451 } ) ;
@@ -474,16 +456,123 @@ macro_rules! declare_class {
474456 }
475457
476458 // Methods
477- $(
478- $( #[ $impl_m] ) *
479- impl $name {
480- $crate:: __inner_declare_class! {
481- @rewrite_methods
482- @( method_out)
483-
484- $( $methods) *
485- }
459+ $crate:: __declare_class_methods!(
460+ @method_out
461+ $( $methods) *
462+ ) ;
463+ } ;
464+ }
465+
466+ #[ doc( hidden) ]
467+ #[ macro_export]
468+ macro_rules! __declare_class_methods {
469+ ( @method_out) => { } ;
470+ // With protocol
471+ (
472+ @method_out
473+
474+ $( #[ $m: meta] ) *
475+ unsafe impl Protocol <$protocol: ident> for $for: ty {
476+ $( $methods: tt) *
477+ }
478+
479+ $( $rest: tt) *
480+ ) => {
481+ $( #[ $m] ) *
482+ impl $for {
483+ $crate:: __inner_declare_class! {
484+ @rewrite_methods
485+ @( method_out)
486+ $( $methods) *
486487 }
487- ) *
488+ }
489+
490+ $crate:: __declare_class_methods!(
491+ @method_out
492+ $( $rest) *
493+ ) ;
494+ } ;
495+ // Without protocol
496+ (
497+ @method_out
498+
499+ $( #[ $m: meta] ) *
500+ unsafe impl $for: ty {
501+ $( $methods: tt) *
502+ }
503+
504+ $( $rest: tt) *
505+ ) => {
506+ $( #[ $m] ) *
507+ impl $for {
508+ $crate:: __inner_declare_class! {
509+ @rewrite_methods
510+ @( method_out)
511+ $( $methods) *
512+ }
513+ }
514+
515+ $crate:: __declare_class_methods!(
516+ @method_out
517+ $( $rest) *
518+ ) ;
519+ } ;
520+
521+ ( @register_out( $builder: ident) ) => { } ;
522+ // With protocol
523+ (
524+ @register_out( $builder: ident)
525+
526+ $( #[ $m: meta] ) *
527+ unsafe impl Protocol <$protocol: ident> for $for: ty {
528+ $( $methods: tt) *
529+ }
530+
531+ $( $rest: tt) *
532+ ) => {
533+ // Implement protocol
534+ let err_str = concat!( "could not find protocol " , stringify!( $protocol) ) ;
535+ $builder. add_protocol( $crate:: runtime:: Protocol :: get( stringify!( $protocol) ) . expect( err_str) ) ;
536+
537+ // SAFETY: Upheld by caller
538+ unsafe {
539+ $crate:: __inner_declare_class! {
540+ @rewrite_methods
541+ @( register_out( $builder) )
542+
543+ $( $methods) *
544+ }
545+ }
546+
547+ $crate:: __declare_class_methods!(
548+ @register_out( $builder)
549+ $( $rest) *
550+ ) ;
551+ } ;
552+ // Without protocol
553+ (
554+ @register_out( $builder: ident)
555+
556+ $( #[ $m: meta] ) *
557+ unsafe impl $for: ty {
558+ $( $methods: tt) *
559+ }
560+
561+ $( $rest: tt) *
562+ ) => {
563+ // SAFETY: Upheld by caller
564+ unsafe {
565+ $crate:: __inner_declare_class! {
566+ @rewrite_methods
567+ @( register_out( $builder) )
568+
569+ $( $methods) *
570+ }
571+ }
572+
573+ $crate:: __declare_class_methods!(
574+ @register_out( $builder)
575+ $( $rest) *
576+ ) ;
488577 } ;
489578}
0 commit comments