mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 14:31:55 +00:00
Rollup merge of #128965 - Zalathar:no-pat, r=Nadrieril
Remove `print::Pat` from the printing of `WitnessPat` After the preliminary work done in #128536, we can now get rid of `print::Pat` entirely. - First, we introduce a variant `PatKind::Print(String)`. - Then we incrementally remove each other variant of `PatKind`, by having the relevant code produce `PatKind::Print` instead. - Once `PatKind::Print` is the only remaining variant, it becomes easy to remove `print::Pat` and replace it with `String`. There is more cleanup that I have in mind, but this seemed like a natural stopping point for one PR. r? ```@Nadrieril```
This commit is contained in:
commit
5858329f1a
@ -774,17 +774,16 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert to a [`print::Pat`] for diagnostic purposes.
|
||||
fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> print::Pat<'tcx> {
|
||||
use print::{Pat, PatKind};
|
||||
/// Prints an [`IntRange`] to a string for diagnostic purposes.
|
||||
fn print_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> String {
|
||||
use MaybeInfiniteInt::*;
|
||||
let cx = self;
|
||||
let kind = if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) {
|
||||
PatKind::Wild
|
||||
if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) {
|
||||
"_".to_string()
|
||||
} else if range.is_singleton() {
|
||||
let lo = cx.hoist_pat_range_bdy(range.lo, ty);
|
||||
let value = lo.as_finite().unwrap();
|
||||
PatKind::Constant { value }
|
||||
value.to_string()
|
||||
} else {
|
||||
// We convert to an inclusive range for diagnostics.
|
||||
let mut end = rustc_hir::RangeEnd::Included;
|
||||
@ -807,32 +806,24 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
||||
range.hi
|
||||
};
|
||||
let hi = cx.hoist_pat_range_bdy(hi, ty);
|
||||
PatKind::Range(Box::new(PatRange { lo, hi, end, ty: ty.inner() }))
|
||||
};
|
||||
|
||||
Pat { ty: ty.inner(), kind }
|
||||
PatRange { lo, hi, end, ty: ty.inner() }.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
// 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 hoist = |p| Box::new(cx.hoist_witness_pat(p));
|
||||
let kind = match pat.ctor() {
|
||||
Bool(b) => PatKind::Constant { value: mir::Const::from_bool(cx.tcx, *b) },
|
||||
IntRange(range) => return self.hoist_pat_range(range, *pat.ty()),
|
||||
let print = |p| cx.print_witness_pat(p);
|
||||
match pat.ctor() {
|
||||
Bool(b) => b.to_string(),
|
||||
Str(s) => s.to_string(),
|
||||
IntRange(range) => return self.print_pat_range(range, *pat.ty()),
|
||||
Struct if pat.ty().is_box() => {
|
||||
// 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)].
|
||||
PatKind::Box { subpattern: hoist(&pat.fields[0]) }
|
||||
format!("box {}", print(&pat.fields[0]))
|
||||
}
|
||||
Struct | Variant(_) | UnionField => {
|
||||
let enum_info = match *pat.ty().kind() {
|
||||
@ -847,12 +838,29 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
||||
let subpatterns = pat
|
||||
.iter_fields()
|
||||
.enumerate()
|
||||
.map(|(i, pat)| FieldPat { field: FieldIdx::new(i), pattern: hoist(pat) })
|
||||
.map(|(i, pat)| print::FieldPat {
|
||||
field: FieldIdx::new(i),
|
||||
pattern: print(pat),
|
||||
is_wildcard: would_print_as_wildcard(cx.tcx, pat),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
PatKind::StructLike { enum_info, subpatterns }
|
||||
let mut s = String::new();
|
||||
print::write_struct_like(
|
||||
&mut s,
|
||||
self.tcx,
|
||||
pat.ty().inner(),
|
||||
&enum_info,
|
||||
&subpatterns,
|
||||
)
|
||||
.unwrap();
|
||||
s
|
||||
}
|
||||
Ref => {
|
||||
let mut s = String::new();
|
||||
print::write_ref_like(&mut s, pat.ty().inner(), &print(&pat.fields[0])).unwrap();
|
||||
s
|
||||
}
|
||||
Ref => PatKind::Deref { subpattern: hoist(&pat.fields[0]) },
|
||||
Slice(slice) => {
|
||||
let (prefix_len, has_dot_dot) = match slice.kind {
|
||||
SliceKind::FixedLen(len) => (len, false),
|
||||
@ -879,14 +887,15 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let prefix = prefix.iter().map(hoist).collect();
|
||||
let suffix = suffix.iter().map(hoist).collect();
|
||||
let prefix = prefix.iter().map(print).collect::<Vec<_>>();
|
||||
let suffix = suffix.iter().map(print).collect::<Vec<_>>();
|
||||
|
||||
PatKind::Slice { prefix, has_dot_dot, suffix }
|
||||
let mut s = String::new();
|
||||
print::write_slice_like(&mut s, &prefix, has_dot_dot, &suffix).unwrap();
|
||||
s
|
||||
}
|
||||
&Str(value) => PatKind::Constant { value },
|
||||
Never if self.tcx.features().never_patterns => PatKind::Never,
|
||||
Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
|
||||
Never if self.tcx.features().never_patterns => "!".to_string(),
|
||||
Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => "_".to_string(),
|
||||
Missing { .. } => bug!(
|
||||
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
|
||||
`Missing` should have been processed in `apply_constructors`"
|
||||
@ -894,9 +903,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
||||
F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | Or => {
|
||||
bug!("can't convert to pattern: {:?}", pat)
|
||||
}
|
||||
};
|
||||
|
||||
Pat { ty: pat.ty().inner(), kind }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -972,7 +979,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
|
||||
overlaps_on: IntRange,
|
||||
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
|
||||
.iter()
|
||||
.map(|pat| pat.data().span)
|
||||
@ -1012,7 +1019,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
|
||||
suggested_range.end = rustc_hir::RangeEnd::Included;
|
||||
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, `gap == T::MAX`.
|
||||
self.tcx.emit_node_span_lint(
|
||||
|
@ -11,75 +11,16 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use rustc_middle::thir::PatRange;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, mir};
|
||||
use rustc_span::sym;
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct FieldPat<'tcx> {
|
||||
pub(crate) struct FieldPat {
|
||||
pub(crate) field: FieldIdx,
|
||||
pub(crate) pattern: Box<Pat<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Pat<'tcx> {
|
||||
pub(crate) ty: Ty<'tcx>,
|
||||
pub(crate) kind: PatKind<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum PatKind<'tcx> {
|
||||
Wild,
|
||||
|
||||
StructLike {
|
||||
enum_info: EnumInfo<'tcx>,
|
||||
subpatterns: Vec<FieldPat<'tcx>>,
|
||||
},
|
||||
|
||||
Box {
|
||||
subpattern: Box<Pat<'tcx>>,
|
||||
},
|
||||
|
||||
Deref {
|
||||
subpattern: Box<Pat<'tcx>>,
|
||||
},
|
||||
|
||||
Constant {
|
||||
value: mir::Const<'tcx>,
|
||||
},
|
||||
|
||||
Range(Box<PatRange<'tcx>>),
|
||||
|
||||
Slice {
|
||||
prefix: Box<[Box<Pat<'tcx>>]>,
|
||||
/// True if this slice-like pattern should include a `..` between the
|
||||
/// prefix and suffix.
|
||||
has_dot_dot: bool,
|
||||
suffix: Box<[Box<Pat<'tcx>>]>,
|
||||
},
|
||||
|
||||
Never,
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for Pat<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.kind {
|
||||
PatKind::Wild => write!(f, "_"),
|
||||
PatKind::Never => write!(f, "!"),
|
||||
PatKind::Box { ref subpattern } => write!(f, "box {subpattern}"),
|
||||
PatKind::StructLike { ref enum_info, ref subpatterns } => {
|
||||
ty::tls::with(|tcx| write_struct_like(f, tcx, self.ty, enum_info, subpatterns))
|
||||
}
|
||||
PatKind::Deref { ref subpattern } => write_ref_like(f, self.ty, subpattern),
|
||||
PatKind::Constant { value } => write!(f, "{value}"),
|
||||
PatKind::Range(ref range) => write!(f, "{range}"),
|
||||
PatKind::Slice { ref prefix, has_dot_dot, ref suffix } => {
|
||||
write_slice_like(f, prefix, has_dot_dot, suffix)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(crate) pattern: String,
|
||||
pub(crate) is_wildcard: bool,
|
||||
}
|
||||
|
||||
/// Returns a closure that will return `""` when called the first time,
|
||||
@ -103,12 +44,12 @@ pub(crate) enum EnumInfo<'tcx> {
|
||||
NotEnum,
|
||||
}
|
||||
|
||||
fn write_struct_like<'tcx>(
|
||||
pub(crate) fn write_struct_like<'tcx>(
|
||||
f: &mut impl fmt::Write,
|
||||
tcx: TyCtxt<'_>,
|
||||
ty: Ty<'tcx>,
|
||||
enum_info: &EnumInfo<'tcx>,
|
||||
subpatterns: &[FieldPat<'tcx>],
|
||||
subpatterns: &[FieldPat],
|
||||
) -> fmt::Result {
|
||||
let variant_and_name = match *enum_info {
|
||||
EnumInfo::Enum { adt_def, variant_index } => {
|
||||
@ -139,12 +80,12 @@ fn write_struct_like<'tcx>(
|
||||
write!(f, " {{ ")?;
|
||||
|
||||
let mut printed = 0;
|
||||
for p in subpatterns {
|
||||
if let PatKind::Wild = p.pattern.kind {
|
||||
for &FieldPat { field, ref pattern, is_wildcard } in subpatterns {
|
||||
if is_wildcard {
|
||||
continue;
|
||||
}
|
||||
let name = variant.fields[p.field].name;
|
||||
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
|
||||
let field_name = variant.fields[field].name;
|
||||
write!(f, "{}{field_name}: {pattern}", start_or_comma())?;
|
||||
printed += 1;
|
||||
}
|
||||
|
||||
@ -184,10 +125,10 @@ fn write_struct_like<'tcx>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_ref_like<'tcx>(
|
||||
pub(crate) fn write_ref_like<'tcx>(
|
||||
f: &mut impl fmt::Write,
|
||||
ty: Ty<'tcx>,
|
||||
subpattern: &Pat<'tcx>,
|
||||
subpattern: &str,
|
||||
) -> fmt::Result {
|
||||
match ty.kind() {
|
||||
ty::Ref(_, _, mutbl) => {
|
||||
@ -198,11 +139,11 @@ fn write_ref_like<'tcx>(
|
||||
write!(f, "{subpattern}")
|
||||
}
|
||||
|
||||
fn write_slice_like<'tcx>(
|
||||
pub(crate) fn write_slice_like(
|
||||
f: &mut impl fmt::Write,
|
||||
prefix: &[Box<Pat<'tcx>>],
|
||||
prefix: &[String],
|
||||
has_dot_dot: bool,
|
||||
suffix: &[Box<Pat<'tcx>>],
|
||||
suffix: &[String],
|
||||
) -> fmt::Result {
|
||||
let mut start_or_comma = start_or_comma();
|
||||
write!(f, "[")?;
|
||||
|
Loading…
Reference in New Issue
Block a user