Skip to content

libc: make structs non_exhaustive by default. #4579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,38 @@ macro_rules! prelude {
/// Implement `Clone` and `Copy` for a struct, as well as `Debug`, `Eq`, `Hash`, and
/// `PartialEq` if the `extra_traits` feature is enabled.
///
/// By default, it will mark a struct as `non_exhaustive`. To opt out, use the attribute
/// `#[@not_non_exhaustive]` as the first attribute of the struct.
///
/// Use [`s_no_extra_traits`] for structs where the `extra_traits` feature does not
/// make sense, and for unions.
macro_rules! s {
($(
$(#[@$not_non_exhaustive:ident])*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be able to match a literal, right?

Suggested change
$(#[@$not_non_exhaustive:ident])*
$(#[not_non_exhaustive])?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, it fails with "attempted to repeat an expression containing no syntax variables"

$(#[$attr:meta])*
pub $t:ident $i:ident { $($field:tt)* }
)*) => ($(
s!(it: $(#[$attr])* pub $t $i { $($field)* });
s!(it: $(#[@$not_non_exhaustive])* $(#[$attr])* pub $t $i { $($field)* });
)*);

(it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead");
);

(it: #[@not_non_exhaustive] $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
__item! {
#[repr(C)]
#[cfg_attr(
feature = "extra_traits",
::core::prelude::v1::derive(Debug, Eq, Hash, PartialEq)
)]
#[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)]
#[allow(deprecated)]
$(#[$attr])*
pub struct $i { $($field)* }
}
);

(it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
__item! {
#[repr(C)]
Expand All @@ -116,6 +134,7 @@ macro_rules! s {
)]
#[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)]
#[allow(deprecated)]
#[non_exhaustive]
$(#[$attr])*
pub struct $i { $($field)* }
}
Expand All @@ -125,6 +144,9 @@ macro_rules! s {
/// Implement `Clone` and `Copy` for a tuple struct, as well as `Debug`, `Eq`, `Hash`,
/// and `PartialEq` if the `extra_traits` feature is enabled.
///
/// By default, it will mark a struct as `non_exhaustive`. To opt out, use the attribute
/// `#[@not_non_exhaustive]` as the first attribute of the struct.
///
/// This is the same as [`s`] but works for tuple structs.
macro_rules! s_paren {
($(
Expand All @@ -149,10 +171,11 @@ macro_rules! s_paren {
/// Most items will prefer to use [`s`].
macro_rules! s_no_extra_traits {
($(
$(#[@$not_non_exhaustive:ident])*
$(#[$attr:meta])*
pub $t:ident $i:ident { $($field:tt)* }
)*) => ($(
s_no_extra_traits!(it: $(#[$attr])* pub $t $i { $($field)* });
s_no_extra_traits!(it: $(#[@$not_non_exhaustive])* $(#[$attr])* pub $t $i { $($field)* });
)*);

(it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
Expand All @@ -171,11 +194,22 @@ macro_rules! s_no_extra_traits {
}
);

(it: #[@not_non_exhaustive] $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
__item! {
#[repr(C)]
#[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)]
#[cfg_attr(feature = "extra_traits", ::core::prelude::v1::derive(Debug))]
$(#[$attr])*
pub struct $i { $($field)* }
}
);

(it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
__item! {
#[repr(C)]
#[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)]
#[cfg_attr(feature = "extra_traits", ::core::prelude::v1::derive(Debug))]
#[non_exhaustive]
$(#[$attr])*
pub struct $i { $($field)* }
}
Expand Down
2 changes: 0 additions & 2 deletions src/unix/linux_like/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,6 @@ s! {
}

// linux/openat2.h
#[non_exhaustive]
pub struct open_how {
pub flags: crate::__u64,
pub mode: crate::__u64,
Expand Down Expand Up @@ -1329,7 +1328,6 @@ s! {

// linux/pidfd.h

#[non_exhaustive]
pub struct pidfd_info {
pub mask: crate::__u64,
pub cgroupid: crate::__u64,
Expand Down
1 change: 1 addition & 0 deletions src/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ s! {
pub h_addr_list: *mut *mut c_char,
}

#[@not_non_exhaustive]
pub struct iovec {
pub iov_base: *mut c_void,
pub iov_len: size_t,
Expand Down
Loading