Skip to main content

verified_bitflags/
lib.rs

1#![allow(non_snake_case)]
2//! A verified version of the [`bitflags`](https://docs.rs/bitflags/latest/bitflags/) crate.
3//!
4//! The macro [`bitflags!`] generates a single `struct` whose layout matches
5//! the one produced by the upstream `bitflags` crate
6//! (see [`bitflags::example_generated::Flags`]):
7//!
8//! ```text
9//! pub struct Flags { bits: T } // bits is private
10//! impl Flags {
11//!     pub const fn A() -> Self;   // one factory per declared flag
12//!     ...
13//!     pub const fn empty() -> Self;
14//!     pub const fn all() -> Self;
15//!     pub const fn bits(&self) -> T;
16//!     pub const fn from_bits(bits: T) -> Option<Self>;
17//!     pub const fn from_bits_truncate(bits: T) -> Self;
18//!     pub const fn contains(&self, other: Self) -> bool;
19//!     pub const fn intersects(&self, other: Self) -> bool;
20//!     pub fn insert(&mut self, other: Self);
21//!     pub fn toggle(&mut self, other: Self);
22//! }
23//! ```
24//!
25//! NOTE: unlike upstream `bitflags`, the per-flag accessors are `pub const fn`
26//! factories (`Flags::A()`) instead of associated constants (`Flags::A`). This
27//! is required because the `bits` field is private:
28//! Verus refuses to publish a constructor for an opaque datatype through a `pub const`.
29//!
30//! Only **literal** values are supported for each flag.
31use vstd::arithmetic::power::*;
32use vstd::arithmetic::power2::*;
33use vstd::bits::*;
34use vstd::prelude::*;
35
36pub use paste;
37
38#[doc(hidden)]
39#[macro_export]
40macro_rules! __bitflags_cfg_expr {
41    (() $base:expr) => {
42        $base
43    };
44    ((#[cfg($($cfg:tt)*)] $($rest:tt)*) $base:expr) => {
45        (cfg!($($cfg)*) && $crate::__bitflags_cfg_expr!(($($rest)*) $base))
46    };
47    ((#[$_other:meta] $($rest:tt)*) $base:expr) => {
48        $crate::__bitflags_cfg_expr!(($($rest)*) $base)
49    };
50}
51
52#[doc(hidden)]
53#[macro_export]
54macro_rules! __bitflags_cfg_guarded_expr {
55    (() $e:expr) => {
56        $e
57    };
58    ((#[cfg($($cfg:tt)*)] $($rest:tt)*) $e:expr) => {{
59        #[cfg($($cfg)*)]
60        {
61            $crate::__bitflags_cfg_guarded_expr!(($($rest)*) $e)
62        }
63        #[cfg(not($($cfg)*))]
64        {
65            true
66        }
67    }};
68    ((#[$_other:meta] $($rest:tt)*) $e:expr) => {
69        $crate::__bitflags_cfg_guarded_expr!(($($rest)*) $e)
70    };
71}
72
73#[doc(hidden)]
74#[macro_export]
75macro_rules! __bitflags_cfg_guarded_stmt {
76    (() $stmt:stmt) => {
77        $stmt
78    };
79    ((#[cfg($($cfg:tt)*)] $($rest:tt)*) $stmt:stmt) => {
80        #[cfg($($cfg)*)]
81        {
82            $crate::__bitflags_cfg_guarded_stmt!(($($rest)*) $stmt)
83        }
84    };
85    ((#[$_other:meta] $($rest:tt)*) $stmt:stmt) => {
86        $crate::__bitflags_cfg_guarded_stmt!(($($rest)*) $stmt)
87    };
88}
89
90/// A macro wrapper for quickly defining bitflags with verified
91/// properties in Verus. It only supports literal values for the bits.
92///
93/// # Example
94///
95/// ```rust,norun
96/// bitflags! {
97///     pub struct Flags: u32 {
98///         const A = 0b00000001;
99///         const B = 0b00000010;
100///         const C = 0b00000100;
101///         const ABC = 0b00000111;
102///     }
103/// }
104///
105/// let f = Flags::A | Flags::B;
106/// assert!(f.contains(Flags::A));
107/// ```
108#[verusfmt::skip]
109#[macro_export]
110macro_rules! bitflags {
111    (
112        $(#[$outer:meta])*
113        $vis:vis struct $name:ident: $T:ty {
114            $(
115                $(#[$inner:ident $($args:tt)*])*
116                const $Flag:ident = $value:expr;
117            )*
118        }
119
120        $($t:tt)*
121    ) => {
122        $crate::paste::paste! {
123        verus! {
124            $(#[$outer])*
125            #[repr(transparent)]
126            $vis struct $name {
127                /// The raw bits backing this flags value.
128                bits: $T,
129            }
130
131            impl ::core::clone::Clone for $name {
132                #[inline]
133                fn clone(&self) -> (r: Self)
134                    returns self
135                {
136                    Self {
137                        bits: self.bits,
138                    }
139                }
140            }
141
142            impl ::core::marker::Copy for $name {}
143
144            impl ::vstd::view::View for $name {
145                type V = ::vstd::set::Set<[< __ghost $name >]>;
146
147                open spec fn view(&self) -> Self::V {
148                    Self::flags_from_bits(self.bits())
149                }
150            }
151
152            #[allow(non_camel_case_types)]
153            $vis ghost enum [< __ghost $name >] {
154                $(
155                    [< __ghost $Flag >],
156                )*
157            }
158
159            impl [< __ghost $name >] {
160                $vis open spec fn enabled(self) -> bool {
161                    match self {
162                        $(
163                            [< __ghost $name >]::[< __ghost $Flag >] => $crate::__bitflags_cfg_expr! {
164                                ($(#[$inner $($args)*])*) true
165                            },
166                        )*
167                    }
168                }
169
170                $vis open spec fn bit(self) -> $T {
171                    match self {
172                        $(
173                            [< __ghost $name >]::[< __ghost $Flag >] => (($value) as $T),
174                        )*
175                    }
176                }
177            }
178
179            impl ::vstd::set_lib::FiniteFull for [< __ghost $name >] {
180                proof fn full_properties() {
181                    let s = ::vstd::iset::ISet::empty()
182                        $(.insert([< __ghost $name >]::[< __ghost $Flag >]))*;
183                    assert(::vstd::iset::ISet::new(|a: [< __ghost $name >]| true) =~= s);
184                }
185            }
186
187            impl $name {
188                $vis open spec fn flags_spec(&self) -> ::vstd::set::Set<[< __ghost $name >]> {
189                    Self::flags_from_bits(self.bits())
190                }
191
192                $vis open spec fn flags_from_bits(bits: $T) -> ::vstd::set::Set<[< __ghost $name >]> {
193                    ::vstd::set::Set::< [< __ghost $name >] >::from_finite_type(|flag: [< __ghost $name >]| {
194                        flag.enabled() && (bits & flag.bit()) == flag.bit()
195                    })
196                }
197
198                closed spec fn from_bits_unchecked_spec(bits: $T) -> Self {
199                    Self { bits }
200                }
201
202                #[verifier::when_used_as_spec(from_bits_unchecked_spec)]
203                const fn from_bits_unchecked(bits: $T) -> (r: Self)
204                    ensures
205                        r.bits() == bits,
206                        r.flags_spec() == Self::flags_from_bits(bits),
207                    returns
208                        Self::from_bits_unchecked(bits),
209                {
210                    Self { bits }
211                }
212
213                $(
214                    $vis closed spec fn [< $Flag _spec >]() -> Self {
215                        Self::from_bits_unchecked_spec($value as $T)
216                    }
217
218                    $(#[$inner $($args)*])*
219                    #[verifier::when_used_as_spec([< $Flag _spec >])]
220                    $vis const fn $Flag() -> (r: Self)
221                        ensures
222                            r.bits() == ($value),
223                            r.flags_spec() == Self::flags_from_bits(($value) as $T),
224                        returns Self::[< $Flag _spec >](),
225                    {
226                        Self::from_bits_unchecked($value)
227                    }
228                )*
229
230                /// The bitwise OR of every declared flag (the "all" bits mask).
231                $vis open spec fn all_bits_spec() -> $T {
232                    (0 as $T) $(| (
233                        if $crate::__bitflags_cfg_expr! { ($(#[$inner $($args)*])*) true } {
234                            (($value) as $T)
235                        } else {
236                            0 as $T
237                        }
238                    ))*
239                }
240
241                #[verifier::when_used_as_spec(all_bits_spec)]
242                $vis const fn all_bits() -> $T
243                    returns Self::all_bits(),
244                {
245                    (0 as $T) $(| (
246                        if $crate::__bitflags_cfg_expr! { ($(#[$inner $($args)*])*) true } {
247                            (($value) as $T)
248                        } else {
249                            0 as $T
250                        }
251                    ))*
252                }
253
254                $(
255                    $(#[$inner $($args)*])*
256                    proof fn [< lemma_ $Flag _constant >]()
257                        ensures
258                            Self::$Flag().bits() == (($value) as $T),
259                    {
260                        let flag = Self::$Flag();
261                        assert(flag.bits() == (($value) as $T));
262                    }
263                )*
264
265                $vis broadcast proof fn lemma_consts()
266                    ensures
267                        $(
268                            #![trigger $crate::__bitflags_cfg_guarded_expr!(
269                                ($(#[$inner $($args)*])*)
270                                Self::$Flag().bits()
271                            )]
272                            $crate::__bitflags_cfg_guarded_expr!(
273                                ($(#[$inner $($args)*])*)
274                                Self::$Flag().bits() == (($value) as $T)
275                            ),
276                        )*
277                {
278                    $(
279                        $crate::__bitflags_cfg_guarded_stmt!(
280                            ($(#[$inner $($args)*])*)
281                            Self::[< lemma_ $Flag _constant >]()
282                        );
283                    )*
284                }
285
286                /// The raw bits stored inside this flags value.
287                $vis closed spec fn bits_spec(&self) -> $T { self.bits }
288
289                #[verifier::when_used_as_spec(bits_spec)]
290                $vis const fn bits(&self) -> $T
291                    returns self.bits(),
292                {
293                    self.bits
294                }
295
296                $vis closed spec fn empty_spec() -> Self {
297                    Self::from_bits_unchecked_spec(0)
298                }
299
300                #[verifier::when_used_as_spec(empty_spec)]
301                $vis const fn empty() -> (r: Self)
302                    ensures
303                        r.bits() == 0,
304                        r.flags_spec() == Self::flags_from_bits(0),
305                    returns Self::empty(),
306                {
307                    Self::from_bits_unchecked(0)
308                }
309
310                $vis closed spec fn all_spec() -> Self {
311                    Self::from_bits_unchecked_spec(Self::all_bits_spec())
312                }
313
314                #[verifier::when_used_as_spec(all_spec)]
315                $vis const fn all() -> (r: Self)
316                    ensures
317                        r == Self::all_spec(),
318                {
319                    Self::from_bits_unchecked(Self::all_bits())
320                }
321
322                $vis open spec fn contains_spec(&self, other: Self) -> bool {
323                    other@.subset_of(self@)
324                }
325
326                $vis open spec fn contains_flags_spec(&self, other: Self) -> bool {
327                    self.contains(other)
328                }
329
330                #[verifier::when_used_as_spec(contains_spec)]
331                $vis const fn contains(&self, other: Self) -> bool
332                    returns self.contains(other),
333                {
334                    let res = $(
335                        (
336                            !$crate::__bitflags_cfg_expr! { ($(#[$inner $($args)*])*) true }
337                            || (other.bits & (($value) as $T)) != (($value) as $T)
338                            || (self.bits & (($value) as $T)) == (($value) as $T)
339                        )
340                    )&&*;
341                    proof {
342                        assert(self@ =~= Self::flags_from_bits(self.bits()));
343                        assert(other@ =~= Self::flags_from_bits(other.bits()));
344
345                        if res {
346                            assert forall|flag: [< __ghost $name >]| #[trigger]
347                                other@.contains(flag) implies self@.contains(flag) by {
348                                match flag {
349                                    $(
350                                        [< __ghost $name >]::[< __ghost $Flag >] => {
351                                            assert(other@.contains(flag));
352                                            assert(Self::flags_from_bits(other.bits()).contains(flag));
353                                            assert(flag.enabled());
354                                            if flag.enabled() {
355                                                assert((other.bits() & (($value) as $T)) == (($value) as $T));
356                                                assert((self.bits() & (($value) as $T)) == (($value) as $T));
357                                                assert(Self::flags_from_bits(self.bits()).contains(flag));
358                                            }
359                                        },
360                                    )*
361                                }
362                            }
363                            assert(other@.subset_of(self@));
364                        }
365
366                        if other@.subset_of(self@) {
367                            $(
368                                if $crate::__bitflags_cfg_expr! { ($(#[$inner $($args)*])*) true }
369                                    && (other.bits() & (($value) as $T)) == (($value) as $T)
370                                {
371                                    assert(Self::flags_from_bits(other.bits()).contains(
372                                        [< __ghost $name >]::[< __ghost $Flag >],
373                                    ));
374                                    assert(other@.contains([< __ghost $name >]::[< __ghost $Flag >]));
375                                    assert(self@.contains([< __ghost $name >]::[< __ghost $Flag >]));
376                                    assert(Self::flags_from_bits(self.bits()).contains(
377                                        [< __ghost $name >]::[< __ghost $Flag >],
378                                    ));
379                                    assert((self.bits() & (($value) as $T)) == (($value) as $T));
380                                }
381                            )*
382                            assert(res);
383                        }
384                    }
385                    res
386                }
387
388                $vis open spec fn intersects_spec(&self, other: Self) -> bool {
389                    exists|flag: [< __ghost $name >]| #[trigger] self@.contains(flag) && other@.contains(flag)
390                }
391
392                #[verifier::when_used_as_spec(intersects_spec)]
393                $vis const fn intersects(&self, other: Self) -> bool
394                    returns self.intersects(other),
395                {
396                    let res = $(
397                        (
398                            $crate::__bitflags_cfg_expr! { ($(#[$inner $($args)*])*) true }
399                            && (self.bits & (($value) as $T)) == (($value) as $T)
400                            && (other.bits & (($value) as $T)) == (($value) as $T)
401                        )
402                    )||*;
403                    proof {
404
405                        if res {
406                            $(
407                                if $crate::__bitflags_cfg_expr! { ($(#[$inner $($args)*])*) true }
408                                    && (self.bits() & (($value) as $T)) == (($value) as $T)
409                                    && (other.bits() & (($value) as $T)) == (($value) as $T)
410                                {
411                                    assert(self@.contains([< __ghost $name >]::[< __ghost $Flag >]));
412                                    assert(other@.contains([< __ghost $name >]::[< __ghost $Flag >]));
413                                    assert(exists|flag: [< __ghost $name >]|
414                                        #[trigger] self@.contains(flag) && other@.contains(flag));
415                                }
416                            )*
417                            assert(exists|flag: [< __ghost $name >]|
418                                #[trigger] self@.contains(flag) && other@.contains(flag));
419                        }
420
421                        if exists|flag: [< __ghost $name >]| #[trigger] self@.contains(flag) && other@.contains(flag) {
422                            let flag = choose|flag: [< __ghost $name >]| self@.contains(flag) && other@.contains(flag);
423                            assert(self@.contains(flag));
424                            assert(other@.contains(flag));
425                            match flag {
426                                $(
427                                    [< __ghost $name >]::[< __ghost $Flag >] => {
428                                        assert(flag.enabled());
429                                        assert((self.bits() & (($value) as $T)) == (($value) as $T));
430                                        assert((other.bits() & (($value) as $T)) == (($value) as $T));
431                                    },
432                                )*
433                            }
434                            assert(res);
435                        }
436                    }
437                    res
438                }
439
440                $vis closed spec fn from_bits_truncate_spec(bits: $T) -> Self {
441                    Self::from_bits_unchecked_spec(bits & Self::all_bits())
442                }
443
444                $vis closed spec fn from_bits_retain_spec(bits: $T) -> Self {
445                    Self::from_bits_unchecked_spec(bits)
446                }
447
448                #[verifier::when_used_as_spec(from_bits_retain_spec)]
449                $vis const fn from_bits_retain(bits: $T) -> (r: Self)
450                    ensures
451                        r.bits() == bits,
452                        r.flags_spec() == Self::flags_from_bits(bits),
453                    returns Self::from_bits_retain(bits),
454                {
455                    Self::from_bits_unchecked(bits)
456                }
457
458                #[verifier::when_used_as_spec(from_bits_truncate_spec)]
459                $vis const fn from_bits_truncate(bits: $T) -> (r: Self)
460                    returns Self::from_bits_truncate(bits),
461                {
462                    Self::from_bits_unchecked(bits & Self::all_bits())
463                }
464
465                $vis closed spec fn from_bits_spec(bits: $T) -> Option<Self> {
466                    if (bits & Self::all_bits()) == bits {
467                        Some(Self::from_bits_unchecked_spec(bits))
468                    } else {
469                        None
470                    }
471                }
472
473                #[verifier::when_used_as_spec(from_bits_spec)]
474                $vis const fn from_bits(bits: $T) -> (r: Option<Self>)
475                    ensures
476                        r is Some == ((bits & Self::all_bits()) == bits),
477                        r matches Some(flags_value) ==> {
478                            &&& flags_value.bits() == bits
479                            &&& flags_value.flags_spec() == Self::flags_from_bits(bits)
480                        },
481                    returns
482                        Self::from_bits(bits),
483                {
484                    if (bits & Self::all_bits()) == bits {
485                        Some(Self::from_bits_unchecked(bits))
486                    } else {
487                        None
488                    }
489                }
490
491                $vis closed spec fn remove_spec(self, other: Self) -> Self {
492                    Self::from_bits_unchecked_spec(self.bits() & !other.bits())
493                }
494
495                $vis fn insert(&mut self, other: Self)
496                    ensures
497                        final(self).bits() == (old(self).bits() | other.bits()),
498                        final(self).flags_spec() == Self::flags_from_bits(
499                            old(self).bits() | other.bits(),
500                        ),
501                {
502                    let bits = self.bits | other.bits;
503                    *self = Self::from_bits_unchecked(bits);
504                }
505
506                $vis fn remove(&mut self, other: Self)
507                    ensures
508                        *final(self) == old(self).remove_spec(other),
509                        final(self).bits() == (old(self).bits() & !other.bits()),
510                        final(self).flags_spec() == Self::flags_from_bits(
511                            old(self).bits() & !other.bits(),
512                        ),
513                {
514                    let bits = self.bits & !other.bits;
515                    *self = Self::from_bits_unchecked(bits);
516                }
517
518                /// The bitwise exclusive-or (`^`) of the bits in `self` and `other`.
519                $vis fn toggle(&mut self, other: Self)
520                    ensures
521                        final(self).bits() == (old(self).bits() ^ other.bits()),
522                        final(self).flags_spec() == Self::flags_from_bits(
523                            old(self).bits() ^ other.bits(),
524                        ),
525                {
526                    let bits = self.bits ^ other.bits;
527                    *self = Self::from_bits_unchecked(bits);
528                }
529
530
531                $vis closed spec fn union_spec(self, other: Self) -> Self {
532                    Self::from_bits_unchecked_spec(self.bits() | other.bits())
533                }
534
535                #[verifier::when_used_as_spec(union_spec)]
536                $vis const fn union(self, other: Self) -> (r: Self)
537                    ensures
538                        r.bits() == (self.bits() | other.bits()),
539                    returns self.union(other),
540                {
541                    Self::from_bits_unchecked(self.bits | other.bits)
542                }
543
544                $vis closed spec fn intersection_spec(self, other: Self) -> Self {
545                    Self::from_bits_unchecked_spec(self.bits() & other.bits())
546                }
547
548                #[verifier::when_used_as_spec(intersection_spec)]
549                $vis const fn intersection(self, other: Self) -> (r: Self)
550                    ensures
551                        r.bits() == (self.bits() & other.bits()),
552                    returns self.intersection(other),
553                {
554                    Self::from_bits_unchecked(self.bits & other.bits)
555                }
556
557                $vis closed spec fn difference_spec(self, other: Self) -> Self {
558                    Self::from_bits_unchecked_spec(self.bits() & !other.bits())
559                }
560
561                #[verifier::when_used_as_spec(difference_spec)]
562                $vis const fn difference(self, other: Self) -> (r: Self)
563                    ensures
564                        r.bits() == (self.bits() & !other.bits()),
565                    returns self.difference(other),
566                {
567                    Self::from_bits_unchecked(self.bits & !other.bits)
568                }
569
570                $vis closed spec fn symmetric_difference_spec(self, other: Self) -> Self {
571                    Self::from_bits_unchecked_spec(self.bits() ^ other.bits())
572                }
573
574                #[verifier::when_used_as_spec(symmetric_difference_spec)]
575                $vis const fn symmetric_difference(self, other: Self) -> (r: Self)
576                    ensures
577                        r.bits() == (self.bits() ^ other.bits()),
578                    returns self.symmetric_difference(other),
579                {
580                    Self::from_bits_unchecked(self.bits ^ other.bits)
581                }
582            }
583
584            impl core::cmp::PartialEq for $name {
585                fn eq(&self, other: &Self) -> (r: bool)
586                    ensures r == (self.bits() == other.bits()),
587                {
588                    self.bits == other.bits
589                }
590            }
591
592            impl ::vstd::std_specs::cmp::PartialEqSpecImpl for $name {
593                closed spec fn obeys_eq_spec() -> bool { true }
594
595                closed spec fn eq_spec(&self, other: &Self) -> bool {
596                    self.bits() == other.bits()
597                }
598            }
599
600            impl core::cmp::Eq for $name {}
601
602            impl ::vstd::std_specs::ops::BitOrSpecImpl for $name {
603                open spec fn obeys_bitor_spec() -> bool { true }
604
605                open spec fn bitor_req(self, rhs: Self) -> bool { true }
606
607                open spec fn bitor_spec(self, rhs: Self) -> Self::Output {
608                    self.union(rhs)
609                }
610            }
611
612            impl core::ops::BitOr for $name {
613                type Output = Self;
614                fn bitor(self, other: Self) -> (r: Self)
615                    ensures
616                        r.bits() == (self.bits() | other.bits()),
617                {
618                    Self::from_bits_unchecked(self.bits | other.bits)
619                }
620            }
621
622            impl vstd::std_specs::ops::BitAndSpecImpl for $name {
623                open spec fn obeys_bitand_spec() -> bool { true }
624
625                open spec fn bitand_req(self, rhs: Self) -> bool { true }
626
627                open spec fn bitand_spec(self, rhs: Self) -> Self::Output {
628                    self.intersection(rhs)
629                }
630            }
631
632            impl core::ops::BitAnd for $name {
633                type Output = Self;
634                fn bitand(self, other: Self) -> (r: Self)
635                    ensures
636                        r.bits() == (self.bits() & other.bits()),
637                {
638                    Self::from_bits_unchecked(self.bits & other.bits)
639                }
640            }
641
642            impl vstd::std_specs::ops::BitXorSpecImpl for $name {
643                open spec fn obeys_bitxor_spec() -> bool { true }
644
645                open spec fn bitxor_req(self, rhs: Self) -> bool { true }
646
647                open spec fn bitxor_spec(self, rhs: Self) -> Self::Output {
648                    self.symmetric_difference(rhs)
649                }
650            }
651
652            impl core::ops::BitXor for $name {
653                type Output = Self;
654                fn bitxor(self, other: Self) -> (r: Self)
655                    ensures
656                        r.bits() == (self.bits() ^ other.bits()),
657                {
658                    Self::from_bits_unchecked(self.bits ^ other.bits)
659                }
660            }
661
662            impl vstd::std_specs::ops::SubSpecImpl for $name {
663                open spec fn obeys_sub_spec() -> bool { true }
664
665                open spec fn sub_req(self, rhs: Self) -> bool { true }
666
667                open spec fn sub_spec(self, rhs: Self) -> Self::Output {
668                    self.difference(rhs)
669                }
670            }
671
672            impl core::ops::Sub for $name {
673                type Output = Self;
674                fn sub(self, other: Self) -> (r: Self)
675                    ensures
676                        r.bits() == (self.bits() & !other.bits()),
677                {
678                    self.difference(other)
679                }
680            }
681
682            impl vstd::std_specs::ops::NotSpecImpl for $name {
683                open spec fn obeys_not_spec() -> bool { true }
684
685                open spec fn not_req(self) -> bool { true }
686
687                closed spec fn not_spec(self) -> Self::Output {
688                    Self::from_bits_unchecked_spec(!self.bits() & Self::all_bits())
689                }
690            }
691
692            impl core::ops::Not for $name {
693                type Output = Self;
694
695                fn not(self) -> (r: Self)
696                    ensures
697                        r.bits() == (!self.bits() & $name::all_bits()),
698                {
699                    Self::from_bits_unchecked(!self.bits & $name::all_bits())
700                }
701            }
702
703        } // verus!
704
705        impl ::core::fmt::Debug for $name {
706            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
707                f.debug_tuple(stringify!($name)).field(&self.bits).finish()
708            }
709        }
710
711        } // paste!
712    };
713}
714
715/// Defines quick named compositions of existing flags.
716///
717/// `bitflags!` only accepts literal values for `const X = ...`, so it cannot
718/// express something like `const AB = A | B;`. This helper macro adds extra
719/// factory methods to an existing flags type, each one OR-ing together a list
720/// of `$T` expressions and truncating any bits that are not declared on the
721/// type.
722///
723/// # Example
724///
725/// ```rust,ignore
726/// bitflags! {
727///     pub struct Flags: u32 {
728///         const A = 0b001;
729///         const B = 0b010;
730///         const C = 0b100;
731///     }
732/// }
733///
734/// bitflags_quick! {
735///     Flags,
736///     ab: { Flags::A().bits(), Flags::B().bits() },
737///     ac: { Flags::A().bits(), Flags::C().bits() },
738/// }
739///
740/// let f = Flags::ab();          // bits == 0b011
741/// assert!(f.contains(Flags::A()));
742/// ```
743#[macro_export]
744#[verusfmt::skip]
745macro_rules! bitflags_quick {
746    ($name:ident, $($bit_name:ident : { $($bits:expr),* $(,)? }),* $(,)?) => {
747        verus! {
748            impl $name {
749                $(
750                    pub fn $bit_name() -> (r: Self)
751                        ensures r == Self::from_bits_truncate( ($($bits)|*) as _ ),
752                    {
753                        Self::from_bits_truncate( ($($bits)|*) as _ )
754                    }
755                )*
756            }
757        }
758    };
759}
760
761// ---------------------------------------------------------------------------
762// Smoke test: instantiate the `bitflags!` macro to make sure it expands and
763// verifies. Mirrors `bitflags::example_generated::Flags`.
764// ---------------------------------------------------------------------------
765
766bitflags! {
767    pub struct Flags: u32 {
768        const A = 0b00000001;
769        const B = 0b00000010;
770        const C = 0b00000100;
771        const ABC = 0b00000111;
772    }
773}
774
775verus! {
776
777#[allow(dead_code)]
778fn _bitflags_smoke_test() {
779    let a = Flags::A();
780    let b = Flags::B();
781    let c = Flags::C();
782    let abc = Flags::ABC();
783
784    assert(a.bits() == 0b001u32);
785    assert(a.bits() == Flags::A().bits());
786    assert(b.bits() == 0b010u32);
787    assert(c.bits() == 0b100u32);
788    assert(abc.bits() == 0b111u32);
789    assert(a@ =~= Flags::flags_from_bits(a.bits()));
790    assert(abc@ =~= Flags::flags_from_bits(abc.bits()));
791
792    let abc_b = abc.bits();
793    let a_b = a.bits();
794    let b_b = b.bits();
795    assert((abc_b & a_b) == a_b) by (bit_vector)
796        requires
797            abc_b == 0b111u32 && a_b == 0b001u32,
798    ;
799    assert((abc_b & b_b) == b_b) by (bit_vector)
800        requires
801            abc_b == 0b111u32 && b_b == 0b010u32,
802    ;
803    assert((a_b & b_b) != b_b) by (bit_vector)
804        requires
805            a_b == 0b001u32 && b_b == 0b010u32,
806    ;
807    assert forall|flag: __ghostFlags| #[trigger] abc@.contains(flag) by {
808        assert(abc@ =~= Flags::flags_from_bits(abc.bits()));
809        match flag {
810            __ghostFlags::__ghostA => {
811                assert((abc_b & 0b001u32) == 0b001u32) by (bit_vector)
812                    requires abc_b == 0b111u32,
813                ;
814                assert((abc.bits() & 0b001u32) == 0b001u32);
815            },
816            __ghostFlags::__ghostB => {
817                assert((abc_b & 0b010u32) == 0b010u32) by (bit_vector)
818                    requires abc_b == 0b111u32,
819                ;
820                assert((abc.bits() & 0b010u32) == 0b010u32);
821            },
822            __ghostFlags::__ghostC => {
823                assert((abc_b & 0b100u32) == 0b100u32) by (bit_vector)
824                    requires abc_b == 0b111u32,
825                ;
826                assert((abc.bits() & 0b100u32) == 0b100u32);
827            },
828            __ghostFlags::__ghostABC => {
829                assert((abc_b & 0b111u32) == 0b111u32) by (bit_vector)
830                    requires abc_b == 0b111u32,
831                ;
832                assert((abc.bits() & 0b111u32) == 0b111u32);
833            },
834        }
835    }
836    assert(a@.subset_of(abc@));
837    assert(b@.subset_of(abc@));
838    assert(b@.contains(__ghostFlags::__ghostB)) by {
839        assert(b@ =~= Flags::flags_from_bits(b.bits()));
840        assert((b_b & 0b010u32) == 0b010u32) by (bit_vector)
841            requires b_b == 0b010u32,
842        ;
843        assert((b.bits() & 0b010u32) == 0b010u32);
844    }
845    assert(a@.contains(__ghostFlags::__ghostA)) by {
846        assert(a@ =~= Flags::flags_from_bits(a.bits()));
847        assert((a_b & 0b001u32) == 0b001u32) by (bit_vector)
848            requires a_b == 0b001u32,
849        ;
850        assert((a.bits() & 0b001u32) == 0b001u32);
851    }
852    assert(!a@.contains(__ghostFlags::__ghostB)) by {
853        assert(a@ =~= Flags::flags_from_bits(a.bits()));
854        assert((a_b & 0b010u32) != 0b010u32) by (bit_vector)
855            requires a_b == 0b001u32,
856        ;
857        assert((a.bits() & 0b010u32) != 0b010u32);
858    }
859    assert(!b@.subset_of(a@)) by {
860        if b@.subset_of(a@) {
861            assert(a@.contains(__ghostFlags::__ghostB));
862        }
863    }
864    assert(abc.contains(a));
865    assert(abc.contains(b));
866    assert(!a.contains(b));
867
868    let mut removed = abc;
869    removed.remove(a);
870    let removed_b = removed.bits();
871    assert(removed_b == (abc_b & !a_b));
872    assert(removed_b == 0b110u32) by (bit_vector)
873        requires
874            removed_b == (abc_b & !a_b),
875            abc_b == 0b111u32 && a_b == 0b001u32,
876    ;
877    assert(removed@ =~= Flags::flags_from_bits(removed.bits()));
878
879    assert(abc.intersects(a)) by {
880        assert(abc@.contains(__ghostFlags::__ghostA));
881        assert(a@.contains(__ghostFlags::__ghostA));
882        assert(exists|flag: __ghostFlags| #[trigger] abc@.contains(flag) && a@.contains(flag));
883    }
884    assert(!a.intersects(b)) by {
885        assert forall|flag: __ghostFlags| !(#[trigger] a@.contains(flag) && b@.contains(flag)) by {
886            match flag {
887                __ghostFlags::__ghostA => {
888                    assert(b@ =~= Flags::flags_from_bits(b.bits()));
889                    assert((b_b & 0b001u32) != 0b001u32) by (bit_vector)
890                        requires b_b == 0b010u32,
891                    ;
892                    assert((b.bits() & 0b001u32) != 0b001u32);
893                    assert(!b@.contains(flag));
894                },
895                __ghostFlags::__ghostB => {
896                    assert(!a@.contains(flag));
897                },
898                __ghostFlags::__ghostC => {
899                    assert(a@ =~= Flags::flags_from_bits(a.bits()));
900                    assert((a_b & 0b100u32) != 0b100u32) by (bit_vector)
901                        requires a_b == 0b001u32,
902                    ;
903                    assert((a.bits() & 0b100u32) != 0b100u32);
904                    assert(!a@.contains(flag));
905                },
906                __ghostFlags::__ghostABC => {
907                    assert(a@ =~= Flags::flags_from_bits(a.bits()));
908                    assert((a_b & 0b111u32) != 0b111u32) by (bit_vector)
909                        requires a_b == 0b001u32,
910                    ;
911                    assert((a.bits() & 0b111u32) != 0b111u32);
912                    assert(!a@.contains(flag));
913                },
914            }
915        }
916        assert(!exists|flag: __ghostFlags| #[trigger] a@.contains(flag) && b@.contains(flag));
917    }
918
919}
920
921} // verus!