@@ -1073,8 +1073,33 @@ impl<'tcx> PatRangeBoundary<'tcx> {
1073
1073
}
1074
1074
}
1075
1075
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 > {
1077
1100
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1101
+ let & Self { pat } = self ;
1102
+
1078
1103
// Printing lists is a chore.
1079
1104
let mut first = true ;
1080
1105
let mut start_or_continue = |s| {
@@ -1087,20 +1112,22 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
1087
1112
} ;
1088
1113
let mut start_or_comma = || start_or_continue ( ", " ) ;
1089
1114
1090
- match self . kind {
1115
+ match pat . kind {
1091
1116
PatKind :: Wild => write ! ( f, "_" ) ,
1092
1117
PatKind :: Never => write ! ( f, "!" ) ,
1093
- PatKind :: AscribeUserType { ref subpattern, .. } => write ! ( f, "{subpattern}: _" ) ,
1118
+ PatKind :: AscribeUserType { ref subpattern, .. } => {
1119
+ write ! ( f, "{}: _" , subpattern. display( ) )
1120
+ }
1094
1121
PatKind :: Binding { name, mode, ref subpattern, .. } => {
1095
1122
f. write_str ( mode. prefix_str ( ) ) ?;
1096
1123
write ! ( f, "{name}" ) ?;
1097
1124
if let Some ( ref subpattern) = * subpattern {
1098
- write ! ( f, " @ {subpattern}" ) ?;
1125
+ write ! ( f, " @ {}" , subpattern . display ( ) ) ?;
1099
1126
}
1100
1127
Ok ( ( ) )
1101
1128
}
1102
1129
PatKind :: Variant { ref subpatterns, .. } | PatKind :: Leaf { ref subpatterns } => {
1103
- let variant_and_name = match self . kind {
1130
+ let variant_and_name = match pat . kind {
1104
1131
PatKind :: Variant { adt_def, variant_index, .. } => ty:: tls:: with ( |tcx| {
1105
1132
let variant = adt_def. variant ( variant_index) ;
1106
1133
let adt_did = adt_def. did ( ) ;
@@ -1113,7 +1140,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
1113
1140
} ;
1114
1141
Some ( ( variant, name) )
1115
1142
} ) ,
1116
- _ => self . ty . ty_adt_def ( ) . and_then ( |adt_def| {
1143
+ _ => pat . ty . ty_adt_def ( ) . and_then ( |adt_def| {
1117
1144
if !adt_def. is_enum ( ) {
1118
1145
ty:: tls:: with ( |tcx| {
1119
1146
Some ( ( adt_def. non_enum_variant ( ) , tcx. def_path_str ( adt_def. did ( ) ) ) )
@@ -1138,11 +1165,11 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
1138
1165
continue ;
1139
1166
}
1140
1167
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 ( ) ) ?;
1142
1169
printed += 1 ;
1143
1170
}
1144
1171
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 ( ) ) ;
1146
1173
if printed < variant. fields . len ( ) && ( !is_union || printed == 0 ) {
1147
1174
write ! ( f, "{}.." , start_or_comma( ) ) ?;
1148
1175
}
@@ -1161,14 +1188,14 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
1161
1188
// Common case: the field is where we expect it.
1162
1189
if let Some ( p) = subpatterns. get ( i) {
1163
1190
if p. field . index ( ) == i {
1164
- write ! ( f, "{}" , p. pattern) ?;
1191
+ write ! ( f, "{}" , p. pattern. display ( ) ) ?;
1165
1192
continue ;
1166
1193
}
1167
1194
}
1168
1195
1169
1196
// Otherwise, we have to go looking for it.
1170
1197
if let Some ( p) = subpatterns. iter ( ) . find ( |p| p. field . index ( ) == i) {
1171
- write ! ( f, "{}" , p. pattern) ?;
1198
+ write ! ( f, "{}" , p. pattern. display ( ) ) ?;
1172
1199
} else {
1173
1200
write ! ( f, "_" ) ?;
1174
1201
}
@@ -1179,45 +1206,45 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
1179
1206
Ok ( ( ) )
1180
1207
}
1181
1208
PatKind :: Deref { ref subpattern } => {
1182
- match self . ty . kind ( ) {
1209
+ match pat . ty . kind ( ) {
1183
1210
ty:: Adt ( def, _) if def. is_box ( ) => write ! ( f, "box " ) ?,
1184
1211
ty:: Ref ( _, _, mutbl) => {
1185
1212
write ! ( f, "&{}" , mutbl. prefix_str( ) ) ?;
1186
1213
}
1187
- _ => bug ! ( "{} is a bad Deref pattern type" , self . ty) ,
1214
+ _ => bug ! ( "{} is a bad Deref pattern type" , pat . ty) ,
1188
1215
}
1189
- write ! ( f, "{subpattern}" )
1216
+ write ! ( f, "{}" , subpattern . display ( ) )
1190
1217
}
1191
1218
PatKind :: DerefPattern { ref subpattern, .. } => {
1192
- write ! ( f, "deref!({subpattern })" )
1219
+ write ! ( f, "deref!({})" , subpattern . display ( ) )
1193
1220
}
1194
1221
PatKind :: Constant { value } => write ! ( f, "{value}" ) ,
1195
1222
PatKind :: InlineConstant { def : _, ref subpattern } => {
1196
- write ! ( f, "{} (from inline const)" , subpattern)
1223
+ write ! ( f, "{} (from inline const)" , subpattern. display ( ) )
1197
1224
}
1198
1225
PatKind :: Range ( ref range) => write ! ( f, "{range}" ) ,
1199
1226
PatKind :: Slice { ref prefix, ref slice, ref suffix }
1200
1227
| PatKind :: Array { ref prefix, ref slice, ref suffix } => {
1201
1228
write ! ( f, "[" ) ?;
1202
1229
for p in prefix. iter ( ) {
1203
- write ! ( f, "{}{}" , start_or_comma( ) , p) ?;
1230
+ write ! ( f, "{}{}" , start_or_comma( ) , p. display ( ) ) ?;
1204
1231
}
1205
1232
if let Some ( ref slice) = * slice {
1206
1233
write ! ( f, "{}" , start_or_comma( ) ) ?;
1207
1234
match slice. kind {
1208
1235
PatKind :: Wild => { }
1209
- _ => write ! ( f, "{slice}" ) ?,
1236
+ _ => write ! ( f, "{}" , slice . display ( ) ) ?,
1210
1237
}
1211
1238
write ! ( f, ".." ) ?;
1212
1239
}
1213
1240
for p in suffix. iter ( ) {
1214
- write ! ( f, "{}{}" , start_or_comma( ) , p) ?;
1241
+ write ! ( f, "{}{}" , start_or_comma( ) , p. display ( ) ) ?;
1215
1242
}
1216
1243
write ! ( f, "]" )
1217
1244
}
1218
1245
PatKind :: Or { ref pats } => {
1219
1246
for pat in pats. iter ( ) {
1220
- write ! ( f, "{}{}" , start_or_continue( " | " ) , pat) ?;
1247
+ write ! ( f, "{}{}" , start_or_continue( " | " ) , pat. display ( ) ) ?;
1221
1248
}
1222
1249
Ok ( ( ) )
1223
1250
}
0 commit comments