Skip to content

Commit c597a2c

Browse files
authored
Merge pull request #231 from madsmtm/extern-class-verify-zst
Statically verify that the user only uses ZSTs in `extern_class!`
2 parents 63755f8 + 5954db6 commit c597a2c

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

objc2/src/__macro_helpers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub use crate::cache::CachedSel;
99
pub use core::borrow::{Borrow, BorrowMut};
1010
pub use core::cell::UnsafeCell;
1111
pub use core::convert::{AsMut, AsRef};
12+
pub use core::mem::size_of;
1213
pub use core::ops::{Deref, DerefMut};
1314
pub use core::option::Option::{self, None, Some};
1415
pub use core::primitive::{bool, str, u8};

objc2/src/macros/extern_class.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@
4747
/// standard memory management messages (this is upheld if [`NSObject`] is
4848
/// part of its inheritance chain).
4949
///
50-
/// Additionally, any fields (if specified) must be zero-sized.
51-
///
5250
/// [`NSObject`]: crate::foundation::NSObject
5351
///
5452
///
@@ -107,6 +105,7 @@ macro_rules! extern_class {
107105
$(#[$m:meta])*
108106
unsafe $v:vis struct $name:ident: $superclass:ty $(, $inheritance_rest:ty)*;
109107
) => {
108+
// Just shorthand syntax for the following
110109
$crate::extern_class! {
111110
$(#[$m])*
112111
unsafe $v struct $name: $superclass $(, $inheritance_rest)* {}
@@ -124,6 +123,16 @@ macro_rules! extern_class {
124123
$($field_vis $field: $field_ty,)*
125124
}
126125
}
126+
127+
const _: () = {
128+
if $crate::__macro_helpers::size_of::<$name>() != 0 {
129+
panic!(concat!(
130+
"the struct ",
131+
stringify!($name),
132+
" is not zero-sized!",
133+
))
134+
}
135+
};
127136
};
128137
}
129138

@@ -181,14 +190,14 @@ macro_rules! __inner_extern_class {
181190
(
182191
$(#[$m:meta])*
183192
unsafe $v:vis struct $name:ident<$($t:ident $(: $b:ident)?),*>: $($inheritance_chain:ty),+ {
184-
$($p:ident: $pty:ty,)*
193+
$($field_vis:vis $field:ident: $field_ty:ty,)*
185194
}
186195
) => {
187196
$crate::__inner_extern_class! {
188197
@__inner
189198
$(#[$m])*
190199
unsafe $v struct $name<$($t $(: $b)?),*>: $($inheritance_chain,)+ $crate::runtime::Object {
191-
$($p: $pty,)*
200+
$($field_vis $field: $field_ty,)*
192201
}
193202
}
194203

@@ -209,7 +218,7 @@ macro_rules! __inner_extern_class {
209218
@__inner
210219
$(#[$m:meta])*
211220
unsafe $v:vis struct $name:ident<$($t:ident $(: $b:ident)?),*>: $superclass:ty $(, $inheritance_rest:ty)* {
212-
$($p_v:vis $p:ident: $pty:ty,)*
221+
$($field_vis:vis $field:ident: $field_ty:ty,)*
213222
}
214223
) => {
215224
$(#[$m])*
@@ -218,7 +227,7 @@ macro_rules! __inner_extern_class {
218227
$v struct $name<$($t $(: $b)?),*> {
219228
__inner: $superclass,
220229
// Additional fields (should only be zero-sized PhantomData or ivars).
221-
$($p_v $p: $pty),*
230+
$($field_vis $field: $field_ty,)*
222231
}
223232

224233
// SAFETY:

test-ui/ui/extern_class_not_zst.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use objc2::extern_class;
2+
use objc2::foundation::NSObject;
3+
4+
extern_class! {
5+
unsafe pub struct NSNumber: NSObject {
6+
var: u32,
7+
}
8+
}
9+
10+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0080]: evaluation of constant value failed
2+
--> ui/extern_class_not_zst.rs
3+
|
4+
| / extern_class! {
5+
| | unsafe pub struct NSNumber: NSObject {
6+
| | var: u32,
7+
| | }
8+
| | }
9+
| |_^ the evaluated program panicked at 'the struct NSNumber is not zero-sized!', $DIR/ui/extern_class_not_zst.rs:4:1
10+
|
11+
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `extern_class` (in Nightly builds, run with -Z macro-backtrace for more info)

0 commit comments

Comments
 (0)