120 lines
3.7 KiB
Rust
120 lines
3.7 KiB
Rust
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
|
|
}
|
|
}
|