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