| use std::fmt; |
| |
| use rustc_data_structures::intern::Interned; |
| use rustc_macros::HashStable; |
| use rustc_type_ir::ir_print::IrPrint; |
| use rustc_type_ir::{ |
| FlagComputation, Flags, {self as ir}, |
| }; |
| |
| use super::TyCtxt; |
| use crate::ty; |
| |
| pub type PatternKind<'tcx> = ir::PatternKind<TyCtxt<'tcx>>; |
| |
| #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] |
| #[rustc_pass_by_value] |
| pub struct Pattern<'tcx>(pub Interned<'tcx, PatternKind<'tcx>>); |
| |
| impl<'tcx> Flags for Pattern<'tcx> { |
| fn flags(&self) -> rustc_type_ir::TypeFlags { |
| match &**self { |
| ty::PatternKind::Range { start, end } => { |
| FlagComputation::for_const_kind(&start.kind()).flags |
| | FlagComputation::for_const_kind(&end.kind()).flags |
| } |
| ty::PatternKind::Or(pats) => { |
| let mut flags = pats[0].flags(); |
| for pat in pats[1..].iter() { |
| flags |= pat.flags(); |
| } |
| flags |
| } |
| } |
| } |
| |
| fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex { |
| match &**self { |
| ty::PatternKind::Range { start, end } => { |
| start.outer_exclusive_binder().max(end.outer_exclusive_binder()) |
| } |
| ty::PatternKind::Or(pats) => { |
| let mut idx = pats[0].outer_exclusive_binder(); |
| for pat in pats[1..].iter() { |
| idx = idx.max(pat.outer_exclusive_binder()); |
| } |
| idx |
| } |
| } |
| } |
| } |
| |
| impl<'tcx> std::ops::Deref for Pattern<'tcx> { |
| type Target = PatternKind<'tcx>; |
| |
| fn deref(&self) -> &Self::Target { |
| &*self.0 |
| } |
| } |
| |
| impl<'tcx> fmt::Debug for Pattern<'tcx> { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| write!(f, "{:?}", **self) |
| } |
| } |
| |
| impl<'tcx> IrPrint<PatternKind<'tcx>> for TyCtxt<'tcx> { |
| fn print(t: &PatternKind<'tcx>, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| match *t { |
| PatternKind::Range { start, end } => { |
| write!(f, "{start}")?; |
| |
| if let Some(c) = end.try_to_value() { |
| let end = c.valtree.unwrap_leaf(); |
| let size = end.size(); |
| let max = match c.ty.kind() { |
| ty::Int(_) => { |
| Some(ty::ScalarInt::truncate_from_int(size.signed_int_max(), size)) |
| } |
| ty::Uint(_) => { |
| Some(ty::ScalarInt::truncate_from_uint(size.unsigned_int_max(), size)) |
| } |
| ty::Char => Some(ty::ScalarInt::truncate_from_uint(char::MAX, size)), |
| _ => None, |
| }; |
| if let Some((max, _)) = max |
| && end == max |
| { |
| return write!(f, ".."); |
| } |
| } |
| |
| write!(f, "..={end}") |
| } |
| PatternKind::Or(patterns) => { |
| write!(f, "(")?; |
| let mut first = true; |
| for pat in patterns { |
| if first { |
| first = false |
| } else { |
| write!(f, " | ")?; |
| } |
| write!(f, "{pat:?}")?; |
| } |
| write!(f, ")") |
| } |
| } |
| } |
| |
| fn print_debug(t: &PatternKind<'tcx>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
| Self::print(t, fmt) |
| } |
| } |
| |
| impl<'tcx> rustc_type_ir::inherent::IntoKind for Pattern<'tcx> { |
| type Kind = PatternKind<'tcx>; |
| fn kind(self) -> Self::Kind { |
| *self |
| } |
| } |