1use rucc_base::Symbol;
16use rucc_diag::Span;
17
18use crate::ast::{AttrList, EnumeratorList, MemberList};
19use crate::decl::TypeNameId;
20use crate::expr::ExprId;
21
22pub type DeclSpecsId = rucc_base::Idx<DeclSpecs>;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct DeclSpecs {
28 pub storage: Option<StorageClass>,
30 pub thread_local: bool,
33 pub ty: TypeSpec,
35 pub quals: Quals,
37 pub func: FuncSpecs,
39 pub align: Option<AlignSpec>,
42 pub attrs: AttrList,
44 pub span: Span,
46}
47
48impl DeclSpecs {
49 #[must_use]
51 pub const fn empty(span: Span) -> DeclSpecs {
52 DeclSpecs {
53 storage: None,
54 thread_local: false,
55 ty: TypeSpec::None,
56 quals: Quals::NONE,
57 func: FuncSpecs::NONE,
58 align: None,
59 attrs: AttrList::EMPTY,
60 span,
61 }
62 }
63
64 #[must_use]
66 pub const fn is_typedef(&self) -> bool {
67 matches!(self.storage, Some(StorageClass::Typedef))
68 }
69
70 #[must_use]
72 pub const fn deduces(&self) -> Option<Deduction> {
73 match self.ty {
74 TypeSpec::Auto(which) => Some(which),
75 _ => None,
76 }
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum StorageClass {
83 Typedef,
85 Extern,
87 Static,
89 Auto,
91 Register,
93 Constexpr,
95}
96
97impl StorageClass {
98 #[must_use]
100 pub const fn spelling(self) -> &'static str {
101 match self {
102 StorageClass::Typedef => "typedef",
103 StorageClass::Extern => "extern",
104 StorageClass::Static => "static",
105 StorageClass::Auto => "auto",
106 StorageClass::Register => "register",
107 StorageClass::Constexpr => "constexpr",
108 }
109 }
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
119pub struct Quals(u8);
120
121impl Quals {
122 pub const NONE: Quals = Quals(0);
124 pub const CONST: Quals = Quals(1);
126 pub const VOLATILE: Quals = Quals(2);
128 pub const RESTRICT: Quals = Quals(4);
130 pub const ATOMIC: Quals = Quals(8);
132
133 #[inline]
135 #[must_use]
136 pub const fn has(self, other: Quals) -> bool {
137 self.0 & other.0 == other.0
138 }
139
140 #[inline]
142 #[must_use]
143 pub const fn with(self, other: Quals) -> Quals {
144 Quals(self.0 | other.0)
145 }
146
147 #[inline]
149 #[must_use]
150 pub const fn is_none(self) -> bool {
151 self.0 == 0
152 }
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
157pub struct FuncSpecs(u8);
158
159impl FuncSpecs {
160 pub const NONE: FuncSpecs = FuncSpecs(0);
162 pub const INLINE: FuncSpecs = FuncSpecs(1);
164 pub const NORETURN: FuncSpecs = FuncSpecs(2);
167
168 #[inline]
170 #[must_use]
171 pub const fn has(self, other: FuncSpecs) -> bool {
172 self.0 & other.0 == other.0
173 }
174
175 #[inline]
177 #[must_use]
178 pub const fn with(self, other: FuncSpecs) -> FuncSpecs {
179 FuncSpecs(self.0 | other.0)
180 }
181
182 #[inline]
184 #[must_use]
185 pub const fn is_none(self) -> bool {
186 self.0 == 0
187 }
188}
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192pub enum AlignSpec {
193 Type(TypeNameId),
195 Expr(ExprId),
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq)]
201pub enum TypeSpec {
202 None,
204 Builtin(Builtin),
206 Record {
208 kind: RecordKind,
210 tag: Option<Symbol>,
212 fields: Option<MemberList>,
216 attrs: AttrList,
218 },
219 Enum {
221 tag: Option<Symbol>,
223 enumerators: Option<EnumeratorList>,
225 underlying: Option<TypeNameId>,
228 attrs: AttrList,
230 },
231 Typedef(Symbol),
233 Typeof {
235 unqual: bool,
237 operand: TypeofArg,
240 },
241 Atomic(TypeNameId),
243 Auto(Deduction),
245}
246
247#[derive(Debug, Clone, Copy, PartialEq, Eq)]
253pub enum Deduction {
254 Auto,
256 AutoType,
258}
259
260impl Deduction {
261 #[must_use]
263 pub const fn spelling(self) -> &'static str {
264 match self {
265 Deduction::Auto => "auto",
266 Deduction::AutoType => "__auto_type",
267 }
268 }
269}
270
271#[derive(Debug, Clone, Copy, PartialEq, Eq)]
273pub enum RecordKind {
274 Struct,
276 Union,
278}
279
280impl RecordKind {
281 #[must_use]
283 pub const fn spelling(self) -> &'static str {
284 match self {
285 RecordKind::Struct => "struct",
286 RecordKind::Union => "union",
287 }
288 }
289}
290
291#[derive(Debug, Clone, Copy, PartialEq, Eq)]
293pub enum TypeofArg {
294 Expr(ExprId),
296 Type(TypeNameId),
298}
299
300#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
307pub struct Builtin {
308 pub set: BuiltinSet,
310 pub longs: u8,
312 pub width: Option<ExprId>,
314}
315
316#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
318pub struct BuiltinSet(u32);
319
320impl BuiltinSet {
321 pub const NONE: BuiltinSet = BuiltinSet(0);
323 pub const VOID: BuiltinSet = BuiltinSet(1 << 0);
325 pub const BOOL: BuiltinSet = BuiltinSet(1 << 1);
327 pub const CHAR: BuiltinSet = BuiltinSet(1 << 2);
329 pub const SHORT: BuiltinSet = BuiltinSet(1 << 3);
331 pub const INT: BuiltinSet = BuiltinSet(1 << 4);
333 pub const LONG: BuiltinSet = BuiltinSet(1 << 5);
335 pub const SIGNED: BuiltinSet = BuiltinSet(1 << 6);
337 pub const UNSIGNED: BuiltinSet = BuiltinSet(1 << 7);
339 pub const FLOAT: BuiltinSet = BuiltinSet(1 << 8);
341 pub const DOUBLE: BuiltinSet = BuiltinSet(1 << 9);
343 pub const COMPLEX: BuiltinSet = BuiltinSet(1 << 10);
345 pub const IMAGINARY: BuiltinSet = BuiltinSet(1 << 11);
347 pub const INT128: BuiltinSet = BuiltinSet(1 << 12);
349 pub const FLOAT16: BuiltinSet = BuiltinSet(1 << 13);
351 pub const FLOAT32: BuiltinSet = BuiltinSet(1 << 14);
353 pub const FLOAT64: BuiltinSet = BuiltinSet(1 << 15);
355 pub const FLOAT128: BuiltinSet = BuiltinSet(1 << 16);
357 pub const FLOAT32X: BuiltinSet = BuiltinSet(1 << 17);
359 pub const FLOAT64X: BuiltinSet = BuiltinSet(1 << 18);
361 pub const FLOAT128X: BuiltinSet = BuiltinSet(1 << 19);
363 pub const FLOAT80: BuiltinSet = BuiltinSet(1 << 20);
365 pub const DECIMAL32: BuiltinSet = BuiltinSet(1 << 21);
367 pub const DECIMAL64: BuiltinSet = BuiltinSet(1 << 22);
369 pub const DECIMAL128: BuiltinSet = BuiltinSet(1 << 23);
371 pub const BIT_INT: BuiltinSet = BuiltinSet(1 << 24);
373
374 const DECIMALS: BuiltinSet =
376 BuiltinSet(Self::DECIMAL32.0 | Self::DECIMAL64.0 | Self::DECIMAL128.0);
377 const EXTENDED: BuiltinSet = BuiltinSet(
379 Self::FLOAT16.0
380 | Self::FLOAT32.0
381 | Self::FLOAT64.0
382 | Self::FLOAT128.0
383 | Self::FLOAT32X.0
384 | Self::FLOAT64X.0
385 | Self::FLOAT128X.0
386 | Self::FLOAT80.0,
387 );
388 const INTEGER: BuiltinSet =
390 BuiltinSet(Self::SHORT.0 | Self::INT.0 | Self::LONG.0 | Self::SIGNED.0 | Self::UNSIGNED.0);
391
392 #[inline]
394 #[must_use]
395 pub const fn has(self, other: BuiltinSet) -> bool {
396 self.0 & other.0 == other.0
397 }
398
399 #[inline]
401 #[must_use]
402 pub const fn has_any(self, other: BuiltinSet) -> bool {
403 self.0 & other.0 != 0
404 }
405
406 #[inline]
408 #[must_use]
409 pub const fn with(self, other: BuiltinSet) -> BuiltinSet {
410 BuiltinSet(self.0 | other.0)
411 }
412
413 #[inline]
415 #[must_use]
416 pub const fn without(self, other: BuiltinSet) -> BuiltinSet {
417 BuiltinSet(self.0 & !other.0)
418 }
419
420 #[inline]
422 #[must_use]
423 pub const fn is_none(self) -> bool {
424 self.0 == 0
425 }
426}
427
428#[derive(Debug, Clone, Copy, PartialEq, Eq)]
430pub enum BuiltinError {
431 Duplicate,
433 TooManyLongs,
435}
436
437impl Builtin {
438 pub const NONE: Builtin = Builtin { set: BuiltinSet::NONE, longs: 0, width: None };
440
441 pub const fn add(self, which: BuiltinSet) -> Result<Builtin, BuiltinError> {
452 if which.0 == BuiltinSet::LONG.0 {
453 if self.longs >= 2 {
454 return Err(BuiltinError::TooManyLongs);
455 }
456 let set = self.set.with(which);
457 return Ok(Builtin { set, longs: self.longs + 1, width: self.width });
458 }
459 if self.set.has(which) {
460 return Err(BuiltinError::Duplicate);
461 }
462 Ok(Builtin { set: self.set.with(which), longs: self.longs, width: self.width })
463 }
464
465 pub const fn add_bit_int(self, width: ExprId) -> Result<Builtin, BuiltinError> {
476 if self.set.has(BuiltinSet::BIT_INT) {
477 return Err(BuiltinError::Duplicate);
478 }
479 let set = self.set.with(BuiltinSet::BIT_INT);
480 Ok(Builtin { set, longs: self.longs, width: Some(width) })
481 }
482
483 #[must_use]
485 pub const fn is_none(self) -> bool {
486 self.set.is_none()
487 }
488
489 #[must_use]
495 pub fn resolve(self) -> Option<Basic> {
496 let set = self.set;
497 let longs = self.longs;
498
499 let complexity = match (set.has(BuiltinSet::COMPLEX), set.has(BuiltinSet::IMAGINARY)) {
500 (true, true) => return None,
501 (true, false) => Complexity::Complex,
502 (false, true) => Complexity::Imaginary,
503 (false, false) => Complexity::Real,
504 };
505 let set = set.without(BuiltinSet::COMPLEX.with(BuiltinSet::IMAGINARY));
506 let basic = |scalar| Some(Basic { scalar, complexity });
507 let real = |scalar| {
508 if complexity == Complexity::Real { Some(Basic { scalar, complexity }) } else { None }
509 };
510
511 if set.has(BuiltinSet::SIGNED) && set.has(BuiltinSet::UNSIGNED) {
512 return None;
513 }
514 let unsigned = set.has(BuiltinSet::UNSIGNED);
515 let signs = BuiltinSet::SIGNED.with(BuiltinSet::UNSIGNED);
516
517 if set.has(BuiltinSet::VOID) {
520 return if set == BuiltinSet::VOID && longs == 0 { real(Scalar::Void) } else { None };
521 }
522 if set.has(BuiltinSet::BOOL) {
523 return if set == BuiltinSet::BOOL && longs == 0 { real(Scalar::Bool) } else { None };
524 }
525 if set.has(BuiltinSet::CHAR) {
526 if set.without(signs) != BuiltinSet::CHAR || longs != 0 {
527 return None;
528 }
529 return real(match (set.has(BuiltinSet::SIGNED), unsigned) {
530 (true, _) => Scalar::SignedChar,
531 (_, true) => Scalar::UnsignedChar,
532 _ => Scalar::Char,
533 });
534 }
535 if set.has(BuiltinSet::INT128) {
536 if set.without(signs) != BuiltinSet::INT128 || longs != 0 {
537 return None;
538 }
539 return real(if unsigned { Scalar::UnsignedInt128 } else { Scalar::Int128 });
540 }
541 if set.has(BuiltinSet::BIT_INT) {
542 if set.without(signs) != BuiltinSet::BIT_INT || longs != 0 {
543 return None;
544 }
545 let width = self.width?;
548 return real(Scalar::BitInt { width, unsigned });
549 }
550 if set.has_any(BuiltinSet::DECIMALS) {
551 if longs != 0 || complexity != Complexity::Real {
552 return None;
553 }
554 return match set {
555 s if s == BuiltinSet::DECIMAL32 => real(Scalar::Decimal32),
556 s if s == BuiltinSet::DECIMAL64 => real(Scalar::Decimal64),
557 s if s == BuiltinSet::DECIMAL128 => real(Scalar::Decimal128),
558 _ => None,
559 };
560 }
561 if set.has_any(BuiltinSet::EXTENDED) {
562 if longs != 0 {
563 return None;
564 }
565 return match set {
566 s if s == BuiltinSet::FLOAT16 => basic(Scalar::Float16),
567 s if s == BuiltinSet::FLOAT32 => basic(Scalar::Float32),
568 s if s == BuiltinSet::FLOAT64 => basic(Scalar::Float64),
569 s if s == BuiltinSet::FLOAT128 => basic(Scalar::Float128),
570 s if s == BuiltinSet::FLOAT32X => basic(Scalar::Float32x),
571 s if s == BuiltinSet::FLOAT64X => basic(Scalar::Float64x),
572 s if s == BuiltinSet::FLOAT128X => basic(Scalar::Float128x),
573 s if s == BuiltinSet::FLOAT80 => basic(Scalar::Float80),
574 _ => None,
575 };
576 }
577 if set.has(BuiltinSet::FLOAT) {
578 return if set == BuiltinSet::FLOAT && longs == 0 {
579 basic(Scalar::Float)
580 } else {
581 None
582 };
583 }
584 if set.has(BuiltinSet::DOUBLE) {
585 if set.without(BuiltinSet::LONG) != BuiltinSet::DOUBLE {
586 return None;
587 }
588 return match longs {
589 0 => basic(Scalar::Double),
590 1 => basic(Scalar::LongDouble),
591 _ => None,
592 };
593 }
594 if set.is_none() {
595 return None;
596 }
597 if !BuiltinSet::INTEGER.has(set) {
600 return None;
601 }
602 if set.has(BuiltinSet::SHORT) {
603 if longs != 0 {
604 return None;
605 }
606 return basic(if unsigned { Scalar::UnsignedShort } else { Scalar::Short });
607 }
608 match longs {
609 0 => basic(if unsigned { Scalar::UnsignedInt } else { Scalar::Int }),
610 1 => basic(if unsigned { Scalar::UnsignedLong } else { Scalar::Long }),
611 2 => basic(if unsigned { Scalar::UnsignedLongLong } else { Scalar::LongLong }),
612 _ => None,
613 }
614 }
615}
616
617#[derive(Debug, Clone, Copy, PartialEq, Eq)]
619pub struct Basic {
620 pub scalar: Scalar,
622 pub complexity: Complexity,
624}
625
626#[derive(Debug, Clone, Copy, PartialEq, Eq)]
628pub enum Complexity {
629 Real,
631 Complex,
633 Imaginary,
635}
636
637#[derive(Debug, Clone, Copy, PartialEq, Eq)]
642pub enum Scalar {
643 Void,
645 Bool,
647 Char,
649 SignedChar,
651 UnsignedChar,
653 Short,
655 UnsignedShort,
657 Int,
659 UnsignedInt,
661 Long,
663 UnsignedLong,
665 LongLong,
667 UnsignedLongLong,
669 Int128,
671 UnsignedInt128,
673 BitInt {
675 width: ExprId,
677 unsigned: bool,
680 },
681 Float,
683 Double,
685 LongDouble,
687 Float16,
689 Float32,
691 Float64,
693 Float128,
695 Float32x,
697 Float64x,
699 Float128x,
701 Float80,
703 Decimal32,
705 Decimal64,
707 Decimal128,
709}
710
711#[cfg(test)]
712mod tests {
713 use super::*;
714
715 fn resolve(keywords: &[BuiltinSet]) -> Option<Basic> {
716 let mut b = Builtin::NONE;
717 for &k in keywords {
718 b = b.add(k).expect("keyword rejected");
719 }
720 b.resolve()
721 }
722
723 fn real(keywords: &[BuiltinSet]) -> Option<Scalar> {
724 resolve(keywords).filter(|b| b.complexity == Complexity::Real).map(|b| b.scalar)
725 }
726
727 #[test]
728 fn the_plain_integer_spellings() {
729 assert_eq!(real(&[BuiltinSet::INT]), Some(Scalar::Int));
730 assert_eq!(real(&[BuiltinSet::SIGNED]), Some(Scalar::Int));
731 assert_eq!(real(&[BuiltinSet::UNSIGNED]), Some(Scalar::UnsignedInt));
732 assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::INT]), Some(Scalar::Int));
733 assert_eq!(real(&[BuiltinSet::SHORT]), Some(Scalar::Short));
734 assert_eq!(real(&[BuiltinSet::SHORT, BuiltinSet::INT]), Some(Scalar::Short));
735 assert_eq!(
736 real(&[BuiltinSet::UNSIGNED, BuiltinSet::SHORT, BuiltinSet::INT]),
737 Some(Scalar::UnsignedShort)
738 );
739 }
740
741 #[test]
742 fn long_counts_rather_than_repeats() {
743 assert_eq!(real(&[BuiltinSet::LONG]), Some(Scalar::Long));
744 assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::LONG]), Some(Scalar::LongLong));
745 assert_eq!(
746 real(&[BuiltinSet::UNSIGNED, BuiltinSet::LONG, BuiltinSet::LONG, BuiltinSet::INT]),
747 Some(Scalar::UnsignedLongLong)
748 );
749 let three = Builtin::NONE
750 .add(BuiltinSet::LONG)
751 .and_then(|b| b.add(BuiltinSet::LONG))
752 .and_then(|b| b.add(BuiltinSet::LONG));
753 assert_eq!(three, Err(BuiltinError::TooManyLongs));
754 }
755
756 #[test]
757 fn a_repeated_keyword_is_caught_where_it_is_written() {
758 let twice = Builtin::NONE.add(BuiltinSet::INT).and_then(|b| b.add(BuiltinSet::INT));
759 assert_eq!(twice, Err(BuiltinError::Duplicate));
760 }
761
762 #[test]
763 fn plain_char_is_its_own_type() {
764 assert_eq!(real(&[BuiltinSet::CHAR]), Some(Scalar::Char));
765 assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::CHAR]), Some(Scalar::SignedChar));
766 assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::CHAR]), Some(Scalar::UnsignedChar));
767 assert_eq!(real(&[BuiltinSet::CHAR, BuiltinSet::INT]), None);
768 assert_eq!(real(&[BuiltinSet::CHAR, BuiltinSet::LONG]), None);
769 }
770
771 #[test]
772 fn long_double_is_a_double_with_one_long() {
773 assert_eq!(real(&[BuiltinSet::DOUBLE]), Some(Scalar::Double));
774 assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::DOUBLE]), Some(Scalar::LongDouble));
775 assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::LONG, BuiltinSet::DOUBLE]), None);
776 assert_eq!(real(&[BuiltinSet::LONG, BuiltinSet::FLOAT]), None);
777 assert_eq!(real(&[BuiltinSet::DOUBLE, BuiltinSet::INT]), None);
778 }
779
780 #[test]
781 fn complex_is_a_modifier_and_not_a_type() {
782 assert_eq!(
783 resolve(&[BuiltinSet::COMPLEX, BuiltinSet::DOUBLE]),
784 Some(Basic { scalar: Scalar::Double, complexity: Complexity::Complex })
785 );
786 assert_eq!(
787 resolve(&[BuiltinSet::LONG, BuiltinSet::DOUBLE, BuiltinSet::IMAGINARY]),
788 Some(Basic { scalar: Scalar::LongDouble, complexity: Complexity::Imaginary })
789 );
790 assert_eq!(
792 resolve(&[BuiltinSet::COMPLEX, BuiltinSet::INT]),
793 Some(Basic { scalar: Scalar::Int, complexity: Complexity::Complex })
794 );
795 assert_eq!(resolve(&[BuiltinSet::COMPLEX, BuiltinSet::IMAGINARY, BuiltinSet::FLOAT]), None);
796 assert_eq!(resolve(&[BuiltinSet::COMPLEX, BuiltinSet::DECIMAL64]), None);
798 }
799
800 #[test]
801 fn the_extended_types_stand_alone_or_with_complex() {
802 assert_eq!(real(&[BuiltinSet::FLOAT128]), Some(Scalar::Float128));
803 assert_eq!(
804 resolve(&[BuiltinSet::COMPLEX, BuiltinSet::FLOAT128]),
805 Some(Basic { scalar: Scalar::Float128, complexity: Complexity::Complex })
806 );
807 assert_eq!(real(&[BuiltinSet::FLOAT32X]), Some(Scalar::Float32x));
808 assert_eq!(real(&[BuiltinSet::FLOAT128X]), Some(Scalar::Float128x));
809 assert_eq!(real(&[BuiltinSet::FLOAT16, BuiltinSet::INT]), None);
810 assert_eq!(real(&[BuiltinSet::FLOAT32, BuiltinSet::FLOAT64]), None);
811 }
812
813 #[test]
814 fn the_wide_integers_take_a_sign_and_nothing_else() {
815 assert_eq!(real(&[BuiltinSet::INT128]), Some(Scalar::Int128));
816 assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::INT128]), Some(Scalar::UnsignedInt128));
817 assert_eq!(real(&[BuiltinSet::INT128, BuiltinSet::INT]), None);
818 }
819
820 #[test]
821 fn void_and_bool_take_nothing() {
822 assert_eq!(real(&[BuiltinSet::VOID]), Some(Scalar::Void));
823 assert_eq!(real(&[BuiltinSet::BOOL]), Some(Scalar::Bool));
824 assert_eq!(real(&[BuiltinSet::VOID, BuiltinSet::INT]), None);
825 assert_eq!(real(&[BuiltinSet::UNSIGNED, BuiltinSet::BOOL]), None);
826 }
827
828 #[test]
829 fn two_signs_name_no_type() {
830 assert_eq!(real(&[BuiltinSet::SIGNED, BuiltinSet::UNSIGNED]), None);
831 }
832
833 #[test]
834 fn no_keywords_at_all_names_no_type() {
835 assert_eq!(Builtin::NONE.resolve(), None);
836 assert!(Builtin::NONE.is_none());
837 }
838
839 #[test]
840 fn short_and_long_do_not_go_together() {
841 assert_eq!(real(&[BuiltinSet::SHORT, BuiltinSet::LONG]), None);
842 }
843
844 #[test]
845 fn qualifier_sets_add_up() {
846 let q = Quals::NONE.with(Quals::CONST).with(Quals::VOLATILE);
847 assert!(q.has(Quals::CONST));
848 assert!(q.has(Quals::VOLATILE));
849 assert!(!q.has(Quals::RESTRICT));
850 assert!(Quals::NONE.is_none());
851 assert!(!q.is_none());
852 }
853
854 #[test]
855 fn function_specifier_sets_add_up() {
856 let f = FuncSpecs::NONE.with(FuncSpecs::INLINE);
857 assert!(f.has(FuncSpecs::INLINE));
858 assert!(!f.has(FuncSpecs::NORETURN));
859 assert!(FuncSpecs::NONE.is_none());
860 }
861}