Skip to content

Commit ae0ec73

Browse files
committed
Make thir::Pat not implement fmt::Display directly
This gives a clearer view of the (diagnostic) code that expects to be able to print THIR patterns, and makes it possible to experiment with requiring some kind of context (for ID lookup) when printing patterns.
1 parent db05b0f commit ae0ec73

File tree

1 file changed

+46
-19
lines changed

1 file changed

+46
-19
lines changed

compiler/rustc_middle/src/thir.rs

+46-19
Original file line numberDiff line numberDiff line change
@@ -1073,8 +1073,33 @@ impl<'tcx> PatRangeBoundary<'tcx> {
10731073
}
10741074
}
10751075

1076-
impl<'tcx> fmt::Display for Pat<'tcx> {
1076+
impl<'tcx> Pat<'tcx> {
1077+
/// Prints a [`Pat`] to an owned string, for user-facing diagnostics.
1078+
///
1079+
/// If we ever switch over to storing subpatterns as `PatId`, this will also
1080+
/// need to take a context that can resolve IDs to subpatterns.
1081+
pub fn to_string(&self) -> String {
1082+
format!("{}", self.display())
1083+
}
1084+
1085+
/// Used internally by [`fmt::Display`] for [`PatDisplay`].
1086+
fn display(&self) -> PatDisplay<'_, 'tcx> {
1087+
PatDisplay { pat: self }
1088+
}
1089+
}
1090+
1091+
/// Wrapper around [`&Pat<'tcx>`][`Pat`] that implements [`fmt::Display`].
1092+
///
1093+
/// If we ever switch over to storing subpatterns as `PatId`, this will also
1094+
/// need to hold a context that can resolve IDs to subpatterns.
1095+
struct PatDisplay<'pat, 'tcx> {
1096+
pat: &'pat Pat<'tcx>,
1097+
}
1098+
1099+
impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> {
10771100
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1101+
let &Self { pat } = self;
1102+
10781103
// Printing lists is a chore.
10791104
let mut first = true;
10801105
let mut start_or_continue = |s| {
@@ -1087,20 +1112,22 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
10871112
};
10881113
let mut start_or_comma = || start_or_continue(", ");
10891114

1090-
match self.kind {
1115+
match pat.kind {
10911116
PatKind::Wild => write!(f, "_"),
10921117
PatKind::Never => write!(f, "!"),
1093-
PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"),
1118+
PatKind::AscribeUserType { ref subpattern, .. } => {
1119+
write!(f, "{}: _", subpattern.display())
1120+
}
10941121
PatKind::Binding { name, mode, ref subpattern, .. } => {
10951122
f.write_str(mode.prefix_str())?;
10961123
write!(f, "{name}")?;
10971124
if let Some(ref subpattern) = *subpattern {
1098-
write!(f, " @ {subpattern}")?;
1125+
write!(f, " @ {}", subpattern.display())?;
10991126
}
11001127
Ok(())
11011128
}
11021129
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
1103-
let variant_and_name = match self.kind {
1130+
let variant_and_name = match pat.kind {
11041131
PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
11051132
let variant = adt_def.variant(variant_index);
11061133
let adt_did = adt_def.did();
@@ -1113,7 +1140,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
11131140
};
11141141
Some((variant, name))
11151142
}),
1116-
_ => self.ty.ty_adt_def().and_then(|adt_def| {
1143+
_ => pat.ty.ty_adt_def().and_then(|adt_def| {
11171144
if !adt_def.is_enum() {
11181145
ty::tls::with(|tcx| {
11191146
Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
@@ -1138,11 +1165,11 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
11381165
continue;
11391166
}
11401167
let name = variant.fields[p.field].name;
1141-
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
1168+
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern.display())?;
11421169
printed += 1;
11431170
}
11441171

1145-
let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
1172+
let is_union = pat.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
11461173
if printed < variant.fields.len() && (!is_union || printed == 0) {
11471174
write!(f, "{}..", start_or_comma())?;
11481175
}
@@ -1161,14 +1188,14 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
11611188
// Common case: the field is where we expect it.
11621189
if let Some(p) = subpatterns.get(i) {
11631190
if p.field.index() == i {
1164-
write!(f, "{}", p.pattern)?;
1191+
write!(f, "{}", p.pattern.display())?;
11651192
continue;
11661193
}
11671194
}
11681195

11691196
// Otherwise, we have to go looking for it.
11701197
if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
1171-
write!(f, "{}", p.pattern)?;
1198+
write!(f, "{}", p.pattern.display())?;
11721199
} else {
11731200
write!(f, "_")?;
11741201
}
@@ -1179,45 +1206,45 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
11791206
Ok(())
11801207
}
11811208
PatKind::Deref { ref subpattern } => {
1182-
match self.ty.kind() {
1209+
match pat.ty.kind() {
11831210
ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
11841211
ty::Ref(_, _, mutbl) => {
11851212
write!(f, "&{}", mutbl.prefix_str())?;
11861213
}
1187-
_ => bug!("{} is a bad Deref pattern type", self.ty),
1214+
_ => bug!("{} is a bad Deref pattern type", pat.ty),
11881215
}
1189-
write!(f, "{subpattern}")
1216+
write!(f, "{}", subpattern.display())
11901217
}
11911218
PatKind::DerefPattern { ref subpattern, .. } => {
1192-
write!(f, "deref!({subpattern})")
1219+
write!(f, "deref!({})", subpattern.display())
11931220
}
11941221
PatKind::Constant { value } => write!(f, "{value}"),
11951222
PatKind::InlineConstant { def: _, ref subpattern } => {
1196-
write!(f, "{} (from inline const)", subpattern)
1223+
write!(f, "{} (from inline const)", subpattern.display())
11971224
}
11981225
PatKind::Range(ref range) => write!(f, "{range}"),
11991226
PatKind::Slice { ref prefix, ref slice, ref suffix }
12001227
| PatKind::Array { ref prefix, ref slice, ref suffix } => {
12011228
write!(f, "[")?;
12021229
for p in prefix.iter() {
1203-
write!(f, "{}{}", start_or_comma(), p)?;
1230+
write!(f, "{}{}", start_or_comma(), p.display())?;
12041231
}
12051232
if let Some(ref slice) = *slice {
12061233
write!(f, "{}", start_or_comma())?;
12071234
match slice.kind {
12081235
PatKind::Wild => {}
1209-
_ => write!(f, "{slice}")?,
1236+
_ => write!(f, "{}", slice.display())?,
12101237
}
12111238
write!(f, "..")?;
12121239
}
12131240
for p in suffix.iter() {
1214-
write!(f, "{}{}", start_or_comma(), p)?;
1241+
write!(f, "{}{}", start_or_comma(), p.display())?;
12151242
}
12161243
write!(f, "]")
12171244
}
12181245
PatKind::Or { ref pats } => {
12191246
for pat in pats.iter() {
1220-
write!(f, "{}{}", start_or_continue(" | "), pat)?;
1247+
write!(f, "{}{}", start_or_continue(" | "), pat.display())?;
12211248
}
12221249
Ok(())
12231250
}

0 commit comments

Comments
 (0)