1#![allow(non_snake_case)]
2use 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#[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 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 $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 $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 $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 } 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 } };
636}
637
638#[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
684bitflags! {
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}