about summary refs log tree commit diff
path: root/library/core/src/pat.rs
blob: f8826096df3e15f176028d050b4ab039b05adea9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Helper module for exporting the `pattern_type` macro

/// Creates a pattern type.
/// ```ignore (cannot test this from within core yet)
/// type Positive = std::pat::pattern_type!(i32 is 1..);
/// ```
#[macro_export]
#[rustc_builtin_macro(pattern_type)]
#[unstable(feature = "pattern_type_macro", issue = "123646")]
macro_rules! pattern_type {
    ($($arg:tt)*) => {
        /* compiler built-in */
    };
}

/// A trait implemented for integer types and `char`.
/// Useful in the future for generic pattern types, but
/// used right now to simplify ast lowering of pattern type ranges.
#[unstable(feature = "pattern_type_range_trait", issue = "123646")]
#[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")]
#[const_trait]
#[diagnostic::on_unimplemented(
    message = "`{Self}` is not a valid base type for range patterns",
    label = "only integer types and `char` are supported"
)]
pub trait RangePattern {
    /// Trait version of the inherent `MIN` assoc const.
    #[cfg_attr(not(bootstrap), lang = "RangeMin")]
    const MIN: Self;

    /// Trait version of the inherent `MIN` assoc const.
    #[cfg_attr(not(bootstrap), lang = "RangeMax")]
    const MAX: Self;

    /// A compile-time helper to subtract 1 for exclusive ranges.
    #[cfg_attr(not(bootstrap), lang = "RangeSub")]
    #[track_caller]
    fn sub_one(self) -> Self;
}

macro_rules! impl_range_pat {
    ($($ty:ty,)*) => {
        $(
            #[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")]
            impl const RangePattern for $ty {
                const MIN: $ty = <$ty>::MIN;
                const MAX: $ty = <$ty>::MAX;
                fn sub_one(self) -> Self {
                    match self.checked_sub(1) {
                        Some(val) => val,
                        None => panic!("exclusive range end at minimum value of type")
                    }
                }
            }
        )*
    }
}

impl_range_pat! {
    i8, i16, i32, i64, i128, isize,
    u8, u16, u32, u64, u128, usize,
}

#[rustc_const_unstable(feature = "pattern_type_range_trait", issue = "123646")]
impl const RangePattern for char {
    const MIN: Self = char::MIN;

    const MAX: Self = char::MAX;

    fn sub_one(self) -> Self {
        match char::from_u32(self as u32 - 1) {
            None => panic!("exclusive range to start of valid chars"),
            Some(val) => val,
        }
    }
}