Skip to content

Commit

Permalink
Improve __collect_msg_send! macro
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Aug 15, 2022
1 parent b74fdfb commit b229e59
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 170 deletions.
195 changes: 25 additions & 170 deletions objc2/src/macros/extern_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ macro_rules! __inner_extern_methods {
$crate::msg_send;
$self;
($($sel)*);
($($arg),*);
($($arg,)*);
)
};
{
Expand All @@ -346,198 +346,53 @@ macro_rules! __inner_extern_methods {
$crate::msg_send;
Self::class();
($($sel)*);
($($arg),*);
($($arg,)*);
)
};
}

/// Zip selector and arguments, and forward to macro.
///
/// TODO: Investigate if there's a better way of doing this.
#[doc(hidden)]
#[macro_export]
macro_rules! __collect_msg_send {
// Selector with no arguments
(
$macro:path;
$obj:expr;
($s:ident);
();
) => {{
$macro![$obj, $s]
}};
(
$macro:path;
$obj:expr;
($s1:ident:);
($a1:expr);
($sel:ident);
($(,)?);
) => {{
$macro![$obj, $s1: $a1]
}};
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident:);
($a1:expr, $a2:expr);
) => {{
$macro![$obj, $s1: $a1, $s2: $a2]
}};
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident:);
($a1:expr, $a2:expr, $a3:expr);
) => {{
$macro![$obj, $s1: $a1, $s2: $a2, $s3: $a3]
}};
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident: $s4:ident:);
($a1:expr, $a2:expr, $a3:expr, $a4:expr);
) => {{
$macro![$obj, $s1: $a1, $s2: $a2, $s3: $a3, $s4: $a4]
}};
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident: $s4:ident: $s5:ident:);
($a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr);
) => {{
$macro![$obj, $s1: $a1, $s2: $a2, $s3: $a3, $s4: $a4, $s5: $a5]
}};
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident: $s4:ident: $s5:ident: $s6:ident:);
($a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr);
) => {{
$macro![
$obj,
$s1: $a1,
$s2: $a2,
$s3: $a3,
$s4: $a4,
$s5: $a5,
$s6: $a6
]
}};
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident: $s4:ident: $s5:ident: $s6:ident: $s7:ident:);
($a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr);
) => {{
$macro![
$obj,
$s1: $a1,
$s2: $a2,
$s3: $a3,
$s4: $a4,
$s5: $a5,
$s6: $a6,
$s7: $a7
]
}};
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident: $s4:ident: $s5:ident: $s6:ident: $s7:ident: $s8:ident:);
($a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr, $a8:expr);
) => {{
$macro![
$obj,
$s1: $a1,
$s2: $a2,
$s3: $a3,
$s4: $a4,
$s5: $a5,
$s6: $a6,
$s7: $a7,
$s8: $a8
]
}};
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident: $s4:ident: $s5:ident: $s6:ident: $s7:ident: $s8:ident: $s9:ident:);
($a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr, $a8:expr, $a9:expr);
) => {{
$macro![
$obj,
$s1: $a1,
$s2: $a2,
$s3: $a3,
$s4: $a4,
$s5: $a5,
$s6: $a6,
$s7: $a7,
$s8: $a8,
$s9: $a9
]
}};
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident: $s4:ident: $s5:ident: $s6:ident: $s7:ident: $s8:ident: $s9:ident: $s10:ident:);
($a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr, $a8:expr, $a9:expr, $a10:expr);
) => {{
$macro![
$obj,
$s1: $a1,
$s2: $a2,
$s3: $a3,
$s4: $a4,
$s5: $a5,
$s6: $a6,
$s7: $a7,
$s8: $a8,
$s9: $a9,
$s10: $a10
]
$macro![$obj, $sel]
}};

// Base case
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident: $s4:ident: $s5:ident: $s6:ident: $s7:ident: $s8:ident: $s9:ident: $s10:ident: $s11:ident:);
($a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr, $a8:expr, $a9:expr, $a10:expr, $a11:expr);
();
($(,)?);
$($output:tt)+
) => {{
$macro![
$obj,
$s1: $a1,
$s2: $a2,
$s3: $a3,
$s4: $a4,
$s5: $a5,
$s6: $a6,
$s7: $a7,
$s8: $a8,
$s9: $a9,
$s10: $a10,
$s11: $a11
]
$macro![$obj, $($output)+]
}};
// tt-munch each argument
(
$macro:path;
$obj:expr;
($s1:ident: $s2:ident: $s3:ident: $s4:ident: $s5:ident: $s6:ident: $s7:ident: $s8:ident: $s9:ident: $s10:ident: $s11:ident: $s12:ident:);
($a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr, $a7:expr, $a8:expr, $a9:expr, $a10:expr, $a11:expr, $a12:expr);
($sel:ident : $($sel_rest:tt)*);
($arg:ident , $($args_rest:tt)*);
$($output:tt)*
) => {{
$macro![
$obj,
$s1: $a1,
$s2: $a2,
$s3: $a3,
$s4: $a4,
$s5: $a5,
$s6: $a6,
$s7: $a7,
$s8: $a8,
$s9: $a9,
$s10: $a10,
$s11: $a11,
$s12: $a12
]
$crate::__collect_msg_send!(
$macro;
$obj;
($($sel_rest)*);
($($args_rest)*);
$($output)* $sel: $arg,
)
}};

// If couldn't zip selector and arguments, show useful error message
($($_any:tt)*) => {{
compile_error!("Number of arguments in function and selector did not match!")
}};
Expand Down
47 changes: 47 additions & 0 deletions test-ui/ui/extern_methods_wrong_arguments.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use objc2::{extern_class, extern_methods, ClassType};
use objc2::foundation::NSObject;

extern_class!(
pub struct MyObject;

unsafe impl ClassType for MyObject {
type Superclass = NSObject;
}
);

extern_methods!(
unsafe impl MyObject {
#[sel(a:)]
fn a();
}
);

extern_methods!(
unsafe impl MyObject {
#[sel(b)]
fn b(arg: i32);
}
);

extern_methods!(
unsafe impl MyObject {
#[sel(c:d:e:)]
fn c(arg1: i32, arg2: u32);
}
);

extern_methods!(
unsafe impl MyObject {
#[sel(x:)]
fn x(&self);
}
);

extern_methods!(
unsafe impl MyObject {
#[sel(y)]
fn y(&self, arg: i32);
}
);

fn main() {}
64 changes: 64 additions & 0 deletions test-ui/ui/extern_methods_wrong_arguments.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
error: Number of arguments in function and selector did not match!
--> ui/extern_methods_wrong_arguments.rs
|
| / extern_methods!(
| | unsafe impl MyObject {
| | #[sel(a:)]
| | fn a();
| | }
| | );
| |_^
|
= note: this error originates in the macro `$crate::__collect_msg_send` which comes from the expansion of the macro `extern_methods` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Number of arguments in function and selector did not match!
--> ui/extern_methods_wrong_arguments.rs
|
| / extern_methods!(
| | unsafe impl MyObject {
| | #[sel(b)]
| | fn b(arg: i32);
| | }
| | );
| |_^
|
= note: this error originates in the macro `$crate::__collect_msg_send` which comes from the expansion of the macro `extern_methods` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Number of arguments in function and selector did not match!
--> ui/extern_methods_wrong_arguments.rs
|
| / extern_methods!(
| | unsafe impl MyObject {
| | #[sel(c:d:e:)]
| | fn c(arg1: i32, arg2: u32);
| | }
| | );
| |_^
|
= note: this error originates in the macro `$crate::__collect_msg_send` which comes from the expansion of the macro `extern_methods` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Number of arguments in function and selector did not match!
--> ui/extern_methods_wrong_arguments.rs
|
| / extern_methods!(
| | unsafe impl MyObject {
| | #[sel(x:)]
| | fn x(&self);
| | }
| | );
| |_^
|
= note: this error originates in the macro `$crate::__collect_msg_send` which comes from the expansion of the macro `extern_methods` (in Nightly builds, run with -Z macro-backtrace for more info)

error: Number of arguments in function and selector did not match!
--> ui/extern_methods_wrong_arguments.rs
|
| / extern_methods!(
| | unsafe impl MyObject {
| | #[sel(y)]
| | fn y(&self, arg: i32);
| | }
| | );
| |_^
|
= note: this error originates in the macro `$crate::__collect_msg_send` which comes from the expansion of the macro `extern_methods` (in Nightly builds, run with -Z macro-backtrace for more info)

0 comments on commit b229e59

Please sign in to comment.