rustc_middle/ty/
pattern.rs

1use std::fmt;
2
3use rustc_data_structures::intern::Interned;
4use rustc_macros::HashStable;
5use rustc_type_ir::ir_print::IrPrint;
6use rustc_type_ir::{
7    FlagComputation, Flags, {self as ir},
8};
9
10use super::TyCtxt;
11use crate::ty;
12
13pub type PatternKind<'tcx> = ir::PatternKind<TyCtxt<'tcx>>;
14
15#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
16#[rustc_pass_by_value]
17pub struct Pattern<'tcx>(pub Interned<'tcx, PatternKind<'tcx>>);
18
19impl<'tcx> Flags for Pattern<'tcx> {
20    fn flags(&self) -> rustc_type_ir::TypeFlags {
21        match &**self {
22            ty::PatternKind::Range { start, end } => {
23                FlagComputation::for_const_kind(&start.kind()).flags
24                    | FlagComputation::for_const_kind(&end.kind()).flags
25            }
26            ty::PatternKind::Or(pats) => {
27                let mut flags = pats[0].flags();
28                for pat in pats[1..].iter() {
29                    flags |= pat.flags();
30                }
31                flags
32            }
33        }
34    }
35
36    fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
37        match &**self {
38            ty::PatternKind::Range { start, end } => {
39                start.outer_exclusive_binder().max(end.outer_exclusive_binder())
40            }
41            ty::PatternKind::Or(pats) => {
42                let mut idx = pats[0].outer_exclusive_binder();
43                for pat in pats[1..].iter() {
44                    idx = idx.max(pat.outer_exclusive_binder());
45                }
46                idx
47            }
48        }
49    }
50}
51
52impl<'tcx> std::ops::Deref for Pattern<'tcx> {
53    type Target = PatternKind<'tcx>;
54
55    fn deref(&self) -> &Self::Target {
56        &*self.0
57    }
58}
59
60impl<'tcx> fmt::Debug for Pattern<'tcx> {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        write!(f, "{:?}", **self)
63    }
64}
65
66impl<'tcx> IrPrint<PatternKind<'tcx>> for TyCtxt<'tcx> {
67    fn print(t: &PatternKind<'tcx>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        match *t {
69            PatternKind::Range { start, end } => {
70                write!(f, "{start}")?;
71
72                if let Some(c) = end.try_to_value() {
73                    let end = c.valtree.unwrap_leaf();
74                    let size = end.size();
75                    let max = match c.ty.kind() {
76                        ty::Int(_) => {
77                            Some(ty::ScalarInt::truncate_from_int(size.signed_int_max(), size))
78                        }
79                        ty::Uint(_) => {
80                            Some(ty::ScalarInt::truncate_from_uint(size.unsigned_int_max(), size))
81                        }
82                        ty::Char => Some(ty::ScalarInt::truncate_from_uint(char::MAX, size)),
83                        _ => None,
84                    };
85                    if let Some((max, _)) = max
86                        && end == max
87                    {
88                        return write!(f, "..");
89                    }
90                }
91
92                write!(f, "..={end}")
93            }
94            PatternKind::Or(patterns) => {
95                write!(f, "(")?;
96                let mut first = true;
97                for pat in patterns {
98                    if first {
99                        first = false
100                    } else {
101                        write!(f, " | ")?;
102                    }
103                    write!(f, "{pat:?}")?;
104                }
105                write!(f, ")")
106            }
107        }
108    }
109
110    fn print_debug(t: &PatternKind<'tcx>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
111        Self::print(t, fmt)
112    }
113}
114
115impl<'tcx> rustc_type_ir::inherent::IntoKind for Pattern<'tcx> {
116    type Kind = PatternKind<'tcx>;
117    fn kind(self) -> Self::Kind {
118        *self
119    }
120}