Skip to content

Commit

Permalink
Revert "Make thir::Pat not implement fmt::Display directly"
Browse files Browse the repository at this point in the history
This reverts commit ae0ec73.

The original change in rust-lang#128304 was intended to be a step towards being able to
print `thir::Pat` even after switching to `PatId`.

But because the only patterns that need to be printed are the synthetic ones
created by pattern analysis (for diagnostic purposes only), it makes more sense
to completely separate the printable patterns from the real THIR patterns.
  • Loading branch information
Zalathar committed Jul 31, 2024
1 parent a2b3256 commit a9ea85e
Showing 1 changed file with 19 additions and 46 deletions.
65 changes: 19 additions & 46 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1073,33 +1073,8 @@ impl<'tcx> PatRangeBoundary<'tcx> {
}
}

impl<'tcx> Pat<'tcx> {
/// Prints a [`Pat`] to an owned string, for user-facing diagnostics.
///
/// If we ever switch over to storing subpatterns as `PatId`, this will also
/// need to take a context that can resolve IDs to subpatterns.
pub fn to_string(&self) -> String {
format!("{}", self.display())
}

/// Used internally by [`fmt::Display`] for [`PatDisplay`].
fn display(&self) -> PatDisplay<'_, 'tcx> {
PatDisplay { pat: self }
}
}

/// Wrapper around [`&Pat<'tcx>`][`Pat`] that implements [`fmt::Display`].
///
/// If we ever switch over to storing subpatterns as `PatId`, this will also
/// need to hold a context that can resolve IDs to subpatterns.
struct PatDisplay<'pat, 'tcx> {
pat: &'pat Pat<'tcx>,
}

impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> {
impl<'tcx> fmt::Display for Pat<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let &Self { pat } = self;

// Printing lists is a chore.
let mut first = true;
let mut start_or_continue = |s| {
Expand All @@ -1112,22 +1087,20 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> {
};
let mut start_or_comma = || start_or_continue(", ");

match pat.kind {
match self.kind {
PatKind::Wild => write!(f, "_"),
PatKind::Never => write!(f, "!"),
PatKind::AscribeUserType { ref subpattern, .. } => {
write!(f, "{}: _", subpattern.display())
}
PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"),
PatKind::Binding { name, mode, ref subpattern, .. } => {
f.write_str(mode.prefix_str())?;
write!(f, "{name}")?;
if let Some(ref subpattern) = *subpattern {
write!(f, " @ {}", subpattern.display())?;
write!(f, " @ {subpattern}")?;
}
Ok(())
}
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
let variant_and_name = match pat.kind {
let variant_and_name = match self.kind {
PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
let variant = adt_def.variant(variant_index);
let adt_did = adt_def.did();
Expand All @@ -1140,7 +1113,7 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> {
};
Some((variant, name))
}),
_ => pat.ty.ty_adt_def().and_then(|adt_def| {
_ => self.ty.ty_adt_def().and_then(|adt_def| {
if !adt_def.is_enum() {
ty::tls::with(|tcx| {
Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
Expand All @@ -1165,11 +1138,11 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> {
continue;
}
let name = variant.fields[p.field].name;
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern.display())?;
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
printed += 1;
}

let is_union = pat.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
if printed < variant.fields.len() && (!is_union || printed == 0) {
write!(f, "{}..", start_or_comma())?;
}
Expand All @@ -1188,14 +1161,14 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> {
// Common case: the field is where we expect it.
if let Some(p) = subpatterns.get(i) {
if p.field.index() == i {
write!(f, "{}", p.pattern.display())?;
write!(f, "{}", p.pattern)?;
continue;
}
}

// Otherwise, we have to go looking for it.
if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
write!(f, "{}", p.pattern.display())?;
write!(f, "{}", p.pattern)?;
} else {
write!(f, "_")?;
}
Expand All @@ -1206,45 +1179,45 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> {
Ok(())
}
PatKind::Deref { ref subpattern } => {
match pat.ty.kind() {
match self.ty.kind() {
ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
ty::Ref(_, _, mutbl) => {
write!(f, "&{}", mutbl.prefix_str())?;
}
_ => bug!("{} is a bad Deref pattern type", pat.ty),
_ => bug!("{} is a bad Deref pattern type", self.ty),
}
write!(f, "{}", subpattern.display())
write!(f, "{subpattern}")
}
PatKind::DerefPattern { ref subpattern, .. } => {
write!(f, "deref!({})", subpattern.display())
write!(f, "deref!({subpattern})")
}
PatKind::Constant { value } => write!(f, "{value}"),
PatKind::InlineConstant { def: _, ref subpattern } => {
write!(f, "{} (from inline const)", subpattern.display())
write!(f, "{} (from inline const)", subpattern)
}
PatKind::Range(ref range) => write!(f, "{range}"),
PatKind::Slice { ref prefix, ref slice, ref suffix }
| PatKind::Array { ref prefix, ref slice, ref suffix } => {
write!(f, "[")?;
for p in prefix.iter() {
write!(f, "{}{}", start_or_comma(), p.display())?;
write!(f, "{}{}", start_or_comma(), p)?;
}
if let Some(ref slice) = *slice {
write!(f, "{}", start_or_comma())?;
match slice.kind {
PatKind::Wild => {}
_ => write!(f, "{}", slice.display())?,
_ => write!(f, "{slice}")?,
}
write!(f, "..")?;
}
for p in suffix.iter() {
write!(f, "{}{}", start_or_comma(), p.display())?;
write!(f, "{}{}", start_or_comma(), p)?;
}
write!(f, "]")
}
PatKind::Or { ref pats } => {
for pat in pats.iter() {
write!(f, "{}{}", start_or_continue(" | "), pat.display())?;
write!(f, "{}{}", start_or_continue(" | "), pat)?;
}
Ok(())
}
Expand Down

0 comments on commit a9ea85e

Please sign in to comment.