1 pub mod lexer;
2 mod parser;
3 
4 use smallvec::SmallVec;
5 use std::ops::Range;
6 
7 /// A predicate function, used to combine 1 or more predicates
8 /// into a single value
9 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
10 pub enum Func {
11     /// `not()` with a configuration predicate. It is true if its predicate
12     /// is false and false if its predicate is true.
13     Not,
14     /// `all()` with a comma separated list of configuration predicates. It
15     /// is false if at least one predicate is false. If there are no predicates,
16     /// it is true.
17     ///
18     /// The associated `usize` is the number of predicates inside the `all()`.
19     All(usize),
20     /// `any()` with a comma separated list of configuration predicates. It
21     /// is true if at least one predicate is true. If there are no predicates,
22     /// it is false.
23     ///
24     /// The associated `usize` is the number of predicates inside the `any()`.
25     Any(usize),
26 }
27 
28 use crate::targets as targ;
29 
30 /// All predicates that pertains to a target, except for `target_feature`
31 #[derive(Clone, Copy, PartialEq, Debug)]
32 pub enum TargetPredicate<'a> {
33     /// [target_arch](https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch)
34     Arch(targ::Arch<'a>),
35     /// [target_endian](https://doc.rust-lang.org/reference/conditional-compilation.html#target_endian)
36     Endian(targ::Endian),
37     /// [target_env](https://doc.rust-lang.org/reference/conditional-compilation.html#target_env)
38     Env(targ::Env<'a>),
39     /// [target_family](https://doc.rust-lang.org/reference/conditional-compilation.html#target_family)
40     /// This also applies to the bare [`unix` and `windows`](https://doc.rust-lang.org/reference/conditional-compilation.html#unix-and-windows)
41     /// predicates.
42     Family(targ::Family),
43     /// [target_os](https://doc.rust-lang.org/reference/conditional-compilation.html#target_os)
44     Os(targ::Os<'a>),
45     /// [target_pointer_width](https://doc.rust-lang.org/reference/conditional-compilation.html#target_pointer_width)
46     PointerWidth(u8),
47     /// [target_vendor](https://doc.rust-lang.org/reference/conditional-compilation.html#target_vendor)
48     Vendor(targ::Vendor<'a>),
49 }
50 
51 pub trait TargetMatcher {
matches(&self, tp: TargetPredicate<'_>) -> bool52     fn matches(&self, tp: TargetPredicate<'_>) -> bool;
53 }
54 
55 impl<'a> TargetMatcher for targ::TargetInfo<'a> {
matches(&self, tp: TargetPredicate<'_>) -> bool56     fn matches(&self, tp: TargetPredicate<'_>) -> bool {
57         use TargetPredicate::{Arch, Endian, Env, Family, Os, PointerWidth, Vendor};
58 
59         match tp {
60             Arch(a) => a == self.arch,
61             Endian(end) => end == self.endian,
62             // The environment is allowed to be an empty string
63             Env(env) => match self.env {
64                 Some(e) => env == e,
65                 None => env.0.is_empty(),
66             },
67             Family(fam) => Some(fam) == self.family,
68             Os(os) => Some(os) == self.os,
69             PointerWidth(w) => w == self.pointer_width,
70             Vendor(ven) => match self.vendor {
71                 Some(v) => ven == v,
72                 None => ven.0 == "unknown",
73             },
74         }
75     }
76 }
77 
78 #[cfg(feature = "targets")]
79 impl TargetMatcher for target_lexicon::Triple {
80     #[allow(clippy::cognitive_complexity)]
81     #[allow(clippy::match_same_arms)]
matches(&self, tp: TargetPredicate<'_>) -> bool82     fn matches(&self, tp: TargetPredicate<'_>) -> bool {
83         use target_lexicon::*;
84         use TargetPredicate::{Arch, Endian, Env, Family, Os, PointerWidth, Vendor};
85 
86         match tp {
87             Arch(arch) => {
88                 if arch.0 == "x86" {
89                     matches!(self.architecture, Architecture::X86_32(_))
90                 } else if arch.0 == "wasm32" {
91                     self.architecture == Architecture::Wasm32
92                         || self.architecture == Architecture::Asmjs
93                 } else if arch.0 == "arm" {
94                     matches!(self.architecture, Architecture::Arm(_))
95                 } else {
96                     match arch.0.parse::<Architecture>() {
97                         Ok(a) => match (self.architecture, a) {
98                             (Architecture::Mips32(_), Architecture::Mips32(_))
99                             | (Architecture::Mips64(_), Architecture::Mips64(_))
100                             | (Architecture::Powerpc64le, Architecture::Powerpc64)
101                             | (Architecture::Riscv32(_), Architecture::Riscv32(_))
102                             | (Architecture::Riscv64(_), Architecture::Riscv64(_))
103                             | (Architecture::Sparcv9, Architecture::Sparc64) => true,
104                             (a, b) => a == b,
105                         },
106                         Err(_) => false,
107                     }
108                 }
109             }
110             Endian(end) => match self.architecture.endianness() {
111                 Ok(endian) => matches!(
112                     (end, endian),
113                     (crate::targets::Endian::little, Endianness::Little)
114                         | (crate::targets::Endian::big, Endianness::Big)
115                 ),
116 
117                 Err(_) => false,
118             },
119             Env(env) => {
120                 // The environment is implied by some operating systems
121                 match self.operating_system {
122                     OperatingSystem::Redox => env.0 == "relibc",
123                     OperatingSystem::VxWorks => env.0 == "gnu",
124                     OperatingSystem::Freebsd => match self.architecture {
125                         Architecture::Arm(ArmArchitecture::Armv6)
126                         | Architecture::Arm(ArmArchitecture::Armv7) => env.0 == "gnueabihf",
127                         _ => env.0.is_empty(),
128                     },
129                     OperatingSystem::Netbsd => match self.architecture {
130                         Architecture::Arm(ArmArchitecture::Armv6)
131                         | Architecture::Arm(ArmArchitecture::Armv7) => env.0 == "eabihf",
132                         _ => env.0.is_empty(),
133                     },
134                     OperatingSystem::None_
135                     | OperatingSystem::Cloudabi
136                     | OperatingSystem::Hermit
137                     | OperatingSystem::Ios => env.0.is_empty(),
138                     _ => {
139                         if env.0.is_empty() {
140                             matches!(
141                                 self.environment,
142                                 Environment::Unknown
143                                     | Environment::Android
144                                     | Environment::Softfloat
145                                     | Environment::Androideabi
146                                     | Environment::Eabi
147                             )
148                         } else {
149                             match env.0.parse::<Environment>() {
150                                 Ok(e) => {
151                                     // Rustc shortens multiple "gnu*" environments to just "gnu"
152                                     if env.0 == "gnu" {
153                                         match self.environment {
154                                             Environment::Gnu
155                                             | Environment::Gnuabi64
156                                             | Environment::Gnueabi
157                                             | Environment::Gnuspe
158                                             | Environment::Gnux32
159                                             | Environment::Gnueabihf => true,
160                                             // Rust 1.49.0 changed all android targets to have the
161                                             // gnu environment
162                                             Environment::Android | Environment::Androideabi
163                                                 if self.operating_system
164                                                     == OperatingSystem::Linux =>
165                                             {
166                                                 true
167                                             }
168                                             Environment::Kernel => {
169                                                 self.operating_system == OperatingSystem::Linux
170                                             }
171                                             _ => false,
172                                         }
173                                     } else if env.0 == "musl" {
174                                         matches!(
175                                             self.environment,
176                                             Environment::Musl
177                                                 | Environment::Musleabi
178                                                 | Environment::Musleabihf
179                                                 | Environment::Muslabi64
180                                         )
181                                     } else if env.0 == "uclibc" {
182                                         matches!(
183                                             self.environment,
184                                             Environment::Uclibc | Environment::Uclibceabi
185                                         )
186                                     } else {
187                                         self.environment == e
188                                     }
189                                 }
190                                 Err(_) => false,
191                             }
192                         }
193                     }
194                 }
195             }
196             Family(fam) => {
197                 use target_lexicon::OperatingSystem::{
198                     AmdHsa, Bitrig, Cloudabi, Cuda, Darwin, Dragonfly, Emscripten, Freebsd,
199                     Fuchsia, Haiku, Hermit, Illumos, Ios, L4re, Linux, MacOSX, Nebulet, Netbsd,
200                     None_, Openbsd, Redox, Solaris, Tvos, Uefi, Unknown, VxWorks, Wasi, Windows,
201                 };
202                 Some(fam)
203                     == match self.operating_system {
204                         Unknown | AmdHsa | Bitrig | Cloudabi | Cuda | Hermit | Nebulet | None_
205                         | Uefi | Wasi => None,
206                         Darwin
207                         | Dragonfly
208                         | Emscripten
209                         | Freebsd
210                         | Fuchsia
211                         | Haiku
212                         | Illumos
213                         | Ios
214                         | L4re
215                         | MacOSX { .. }
216                         | Netbsd
217                         | Openbsd
218                         | Redox
219                         | Solaris
220                         | Tvos
221                         | VxWorks => Some(crate::targets::Family::unix),
222                         Linux => {
223                             // The 'kernel' environment is treated specially as not-unix
224                             if self.environment != Environment::Kernel {
225                                 Some(crate::targets::Family::unix)
226                             } else {
227                                 None
228                             }
229                         }
230                         Windows => Some(crate::targets::Family::windows),
231                         // I really dislike non-exhaustive :(
232                         _ => None,
233                     }
234             }
235             Os(os) => match os.0.parse::<OperatingSystem>() {
236                 Ok(o) => self.operating_system == o,
237                 Err(_) => {
238                     // Handle special case for darwin/macos, where the triple is
239                     // "darwin", but rustc identifies the OS as "macos"
240                     if os.0 == "macos" && self.operating_system == OperatingSystem::Darwin {
241                         true
242                     } else {
243                         // For android, the os is still linux, but the environment is android
244                         os.0 == "android"
245                             && self.operating_system == OperatingSystem::Linux
246                             && (self.environment == Environment::Android
247                                 || self.environment == Environment::Androideabi)
248                     }
249                 }
250             },
251             Vendor(ven) => match ven.0.parse::<target_lexicon::Vendor>() {
252                 Ok(v) => match self.operating_system {
253                     OperatingSystem::Solaris => v == target_lexicon::Vendor::Sun,
254                     _ => self.vendor == v,
255                 },
256                 Err(_) => false,
257             },
258             PointerWidth(pw) => {
259                 // The gnux32 environment is a special case, where it has an
260                 // x86_64 architecture, but a 32-bit pointer width
261                 if self.environment != Environment::Gnux32 {
262                     pw == match self.pointer_width() {
263                         Ok(pw) => pw.bits(),
264                         Err(_) => return false,
265                     }
266                 } else {
267                     pw == 32
268                 }
269             }
270         }
271     }
272 }
273 
274 impl<'a> TargetPredicate<'a> {
275     /// Returns true of the predicate matches the specified target
276     ///
277     /// ```
278     /// use cfg_expr::{targets::*, expr::TargetPredicate as tp};
279     /// let win = get_builtin_target_by_triple("x86_64-pc-windows-msvc").unwrap();
280     ///
281     /// assert!(
282     ///     tp::Arch(Arch::x86_64).matches(win) &&
283     ///     tp::Endian(Endian::little).matches(win) &&
284     ///     tp::Env(Env::msvc).matches(win) &&
285     ///     tp::Family(Family::windows).matches(win) &&
286     ///     tp::Os(Os::windows).matches(win) &&
287     ///     tp::PointerWidth(64).matches(win) &&
288     ///     tp::Vendor(Vendor::pc).matches(win)
289     /// );
290     /// ```
matches<T>(self, target: &T) -> bool where T: TargetMatcher,291     pub fn matches<T>(self, target: &T) -> bool
292     where
293         T: TargetMatcher,
294     {
295         target.matches(self)
296     }
297 }
298 
299 #[derive(Clone, Debug)]
300 pub(crate) enum Which {
301     Arch,
302     Endian(targ::Endian),
303     Env,
304     Family(targ::Family),
305     Os,
306     PointerWidth(u8),
307     Vendor,
308 }
309 
310 #[derive(Clone, Debug)]
311 pub(crate) struct InnerTarget {
312     which: Which,
313     span: Option<Range<usize>>,
314 }
315 
316 /// A single predicate in a `cfg()` expression
317 #[derive(Debug, PartialEq)]
318 pub enum Predicate<'a> {
319     /// A target predicate, with the `target_` prefix
320     Target(TargetPredicate<'a>),
321     /// Whether rustc's test harness is [enabled](https://doc.rust-lang.org/reference/conditional-compilation.html#test)
322     Test,
323     /// [Enabled](https://doc.rust-lang.org/reference/conditional-compilation.html#debug_assertions)
324     /// when compiling without optimizations.
325     DebugAssertions,
326     /// [Enabled](https://doc.rust-lang.org/reference/conditional-compilation.html#proc_macro) for
327     /// crates of the proc_macro type.
328     ProcMacro,
329     /// A [`feature = "<name>"`](https://doc.rust-lang.org/nightly/cargo/reference/features.html)
330     Feature(&'a str),
331     /// [target_feature](https://doc.rust-lang.org/reference/conditional-compilation.html#target_feature)
332     TargetFeature(&'a str),
333     /// A generic bare predicate key that doesn't match one of the known options, eg `cfg(bare)`
334     Flag(&'a str),
335     /// A generic key = "value" predicate that doesn't match one of the known options, eg `cfg(foo = "bar")`
336     KeyValue { key: &'a str, val: &'a str },
337 }
338 
339 #[derive(Clone, Debug)]
340 pub(crate) enum InnerPredicate {
341     Target(InnerTarget),
342     Test,
343     DebugAssertions,
344     ProcMacro,
345     Feature(Range<usize>),
346     TargetFeature(Range<usize>),
347     Other {
348         identifier: Range<usize>,
349         value: Option<Range<usize>>,
350     },
351 }
352 
353 impl InnerPredicate {
to_pred<'a>(&self, s: &'a str) -> Predicate<'a>354     fn to_pred<'a>(&self, s: &'a str) -> Predicate<'a> {
355         use InnerPredicate as IP;
356         use Predicate::{
357             DebugAssertions, Feature, Flag, KeyValue, ProcMacro, Target, TargetFeature, Test,
358         };
359 
360         match self {
361             IP::Target(it) => match &it.which {
362                 Which::Arch => Target(TargetPredicate::Arch(targ::Arch(
363                     &s[it.span.clone().unwrap()],
364                 ))),
365                 Which::Os => Target(TargetPredicate::Os(targ::Os(&s[it.span.clone().unwrap()]))),
366                 Which::Vendor => Target(TargetPredicate::Vendor(targ::Vendor(
367                     &s[it.span.clone().unwrap()],
368                 ))),
369                 Which::Env => Target(TargetPredicate::Env(targ::Env(
370                     &s[it.span.clone().unwrap()],
371                 ))),
372                 Which::Endian(end) => Target(TargetPredicate::Endian(*end)),
373                 Which::Family(fam) => Target(TargetPredicate::Family(*fam)),
374                 Which::PointerWidth(pw) => Target(TargetPredicate::PointerWidth(*pw)),
375             },
376             IP::Test => Test,
377             IP::DebugAssertions => DebugAssertions,
378             IP::ProcMacro => ProcMacro,
379             IP::Feature(rng) => Feature(&s[rng.clone()]),
380             IP::TargetFeature(rng) => TargetFeature(&s[rng.clone()]),
381             IP::Other { identifier, value } => match value {
382                 Some(vs) => KeyValue {
383                     key: &s[identifier.clone()],
384                     val: &s[vs.clone()],
385                 },
386                 None => Flag(&s[identifier.clone()]),
387             },
388         }
389     }
390 }
391 
392 #[derive(Clone, Debug)]
393 pub(crate) enum ExprNode {
394     Fn(Func),
395     Predicate(InnerPredicate),
396 }
397 
398 /// A parsed `cfg()` expression that can evaluated
399 #[derive(Clone, Debug)]
400 pub struct Expression {
401     pub(crate) expr: SmallVec<[ExprNode; 5]>,
402     // We keep the original string around for providing the arbitrary
403     // strings that can make up an expression
404     pub(crate) original: String,
405 }
406 
407 impl Expression {
408     /// An iterator over each predicate in the expression
predicates(&self) -> impl Iterator<Item = Predicate<'_>>409     pub fn predicates(&self) -> impl Iterator<Item = Predicate<'_>> {
410         self.expr.iter().filter_map(move |item| match item {
411             ExprNode::Predicate(pred) => {
412                 let pred = pred.clone().to_pred(&self.original);
413                 Some(pred)
414             }
415             _ => None,
416         })
417     }
418 
419     /// Evaluates the expression, using the provided closure to determine the value of
420     /// each predicate, which are then combined into a final result depending on the
421     /// functions not(), all(), or any() in the expression.
422     ///
423     /// `eval_predicate` typically returns `bool`, but may return any type that implements
424     /// the `Logic` trait.
425     ///
426     /// ## Examples
427     ///
428     /// ```
429     /// use cfg_expr::{targets::*, Expression, Predicate};
430     ///
431     /// let linux_musl = get_builtin_target_by_triple("x86_64-unknown-linux-musl").unwrap();
432     ///
433     /// let expr = Expression::parse(r#"all(not(windows), target_env = "musl", any(target_arch = "x86", target_arch = "x86_64"))"#).unwrap();
434     ///
435     /// assert!(expr.eval(|pred| {
436     ///     match pred {
437     ///         Predicate::Target(tp) => tp.matches(linux_musl),
438     ///         _ => false,
439     ///     }
440     /// }));
441     /// ```
442     ///
443     /// Returning `Option<bool>`, where `None` indicates the result is unknown:
444     ///
445     /// ```
446     /// use cfg_expr::{targets::*, Expression, Predicate};
447     ///
448     /// let expr = Expression::parse(r#"any(target_feature = "sse2", target_env = "musl")"#).unwrap();
449     ///
450     /// let linux_gnu = get_builtin_target_by_triple("x86_64-unknown-linux-gnu").unwrap();
451     /// let linux_musl = get_builtin_target_by_triple("x86_64-unknown-linux-musl").unwrap();
452     ///
453     /// fn eval(expr: &Expression, target: &TargetInfo) -> Option<bool> {
454     ///     expr.eval(|pred| {
455     ///         match pred {
456     ///             Predicate::Target(tp) => Some(tp.matches(target)),
457     ///             Predicate::TargetFeature(_) => None,
458     ///             _ => panic!("unexpected predicate"),
459     ///         }
460     ///     })
461     /// }
462     ///
463     /// // Whether the target feature is present is unknown, so the whole expression evaluates to
464     /// // None (unknown).
465     /// assert_eq!(eval(&expr, linux_gnu), None);
466     ///
467     /// // Whether the target feature is present is irrelevant for musl, since the any() always
468     /// // evaluates to true.
469     /// assert_eq!(eval(&expr, linux_musl), Some(true));
470     /// ```
eval<EP, T>(&self, mut eval_predicate: EP) -> T where EP: FnMut(&Predicate<'_>) -> T, T: Logic + std::fmt::Debug,471     pub fn eval<EP, T>(&self, mut eval_predicate: EP) -> T
472     where
473         EP: FnMut(&Predicate<'_>) -> T,
474         T: Logic + std::fmt::Debug,
475     {
476         let mut result_stack = SmallVec::<[T; 8]>::new();
477 
478         // We store the expression as postfix, so just evaluate each license
479         // requirement in the order it comes, and then combining the previous
480         // results according to each operator as it comes
481         for node in self.expr.iter() {
482             match node {
483                 ExprNode::Predicate(pred) => {
484                     let pred = pred.to_pred(&self.original);
485 
486                     result_stack.push(eval_predicate(&pred));
487                 }
488                 ExprNode::Fn(Func::All(count)) => {
489                     // all() with a comma separated list of configuration predicates.
490                     let mut result = T::top();
491 
492                     for _ in 0..*count {
493                         let r = result_stack.pop().unwrap();
494                         result = result.and(r);
495                     }
496 
497                     result_stack.push(result);
498                 }
499                 ExprNode::Fn(Func::Any(count)) => {
500                     // any() with a comma separated list of configuration predicates.
501                     let mut result = T::bottom();
502 
503                     for _ in 0..*count {
504                         let r = result_stack.pop().unwrap();
505                         result = result.or(r);
506                     }
507 
508                     result_stack.push(result);
509                 }
510                 ExprNode::Fn(Func::Not) => {
511                     // not() with a configuration predicate.
512                     // It is true if its predicate is false
513                     // and false if its predicate is true.
514                     let r = result_stack.pop().unwrap();
515                     result_stack.push(r.not());
516                 }
517             }
518         }
519 
520         result_stack.pop().unwrap()
521     }
522 
523     /// The original string which has been parsed to produce this ['Expression`].
524     ///
525     /// ```
526     /// use cfg_expr::Expression;
527     ///
528     /// assert_eq!(
529     ///     Expression::parse("any()").unwrap().original(),
530     ///     "any()"
531     /// );
532     /// ```
533     #[inline]
original(&self) -> &str534     pub fn original(&self) -> &str {
535         &self.original
536     }
537 }
538 
539 /// [`PartialEq`] will do a **syntactical** comparaison, so will just check if both
540 /// expressions have been parsed from the same string, **not** if they are semantically
541 /// equivalent.
542 ///
543 /// ```
544 /// use cfg_expr::Expression;
545 ///
546 /// assert_eq!(
547 ///     Expression::parse("any()").unwrap(),
548 ///     Expression::parse("any()").unwrap()
549 /// );
550 /// assert_ne!(
551 ///     Expression::parse("any()").unwrap(),
552 ///     Expression::parse("unix").unwrap()
553 /// );
554 /// ```
555 impl PartialEq for Expression {
eq(&self, other: &Self) -> bool556     fn eq(&self, other: &Self) -> bool {
557         self.original.eq(&other.original)
558     }
559 }
560 
561 /// A propositional logic used to evaluate `Expression` instances.
562 ///
563 /// An `Expression` consists of some predicates and the `any`, `all` and `not` operators. An
564 /// implementation of `Logic` defines how the `any`, `all` and `not` operators should be evaluated.
565 pub trait Logic {
566     /// The result of an `all` operation with no operands, akin to Boolean `true`.
top() -> Self567     fn top() -> Self;
568 
569     /// The result of an `any` operation with no operands, akin to Boolean `false`.
bottom() -> Self570     fn bottom() -> Self;
571 
572     /// `AND`, which corresponds to the `all` operator.
and(self, other: Self) -> Self573     fn and(self, other: Self) -> Self;
574 
575     /// `OR`, which corresponds to the `any` operator.
or(self, other: Self) -> Self576     fn or(self, other: Self) -> Self;
577 
578     /// `NOT`, which corresponds to the `not` operator.
not(self) -> Self579     fn not(self) -> Self;
580 }
581 
582 /// A boolean logic.
583 impl Logic for bool {
584     #[inline]
top() -> Self585     fn top() -> Self {
586         true
587     }
588 
589     #[inline]
bottom() -> Self590     fn bottom() -> Self {
591         false
592     }
593 
594     #[inline]
and(self, other: Self) -> Self595     fn and(self, other: Self) -> Self {
596         self && other
597     }
598 
599     #[inline]
or(self, other: Self) -> Self600     fn or(self, other: Self) -> Self {
601         self || other
602     }
603 
604     #[inline]
not(self) -> Self605     fn not(self) -> Self {
606         !self
607     }
608 }
609 
610 /// A three-valued logic -- `None` stands for the value being unknown.
611 ///
612 /// The truth tables for this logic are described on
613 /// [Wikipedia](https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics).
614 impl Logic for Option<bool> {
615     #[inline]
top() -> Self616     fn top() -> Self {
617         Some(true)
618     }
619 
620     #[inline]
bottom() -> Self621     fn bottom() -> Self {
622         Some(false)
623     }
624 
625     #[inline]
and(self, other: Self) -> Self626     fn and(self, other: Self) -> Self {
627         match (self, other) {
628             // If either is false, the expression is false.
629             (Some(false), _) | (_, Some(false)) => Some(false),
630             // If both are true, the expression is true.
631             (Some(true), Some(true)) => Some(true),
632             // One or both are unknown -- the result is unknown.
633             _ => None,
634         }
635     }
636 
637     #[inline]
or(self, other: Self) -> Self638     fn or(self, other: Self) -> Self {
639         match (self, other) {
640             // If either is true, the expression is true.
641             (Some(true), _) | (_, Some(true)) => Some(true),
642             // If both are false, the expression is false.
643             (Some(false), Some(false)) => Some(false),
644             // One or both are unknown -- the result is unknown.
645             _ => None,
646         }
647     }
648 
649     #[inline]
not(self) -> Self650     fn not(self) -> Self {
651         self.map(|v| !v)
652     }
653 }
654