Skip to content

Commit a8ce4e5

Browse files
authored
Unrolled build for rust-lang#128430
Rollup merge of rust-lang#128430 - Zalathar:print-pat, r=Nadrieril Use a separate pattern type for `rustc_pattern_analysis` diagnostics The pattern-analysis code needs to print patterns, as part of its user-visible diagnostics. But it never actually tries to print "real" patterns! Instead, it only ever prints synthetic patterns that it has reconstructed from its own internal represenations. We can therefore simultaneously remove two obstacles to changing `thir::Pat`, by having the pattern-analysis code use its own dedicated type for building printable patterns, and then making `thir::Pat` not printable at all. r? `@Nadrieril`
2 parents 0b5eb7b + dd5a8d7 commit a8ce4e5

File tree

3 files changed

+216
-204
lines changed

3 files changed

+216
-204
lines changed

compiler/rustc_middle/src/thir.rs

+1-185
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_middle::ty::{
2828
TyCtxt, UpvarArgs,
2929
};
3030
use rustc_span::def_id::LocalDefId;
31-
use rustc_span::{sym, ErrorGuaranteed, Span, Symbol, DUMMY_SP};
31+
use rustc_span::{ErrorGuaranteed, Span, Symbol};
3232
use rustc_target::abi::{FieldIdx, Integer, Size, VariantIdx};
3333
use rustc_target::asm::InlineAsmRegOrRegClass;
3434
use tracing::instrument;
@@ -597,10 +597,6 @@ pub struct Pat<'tcx> {
597597
}
598598

599599
impl<'tcx> Pat<'tcx> {
600-
pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
601-
Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
602-
}
603-
604600
pub fn simple_ident(&self) -> Option<Symbol> {
605601
match self.kind {
606602
PatKind::Binding {
@@ -1073,186 +1069,6 @@ impl<'tcx> PatRangeBoundary<'tcx> {
10731069
}
10741070
}
10751071

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> {
1100-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1101-
let &Self { pat } = self;
1102-
1103-
// Printing lists is a chore.
1104-
let mut first = true;
1105-
let mut start_or_continue = |s| {
1106-
if first {
1107-
first = false;
1108-
""
1109-
} else {
1110-
s
1111-
}
1112-
};
1113-
let mut start_or_comma = || start_or_continue(", ");
1114-
1115-
match pat.kind {
1116-
PatKind::Wild => write!(f, "_"),
1117-
PatKind::Never => write!(f, "!"),
1118-
PatKind::AscribeUserType { ref subpattern, .. } => {
1119-
write!(f, "{}: _", subpattern.display())
1120-
}
1121-
PatKind::Binding { name, mode, ref subpattern, .. } => {
1122-
f.write_str(mode.prefix_str())?;
1123-
write!(f, "{name}")?;
1124-
if let Some(ref subpattern) = *subpattern {
1125-
write!(f, " @ {}", subpattern.display())?;
1126-
}
1127-
Ok(())
1128-
}
1129-
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
1130-
let variant_and_name = match pat.kind {
1131-
PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
1132-
let variant = adt_def.variant(variant_index);
1133-
let adt_did = adt_def.did();
1134-
let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
1135-
|| tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
1136-
{
1137-
variant.name.to_string()
1138-
} else {
1139-
format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
1140-
};
1141-
Some((variant, name))
1142-
}),
1143-
_ => pat.ty.ty_adt_def().and_then(|adt_def| {
1144-
if !adt_def.is_enum() {
1145-
ty::tls::with(|tcx| {
1146-
Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
1147-
})
1148-
} else {
1149-
None
1150-
}
1151-
}),
1152-
};
1153-
1154-
if let Some((variant, name)) = &variant_and_name {
1155-
write!(f, "{name}")?;
1156-
1157-
// Only for Adt we can have `S {...}`,
1158-
// which we handle separately here.
1159-
if variant.ctor.is_none() {
1160-
write!(f, " {{ ")?;
1161-
1162-
let mut printed = 0;
1163-
for p in subpatterns {
1164-
if let PatKind::Wild = p.pattern.kind {
1165-
continue;
1166-
}
1167-
let name = variant.fields[p.field].name;
1168-
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern.display())?;
1169-
printed += 1;
1170-
}
1171-
1172-
let is_union = pat.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
1173-
if printed < variant.fields.len() && (!is_union || printed == 0) {
1174-
write!(f, "{}..", start_or_comma())?;
1175-
}
1176-
1177-
return write!(f, " }}");
1178-
}
1179-
}
1180-
1181-
let num_fields =
1182-
variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
1183-
if num_fields != 0 || variant_and_name.is_none() {
1184-
write!(f, "(")?;
1185-
for i in 0..num_fields {
1186-
write!(f, "{}", start_or_comma())?;
1187-
1188-
// Common case: the field is where we expect it.
1189-
if let Some(p) = subpatterns.get(i) {
1190-
if p.field.index() == i {
1191-
write!(f, "{}", p.pattern.display())?;
1192-
continue;
1193-
}
1194-
}
1195-
1196-
// Otherwise, we have to go looking for it.
1197-
if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
1198-
write!(f, "{}", p.pattern.display())?;
1199-
} else {
1200-
write!(f, "_")?;
1201-
}
1202-
}
1203-
write!(f, ")")?;
1204-
}
1205-
1206-
Ok(())
1207-
}
1208-
PatKind::Deref { ref subpattern } => {
1209-
match pat.ty.kind() {
1210-
ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
1211-
ty::Ref(_, _, mutbl) => {
1212-
write!(f, "&{}", mutbl.prefix_str())?;
1213-
}
1214-
_ => bug!("{} is a bad Deref pattern type", pat.ty),
1215-
}
1216-
write!(f, "{}", subpattern.display())
1217-
}
1218-
PatKind::DerefPattern { ref subpattern, .. } => {
1219-
write!(f, "deref!({})", subpattern.display())
1220-
}
1221-
PatKind::Constant { value } => write!(f, "{value}"),
1222-
PatKind::InlineConstant { def: _, ref subpattern } => {
1223-
write!(f, "{} (from inline const)", subpattern.display())
1224-
}
1225-
PatKind::Range(ref range) => write!(f, "{range}"),
1226-
PatKind::Slice { ref prefix, ref slice, ref suffix }
1227-
| PatKind::Array { ref prefix, ref slice, ref suffix } => {
1228-
write!(f, "[")?;
1229-
for p in prefix.iter() {
1230-
write!(f, "{}{}", start_or_comma(), p.display())?;
1231-
}
1232-
if let Some(ref slice) = *slice {
1233-
write!(f, "{}", start_or_comma())?;
1234-
match slice.kind {
1235-
PatKind::Wild => {}
1236-
_ => write!(f, "{}", slice.display())?,
1237-
}
1238-
write!(f, "..")?;
1239-
}
1240-
for p in suffix.iter() {
1241-
write!(f, "{}{}", start_or_comma(), p.display())?;
1242-
}
1243-
write!(f, "]")
1244-
}
1245-
PatKind::Or { ref pats } => {
1246-
for pat in pats.iter() {
1247-
write!(f, "{}{}", start_or_continue(" | "), pat.display())?;
1248-
}
1249-
Ok(())
1250-
}
1251-
PatKind::Error(_) => write!(f, "<error>"),
1252-
}
1253-
}
1254-
}
1255-
12561072
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
12571073
#[cfg(target_pointer_width = "64")]
12581074
mod size_asserts {

compiler/rustc_pattern_analysis/src/rustc.rs

+22-19
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_hir::HirId;
77
use rustc_index::{Idx, IndexVec};
88
use rustc_middle::middle::stability::EvalResult;
99
use rustc_middle::mir::{self, Const};
10-
use rustc_middle::thir::{self, FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
10+
use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
1111
use rustc_middle::ty::layout::IntegerExt;
1212
use rustc_middle::ty::{
1313
self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
@@ -26,6 +26,8 @@ use crate::pat_column::PatternColumn;
2626
use crate::usefulness::{compute_match_usefulness, PlaceValidity};
2727
use crate::{errors, Captures, PatCx, PrivateUninhabitedField};
2828

29+
mod print;
30+
2931
// Re-export rustc-specific versions of all these types.
3032
pub type Constructor<'p, 'tcx> = crate::constructor::Constructor<RustcPatCtxt<'p, 'tcx>>;
3133
pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet<RustcPatCtxt<'p, 'tcx>>;
@@ -773,8 +775,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
773775
}
774776
}
775777

776-
/// Convert back to a `thir::Pat` for diagnostic purposes.
777-
fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> Pat<'tcx> {
778+
/// Convert to a [`print::Pat`] for diagnostic purposes.
779+
fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> print::Pat<'tcx> {
780+
use print::{Pat, PatKind};
778781
use MaybeInfiniteInt::*;
779782
let cx = self;
780783
let kind = if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) {
@@ -808,19 +811,20 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
808811
PatKind::Range(Box::new(PatRange { lo, hi, end, ty: ty.inner() }))
809812
};
810813

811-
Pat { ty: ty.inner(), span: DUMMY_SP, kind }
814+
Pat { ty: ty.inner(), kind }
812815
}
813816

814817
/// Prints a [`WitnessPat`] to an owned string, for diagnostic purposes.
815818
pub fn print_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> String {
816-
// This works by converting the witness pattern back to a `thir::Pat`
819+
// This works by converting the witness pattern to a `print::Pat`
817820
// and then printing that, but callers don't need to know that.
818821
self.hoist_witness_pat(pat).to_string()
819822
}
820823

821-
/// Convert back to a `thir::Pat` for diagnostic purposes. This panics for patterns that don't
824+
/// Convert to a [`print::Pat`] for diagnostic purposes. This panics for patterns that don't
822825
/// appear in diagnostics, like float ranges.
823-
fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> Pat<'tcx> {
826+
fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> print::Pat<'tcx> {
827+
use print::{FieldPat, Pat, PatKind};
824828
let cx = self;
825829
let is_wildcard = |pat: &Pat<'_>| matches!(pat.kind, PatKind::Wild);
826830
let mut subpatterns = pat.iter_fields().map(|p| Box::new(cx.hoist_witness_pat(p)));
@@ -840,15 +844,15 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
840844
// the pattern is a box pattern.
841845
PatKind::Deref { subpattern: subpatterns.next().unwrap() }
842846
}
843-
ty::Adt(adt_def, args) => {
847+
ty::Adt(adt_def, _args) => {
844848
let variant_index = RustcPatCtxt::variant_index_for_adt(&pat.ctor(), *adt_def);
845849
let subpatterns = subpatterns
846850
.enumerate()
847851
.map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern })
848852
.collect();
849853

850854
if adt_def.is_enum() {
851-
PatKind::Variant { adt_def: *adt_def, args, variant_index, subpatterns }
855+
PatKind::Variant { adt_def: *adt_def, variant_index, subpatterns }
852856
} else {
853857
PatKind::Leaf { subpatterns }
854858
}
@@ -885,7 +889,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
885889
}
886890
}
887891
let suffix: Box<[_]> = subpatterns.collect();
888-
let wild = Pat::wildcard_from_ty(pat.ty().inner());
892+
let wild = Pat { ty: pat.ty().inner(), kind: PatKind::Wild };
889893
PatKind::Slice {
890894
prefix: prefix.into_boxed_slice(),
891895
slice: Some(Box::new(wild)),
@@ -906,7 +910,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
906910
}
907911
};
908912

909-
Pat { ty: pat.ty().inner(), span: DUMMY_SP, kind }
913+
Pat { ty: pat.ty().inner(), kind }
910914
}
911915
}
912916

@@ -1003,12 +1007,11 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
10031007
}
10041008
// `pat` is an exclusive range like `lo..gap`. `gapped_with` contains ranges that start with
10051009
// `gap+1`.
1006-
let suggested_range: thir::Pat<'_> = {
1010+
let suggested_range: String = {
10071011
// Suggest `lo..=gap` instead.
1008-
let mut suggested_range = thir_pat.clone();
1009-
let thir::PatKind::Range(range) = &mut suggested_range.kind else { unreachable!() };
1010-
range.end = rustc_hir::RangeEnd::Included;
1011-
suggested_range
1012+
let mut suggested_range = PatRange::clone(range);
1013+
suggested_range.end = rustc_hir::RangeEnd::Included;
1014+
suggested_range.to_string()
10121015
};
10131016
let gap_as_pat = self.hoist_pat_range(&gap, *pat.ty());
10141017
if gapped_with.is_empty() {
@@ -1023,7 +1026,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
10231026
// That's the gap that isn't covered.
10241027
max: gap_as_pat.to_string(),
10251028
// Suggest `lo..=max` instead.
1026-
suggestion: suggested_range.to_string(),
1029+
suggestion: suggested_range,
10271030
},
10281031
);
10291032
} else {
@@ -1037,15 +1040,15 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
10371040
// That's the gap that isn't covered.
10381041
gap: gap_as_pat.to_string(),
10391042
// Suggest `lo..=gap` instead.
1040-
suggestion: suggested_range.to_string(),
1043+
suggestion: suggested_range,
10411044
// All these ranges skipped over `gap` which we think is probably a
10421045
// mistake.
10431046
gap_with: gapped_with
10441047
.iter()
10451048
.map(|pat| errors::GappedRange {
10461049
span: pat.data().span,
10471050
gap: gap_as_pat.to_string(),
1048-
first_range: thir_pat.to_string(),
1051+
first_range: range.to_string(),
10491052
})
10501053
.collect(),
10511054
},

0 commit comments

Comments
 (0)