Remove print::Pat entirely, replacing it with String

This commit is contained in:
Zalathar 2024-08-03 21:20:22 +10:00
parent bfe88a3bd0
commit fc55129774
2 changed files with 35 additions and 69 deletions

View File

@ -774,17 +774,16 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
} }
} }
/// Convert to a [`print::Pat`] for diagnostic purposes. /// Prints an [`IntRange`] to a string for diagnostic purposes.
fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> print::Pat<'tcx> { fn print_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> String {
use print::{Pat, PatKind};
use MaybeInfiniteInt::*; use MaybeInfiniteInt::*;
let cx = self; let cx = self;
let kind = if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) { if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) {
PatKind::Print("_".to_string()) "_".to_string()
} else if range.is_singleton() { } else if range.is_singleton() {
let lo = cx.hoist_pat_range_bdy(range.lo, ty); let lo = cx.hoist_pat_range_bdy(range.lo, ty);
let value = lo.as_finite().unwrap(); let value = lo.as_finite().unwrap();
PatKind::Print(value.to_string()) value.to_string()
} else { } else {
// We convert to an inclusive range for diagnostics. // We convert to an inclusive range for diagnostics.
let mut end = rustc_hir::RangeEnd::Included; let mut end = rustc_hir::RangeEnd::Included;
@ -807,33 +806,24 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
range.hi range.hi
}; };
let hi = cx.hoist_pat_range_bdy(hi, ty); let hi = cx.hoist_pat_range_bdy(hi, ty);
PatKind::Print(PatRange { lo, hi, end, ty: ty.inner() }.to_string()) PatRange { lo, hi, end, ty: ty.inner() }.to_string()
}; }
Pat { ty: ty.inner(), kind }
} }
/// Prints a [`WitnessPat`] to an owned string, for diagnostic purposes. /// Prints a [`WitnessPat`] to an owned string, for diagnostic purposes.
///
/// This panics for patterns that don't appear in diagnostics, like float ranges.
pub fn print_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> String { pub fn print_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> String {
// This works by converting the witness pattern to a `print::Pat`
// and then printing that, but callers don't need to know that.
self.hoist_witness_pat(pat).to_string()
}
/// Convert to a [`print::Pat`] for diagnostic purposes. This panics for patterns that don't
/// appear in diagnostics, like float ranges.
fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> print::Pat<'tcx> {
use print::{FieldPat, Pat, PatKind};
let cx = self; let cx = self;
let hoist = |p| Box::new(cx.hoist_witness_pat(p)); let print = |p| cx.print_witness_pat(p);
let kind = match pat.ctor() { match pat.ctor() {
Bool(b) => PatKind::Print(b.to_string()), Bool(b) => b.to_string(),
Str(s) => PatKind::Print(s.to_string()), Str(s) => s.to_string(),
IntRange(range) => return self.hoist_pat_range(range, *pat.ty()), IntRange(range) => return self.print_pat_range(range, *pat.ty()),
Struct if pat.ty().is_box() => { Struct if pat.ty().is_box() => {
// Outside of the `alloc` crate, the only way to create a struct pattern // Outside of the `alloc` crate, the only way to create a struct pattern
// of type `Box` is to use a `box` pattern via #[feature(box_patterns)]. // of type `Box` is to use a `box` pattern via #[feature(box_patterns)].
PatKind::Print(format!("box {}", hoist(&pat.fields[0]))) format!("box {}", print(&pat.fields[0]))
} }
Struct | Variant(_) | UnionField => { Struct | Variant(_) | UnionField => {
let enum_info = match *pat.ty().kind() { let enum_info = match *pat.ty().kind() {
@ -848,9 +838,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
let subpatterns = pat let subpatterns = pat
.iter_fields() .iter_fields()
.enumerate() .enumerate()
.map(|(i, pat)| FieldPat { .map(|(i, pat)| print::FieldPat {
field: FieldIdx::new(i), field: FieldIdx::new(i),
pattern: hoist(pat), pattern: print(pat),
is_wildcard: would_print_as_wildcard(cx.tcx, pat), is_wildcard: would_print_as_wildcard(cx.tcx, pat),
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -864,12 +854,12 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
&subpatterns, &subpatterns,
) )
.unwrap(); .unwrap();
PatKind::Print(s) s
} }
Ref => { Ref => {
let mut s = String::new(); let mut s = String::new();
print::write_ref_like(&mut s, pat.ty().inner(), &hoist(&pat.fields[0])).unwrap(); print::write_ref_like(&mut s, pat.ty().inner(), &print(&pat.fields[0])).unwrap();
PatKind::Print(s) s
} }
Slice(slice) => { Slice(slice) => {
let (prefix_len, has_dot_dot) = match slice.kind { let (prefix_len, has_dot_dot) = match slice.kind {
@ -897,17 +887,15 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
} }
} }
let prefix = prefix.iter().map(hoist).collect::<Vec<_>>(); let prefix = prefix.iter().map(print).collect::<Vec<_>>();
let suffix = suffix.iter().map(hoist).collect::<Vec<_>>(); let suffix = suffix.iter().map(print).collect::<Vec<_>>();
let mut s = String::new(); let mut s = String::new();
print::write_slice_like(&mut s, &prefix, has_dot_dot, &suffix).unwrap(); print::write_slice_like(&mut s, &prefix, has_dot_dot, &suffix).unwrap();
PatKind::Print(s) s
}
Never if self.tcx.features().never_patterns => PatKind::Print("!".to_string()),
Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => {
PatKind::Print("_".to_string())
} }
Never if self.tcx.features().never_patterns => "!".to_string(),
Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => "_".to_string(),
Missing { .. } => bug!( Missing { .. } => bug!(
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug, "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
`Missing` should have been processed in `apply_constructors`" `Missing` should have been processed in `apply_constructors`"
@ -915,9 +903,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | Or => { F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | Or => {
bug!("can't convert to pattern: {:?}", pat) bug!("can't convert to pattern: {:?}", pat)
} }
}; }
Pat { ty: pat.ty().inner(), kind }
} }
} }
@ -993,7 +979,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
overlaps_on: IntRange, overlaps_on: IntRange,
overlaps_with: &[&crate::pat::DeconstructedPat<Self>], overlaps_with: &[&crate::pat::DeconstructedPat<Self>],
) { ) {
let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty()); let overlap_as_pat = self.print_pat_range(&overlaps_on, *pat.ty());
let overlaps: Vec<_> = overlaps_with let overlaps: Vec<_> = overlaps_with
.iter() .iter()
.map(|pat| pat.data().span) .map(|pat| pat.data().span)
@ -1033,7 +1019,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
suggested_range.end = rustc_hir::RangeEnd::Included; suggested_range.end = rustc_hir::RangeEnd::Included;
suggested_range.to_string() suggested_range.to_string()
}; };
let gap_as_pat = self.hoist_pat_range(&gap, *pat.ty()); let gap_as_pat = self.print_pat_range(&gap, *pat.ty());
if gapped_with.is_empty() { if gapped_with.is_empty() {
// If `gapped_with` is empty, `gap == T::MAX`. // If `gapped_with` is empty, `gap == T::MAX`.
self.tcx.emit_node_span_lint( self.tcx.emit_node_span_lint(

View File

@ -17,32 +17,12 @@ use rustc_span::sym;
use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_target::abi::{FieldIdx, VariantIdx};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct FieldPat<'tcx> { pub(crate) struct FieldPat {
pub(crate) field: FieldIdx, pub(crate) field: FieldIdx,
pub(crate) pattern: Box<Pat<'tcx>>, pub(crate) pattern: String,
pub(crate) is_wildcard: bool, pub(crate) is_wildcard: bool,
} }
#[derive(Clone, Debug)]
pub(crate) struct Pat<'tcx> {
#[allow(dead_code)]
pub(crate) ty: Ty<'tcx>,
pub(crate) kind: PatKind,
}
#[derive(Clone, Debug)]
pub(crate) enum PatKind {
Print(String),
}
impl<'tcx> fmt::Display for Pat<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
PatKind::Print(ref string) => write!(f, "{string}"),
}
}
}
/// Returns a closure that will return `""` when called the first time, /// Returns a closure that will return `""` when called the first time,
/// and then return `", "` when called any subsequent times. /// and then return `", "` when called any subsequent times.
/// Useful for printing comma-separated lists. /// Useful for printing comma-separated lists.
@ -69,7 +49,7 @@ pub(crate) fn write_struct_like<'tcx>(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
enum_info: &EnumInfo<'tcx>, enum_info: &EnumInfo<'tcx>,
subpatterns: &[FieldPat<'tcx>], subpatterns: &[FieldPat],
) -> fmt::Result { ) -> fmt::Result {
let variant_and_name = match *enum_info { let variant_and_name = match *enum_info {
EnumInfo::Enum { adt_def, variant_index } => { EnumInfo::Enum { adt_def, variant_index } => {
@ -148,7 +128,7 @@ pub(crate) fn write_struct_like<'tcx>(
pub(crate) fn write_ref_like<'tcx>( pub(crate) fn write_ref_like<'tcx>(
f: &mut impl fmt::Write, f: &mut impl fmt::Write,
ty: Ty<'tcx>, ty: Ty<'tcx>,
subpattern: &Pat<'tcx>, subpattern: &str,
) -> fmt::Result { ) -> fmt::Result {
match ty.kind() { match ty.kind() {
ty::Ref(_, _, mutbl) => { ty::Ref(_, _, mutbl) => {
@ -159,11 +139,11 @@ pub(crate) fn write_ref_like<'tcx>(
write!(f, "{subpattern}") write!(f, "{subpattern}")
} }
pub(crate) fn write_slice_like<'tcx>( pub(crate) fn write_slice_like(
f: &mut impl fmt::Write, f: &mut impl fmt::Write,
prefix: &[Box<Pat<'tcx>>], prefix: &[String],
has_dot_dot: bool, has_dot_dot: bool,
suffix: &[Box<Pat<'tcx>>], suffix: &[String],
) -> fmt::Result { ) -> fmt::Result {
let mut start_or_comma = start_or_comma(); let mut start_or_comma = start_or_comma();
write!(f, "[")?; write!(f, "[")?;