abi_stable/erased_types/
enabled_traits_macro.rs

1macro_rules! declare_enabled_traits {
2    (
3        auto_traits[
4            $(($auto_trait:ident, $auto_trait_query:ident, $auto_trait_path:path)),* $(,)*
5        ]
6
7        regular_traits[
8            $(($regular_trait:ident, $regular_trait_query:ident, $regular_trait_path:path)),* $(,)*
9        ]
10    ) => (
11        use crate::{
12            abi_stability::extra_checks::{
13                TypeCheckerMut,ExtraChecks,
14                ForExtraChecksImplementor,ExtraChecksError,
15            },
16            type_layout::TypeLayout,
17            std_types::{RCowSlice,RResult},
18        };
19
20        use core_extensions::strings::StringExt;
21
22        #[allow(non_upper_case_globals)]
23        mod auto_trait_mask{
24            #[repr(u32)]
25            enum __Index {
26                $($auto_trait,)*
27            }
28            $(pub(super) const $auto_trait: u16 = 1u16 << __Index::$auto_trait as u32;)*
29        }
30
31        #[allow(non_upper_case_globals)]
32        mod regular_trait_mask{
33            #[repr(u32)]
34            enum __Index {
35                $($regular_trait,)*
36            }
37            $(pub(super) const $regular_trait: u64 = 1u64 << __Index::$regular_trait as u32;)*
38        }
39
40
41        /// Describes which traits are required and enabled by the `I: `[`InterfaceType`]
42        /// that this `RequiredTraits` is created from.
43        ///
44        /// # Purpose
45        ///
46        /// This is what [`DynTrait`] uses to check that the traits it
47        /// requires are compatible between library versions,
48        /// by using this type in
49        /// [`#[sabi(extra_checks = <here>)]`](derive@crate::StableAbi#sabi_extra_checks_attr).
50        ///
51        /// This type requires that auto traits are the same across versions.
52        /// Non-auto traits can be added in newer versions of a library.
53        #[repr(C)]
54        #[derive(Copy,Clone,StableAbi)]
55        pub struct RequiredTraits{
56            auto_traits:u16,
57            regular_traits:u64,
58        }
59
60        impl RequiredTraits {
61            /// Constructs an RequiredTraits.
62            pub const fn new<I: InterfaceType>() -> Self {
63                use crate::type_level::impl_enum::Implementability;
64
65                RequiredTraits {
66                    auto_traits: $(
67                        if <I::$auto_trait as Implementability>::IS_IMPLD {
68                            auto_trait_mask::$auto_trait
69                        } else {
70                            0
71                        }
72                    )|*,
73                    regular_traits: $(
74                        if <I::$regular_trait as Implementability>::IS_IMPLD {
75                            regular_trait_mask::$regular_trait
76                        } else {
77                            0
78                        }
79                    )|*
80                }
81            }
82
83            $(
84                #[doc = concat!(
85                    "Whether the [`",
86                    stringify!($auto_trait_path),
87                    "`] trait is required",
88                )]
89                pub const fn $auto_trait_query(self) -> bool {
90                    (self.auto_traits & auto_trait_mask::$auto_trait) != 0
91                }
92            )*
93            $(
94                #[doc = concat!(
95                    "Whether the [`",
96                    stringify!($regular_trait_path),
97                    "`] trait is required",
98                )]
99                pub const fn $regular_trait_query(self) -> bool {
100                    (self.regular_traits & regular_trait_mask::$regular_trait) != 0
101                }
102            )*
103        }
104
105        impl Debug for RequiredTraits{
106            fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
107                use self::debug_impl_details::{EnabledAutoTraits,EnabledRegularTraits};
108
109                f.debug_struct("RequiredTraits")
110                 .field("auto_traits_bits",&self.auto_traits)
111                 .field("auto_traits",&EnabledAutoTraits{traits:self.auto_traits})
112                 .field("regular_traits_bits",&self.regular_traits)
113                 .field("regular_traits",&EnabledRegularTraits{traits:self.regular_traits})
114                 .finish()
115            }
116        }
117
118        impl Display for RequiredTraits{
119            fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
120                f.write_str("RequiredTraits\n")?;
121
122                f.write_str("Auto traits:")?;
123                if self.auto_traits==0 {
124                    f.write_str("<no_traits>")?;
125                }else{
126                    $(
127                        if (self.auto_traits&auto_trait_mask::$auto_trait)!=0 {
128                            f.write_str(concat!(" ",stringify!($auto_trait)))?;
129                        }
130                    )*
131                }
132                writeln!(f,)?;
133
134                f.write_str("Impld traits:")?;
135                if self.regular_traits==0 {
136                    f.write_str("<no_traits>")?;
137                }else{
138                    $(
139                        if (self.regular_traits&regular_trait_mask::$regular_trait)!=0 {
140                            f.write_str(concat!(" ",stringify!($regular_trait)))?;
141                        }
142                    )*
143                }
144                writeln!(f,)?;
145
146                Ok(())
147            }
148        }
149
150
151        unsafe impl ExtraChecks for RequiredTraits {
152            fn type_layout(&self)->&'static TypeLayout{
153                <Self as StableAbi>::LAYOUT
154            }
155
156            fn check_compatibility(
157                &self,
158                _layout_containing_self:&'static TypeLayout,
159                layout_containing_other:&'static TypeLayout,
160                checker:TypeCheckerMut<'_>,
161            )->RResult<(), ExtraChecksError> {
162                Self::downcast_with_layout(layout_containing_other,checker,|other,_|{
163                    if self.auto_traits!=other.auto_traits {
164                        Err(ImpldTraitsError{
165                            kind:ImpldTraitsErrorKind::MismatchedAutoTraits,
166                            expected:self.clone(),
167                            found:other.clone(),
168                        })
169                    }else if (self.regular_traits&other.regular_traits)!=self.regular_traits {
170                        Err(ImpldTraitsError{
171                            kind:ImpldTraitsErrorKind::UnimpldTraits,
172                            expected:self.clone(),
173                            found:other.clone(),
174                        })
175                    }else{
176                        Ok(())
177                    }
178                })
179            }
180
181            fn nested_type_layouts(&self)->RCowSlice<'_, &'static TypeLayout>{
182                RCowSlice::from_slice(&[])
183            }
184        }
185
186        mod debug_impl_details{
187            use super::*;
188
189            pub(super) struct EnabledAutoTraits{
190                pub(super) traits:u16,
191            }
192
193            impl Debug for EnabledAutoTraits{
194                fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
195                    let mut ds=f.debug_set();
196                    $(
197                        if (self.traits&auto_trait_mask::$auto_trait)!=0 {
198                            ds.entry(&stringify!( $auto_trait ));
199                        }
200                    )*
201                    ds.finish()
202                }
203            }
204
205
206            pub(super) struct EnabledRegularTraits{
207                pub(super) traits:u64,
208            }
209
210            impl Debug for EnabledRegularTraits{
211                fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
212                    let mut ds=f.debug_set();
213                    $(
214                        if (self.traits&regular_trait_mask::$regular_trait)!=0 {
215                            ds.entry(&stringify!( $regular_trait ));
216                        }
217                    )*
218                    ds.finish()
219                }
220            }
221        }
222
223
224        ////////////////////////////////////////////////////////////////////////
225
226
227        #[derive(Debug,Clone)]
228        pub struct ImpldTraitsError{
229            kind:ImpldTraitsErrorKind,
230            expected:RequiredTraits,
231            found:RequiredTraits,
232        }
233
234        #[derive(Debug,Clone)]
235        pub enum ImpldTraitsErrorKind{
236            MismatchedAutoTraits,
237            UnimpldTraits,
238        }
239
240        impl Display for ImpldTraitsError{
241            fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
242
243                let msg=match self.kind {
244                    ImpldTraitsErrorKind::MismatchedAutoTraits=>
245                        "Expected auto traits to be exactly the same",
246                    ImpldTraitsErrorKind::UnimpldTraits=>
247                        "`Expected` does not contain a subset of the traits in`Found`",
248                };
249                f.write_str(msg)?;
250                writeln!(f,)?;
251
252                writeln!(f,"Expected:\n{}",self.expected.to_string().left_padder(4))?;
253                writeln!(f,"Found:\n{}",self.found.to_string().left_padder(4))?;
254
255                Ok(())
256            }
257        }
258
259        impl std::error::Error for ImpldTraitsError{}
260
261    )
262}