rustc_middle/ty/
pattern.rs1use 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 ty::PatternKind::NotNull => rustc_type_ir::TypeFlags::empty(),
34 }
35 }
36
37 fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
38 match &**self {
39 ty::PatternKind::Range { start, end } => {
40 start.outer_exclusive_binder().max(end.outer_exclusive_binder())
41 }
42 ty::PatternKind::Or(pats) => {
43 let mut idx = pats[0].outer_exclusive_binder();
44 for pat in pats[1..].iter() {
45 idx = idx.max(pat.outer_exclusive_binder());
46 }
47 idx
48 }
49 ty::PatternKind::NotNull => rustc_type_ir::INNERMOST,
50 }
51 }
52}
53
54impl<'tcx> std::ops::Deref for Pattern<'tcx> {
55 type Target = PatternKind<'tcx>;
56
57 fn deref(&self) -> &Self::Target {
58 &*self.0
59 }
60}
61
62impl<'tcx> fmt::Debug for Pattern<'tcx> {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "{:?}", **self)
65 }
66}
67
68impl<'tcx> IrPrint<PatternKind<'tcx>> for TyCtxt<'tcx> {
69 fn print(t: &PatternKind<'tcx>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 match *t {
71 PatternKind::Range { start, end } => {
72 write!(f, "{start}")?;
73
74 if let Some(c) = end.try_to_value() {
75 let end = c.valtree.unwrap_leaf();
76 let size = end.size();
77 let max = match c.ty.kind() {
78 ty::Int(_) => {
79 Some(ty::ScalarInt::truncate_from_int(size.signed_int_max(), size))
80 }
81 ty::Uint(_) => {
82 Some(ty::ScalarInt::truncate_from_uint(size.unsigned_int_max(), size))
83 }
84 ty::Char => Some(ty::ScalarInt::truncate_from_uint(char::MAX, size)),
85 _ => None,
86 };
87 if let Some((max, _)) = max
88 && end == max
89 {
90 return write!(f, "..");
91 }
92 }
93
94 write!(f, "..={end}")
95 }
96 PatternKind::NotNull => write!(f, "!null"),
97 PatternKind::Or(patterns) => {
98 write!(f, "(")?;
99 let mut first = true;
100 for pat in patterns {
101 if first {
102 first = false
103 } else {
104 write!(f, " | ")?;
105 }
106 write!(f, "{pat:?}")?;
107 }
108 write!(f, ")")
109 }
110 }
111 }
112
113 fn print_debug(t: &PatternKind<'tcx>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
114 Self::print(t, fmt)
115 }
116}
117
118impl<'tcx> rustc_type_ir::inherent::IntoKind for Pattern<'tcx> {
119 type Kind = PatternKind<'tcx>;
120 fn kind(self) -> Self::Kind {
121 *self
122 }
123}