blob: 5af9b17dd7777443c2ccd167a71b8241d4721f1a [file] [log] [blame]
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
}
}