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>; #[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> 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 } }