non_exhaustive/
lib.rs

1#![no_std]
2#![warn(clippy::pedantic, missing_docs, clippy::cargo)]
3#![allow(clippy::wildcard_imports)]
4#![cfg_attr(docsrs, feature(doc_auto_cfg))]
5#![doc = include_str!("doc.md")]
6
7#[macro_export]
8#[doc = include_str!("doc.md")]
9macro_rules! non_exhaustive {
10    {$type:ty {$($field:ident: $value:expr,)* ..$default:expr}} => {{
11        #[allow(unused)]
12        let mut value: $type = $default;
13        $(value.$field = $value;)*
14        value
15    }};
16    {$type:ty {$($field:ident: $value:expr),* $(,)?}} => {
17        $crate::non_exhaustive!($type {$($field: $value,)* ..::core::default::Default::default()})
18    };
19}
20
21#[cfg(test)]
22#[allow(clippy::all, unused, clippy::pedantic)]
23mod test {
24    use crate::non_exhaustive;
25
26    #[non_exhaustive]
27    #[derive(Default)]
28    struct Test {
29        a: usize,
30        b: usize,
31        c: usize,
32    }
33
34    #[test]
35    #[rustfmt::skip]
36    fn test() {
37        non_exhaustive!(Test {});
38        non_exhaustive!(Test { a: 1 });
39        non_exhaustive!(Test { a: 1, a: 2 });
40        non_exhaustive!(Test { a: 1, a: 2, a: 3 });
41        non_exhaustive!(Test { a: 1, });
42        non_exhaustive!(Test { a: 1, a: 2, });
43        non_exhaustive!(Test { a: 1, a: 2, a: 3, });
44        non_exhaustive!(Test { ..Default::default() });
45        non_exhaustive!(Test { a: 1, ..Default::default() });
46        non_exhaustive!(Test { a: 1, a: 2, ..Default::default() });
47        non_exhaustive!(Test { a: 1, a: 2, a: 3, ..Default::default() });
48    }
49}