Skip to content

Commit 70ebbc1

Browse files
committed
Improve the WitnessPat: Debug impl
1 parent b68b2e6 commit 70ebbc1

File tree

4 files changed

+88
-75
lines changed

4 files changed

+88
-75
lines changed

compiler/rustc_pattern_analysis/src/constructor.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,80 @@ impl<Cx: PatCx> Constructor<Cx> {
814814
}
815815
})
816816
}
817+
818+
pub(crate) fn fmt_fields(
819+
&self,
820+
f: &mut fmt::Formatter<'_>,
821+
ty: &Cx::Ty,
822+
mut fields: impl Iterator<Item = impl fmt::Debug>,
823+
) -> fmt::Result {
824+
let mut first = true;
825+
let mut start_or_continue = |s| {
826+
if first {
827+
first = false;
828+
""
829+
} else {
830+
s
831+
}
832+
};
833+
let mut start_or_comma = || start_or_continue(", ");
834+
835+
match self {
836+
Struct | Variant(_) | UnionField => {
837+
Cx::write_variant_name(f, self, ty)?;
838+
// Without `cx`, we can't know which field corresponds to which, so we can't
839+
// get the names of the fields. Instead we just display everything as a tuple
840+
// struct, which should be good enough.
841+
write!(f, "(")?;
842+
for p in fields {
843+
write!(f, "{}{:?}", start_or_comma(), p)?;
844+
}
845+
write!(f, ")")?;
846+
}
847+
// Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
848+
// be careful to detect strings here. However a string literal pattern will never
849+
// be reported as a non-exhaustiveness witness, so we can ignore this issue.
850+
Ref => {
851+
write!(f, "&{:?}", &fields.next().unwrap())?;
852+
}
853+
Slice(slice) => {
854+
write!(f, "[")?;
855+
match slice.kind {
856+
SliceKind::FixedLen(_) => {
857+
for p in fields {
858+
write!(f, "{}{:?}", start_or_comma(), p)?;
859+
}
860+
}
861+
SliceKind::VarLen(prefix_len, _) => {
862+
for p in fields.by_ref().take(prefix_len) {
863+
write!(f, "{}{:?}", start_or_comma(), p)?;
864+
}
865+
write!(f, "{}..", start_or_comma())?;
866+
for p in fields {
867+
write!(f, "{}{:?}", start_or_comma(), p)?;
868+
}
869+
}
870+
}
871+
write!(f, "]")?;
872+
}
873+
Bool(b) => write!(f, "{b}")?,
874+
// Best-effort, will render signed ranges incorrectly
875+
IntRange(range) => write!(f, "{range:?}")?,
876+
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
877+
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}")?,
878+
Str(value) => write!(f, "{value:?}")?,
879+
Opaque(..) => write!(f, "<constant pattern>")?,
880+
Or => {
881+
for pat in fields {
882+
write!(f, "{}{:?}", start_or_continue(" | "), pat)?;
883+
}
884+
}
885+
Wildcard | Missing | NonExhaustive | Hidden | PrivateUninhabited => {
886+
write!(f, "_ : {:?}", ty)?
887+
}
888+
}
889+
Ok(())
890+
}
817891
}
818892

819893
#[derive(Debug, Clone, Copy)]

compiler/rustc_pattern_analysis/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ pub trait PatCx: Sized + fmt::Debug {
120120
/// `DeconstructedPat`. Only invoqued when `pat.ctor()` is `Struct | Variant(_) | UnionField`.
121121
fn write_variant_name(
122122
f: &mut fmt::Formatter<'_>,
123-
pat: &crate::pat::DeconstructedPat<Self>,
123+
ctor: &crate::constructor::Constructor<Self>,
124+
ty: &Self::Ty,
124125
) -> fmt::Result;
125126

126127
/// Raise a bug.

compiler/rustc_pattern_analysis/src/pat.rs

Lines changed: 8 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -138,80 +138,11 @@ impl<Cx: PatCx> DeconstructedPat<Cx> {
138138
/// This is best effort and not good enough for a `Display` impl.
139139
impl<Cx: PatCx> fmt::Debug for DeconstructedPat<Cx> {
140140
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141-
let pat = self;
142-
let mut first = true;
143-
let mut start_or_continue = |s| {
144-
if first {
145-
first = false;
146-
""
147-
} else {
148-
s
149-
}
150-
};
151-
let mut start_or_comma = || start_or_continue(", ");
152-
153141
let mut fields: Vec<_> = (0..self.arity).map(|_| PatOrWild::Wild).collect();
154142
for ipat in self.iter_fields() {
155143
fields[ipat.idx] = PatOrWild::Pat(&ipat.pat);
156144
}
157-
158-
match pat.ctor() {
159-
Struct | Variant(_) | UnionField => {
160-
Cx::write_variant_name(f, pat)?;
161-
// Without `cx`, we can't know which field corresponds to which, so we can't
162-
// get the names of the fields. Instead we just display everything as a tuple
163-
// struct, which should be good enough.
164-
write!(f, "(")?;
165-
for p in fields {
166-
write!(f, "{}", start_or_comma())?;
167-
write!(f, "{p:?}")?;
168-
}
169-
write!(f, ")")
170-
}
171-
// Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
172-
// be careful to detect strings here. However a string literal pattern will never
173-
// be reported as a non-exhaustiveness witness, so we can ignore this issue.
174-
Ref => {
175-
write!(f, "&{:?}", &fields[0])
176-
}
177-
Slice(slice) => {
178-
write!(f, "[")?;
179-
match slice.kind {
180-
SliceKind::FixedLen(_) => {
181-
for p in fields {
182-
write!(f, "{}{:?}", start_or_comma(), p)?;
183-
}
184-
}
185-
SliceKind::VarLen(prefix_len, _) => {
186-
for p in &fields[..prefix_len] {
187-
write!(f, "{}{:?}", start_or_comma(), p)?;
188-
}
189-
write!(f, "{}", start_or_comma())?;
190-
write!(f, "..")?;
191-
for p in &fields[prefix_len..] {
192-
write!(f, "{}{:?}", start_or_comma(), p)?;
193-
}
194-
}
195-
}
196-
write!(f, "]")
197-
}
198-
Bool(b) => write!(f, "{b}"),
199-
// Best-effort, will render signed ranges incorrectly
200-
IntRange(range) => write!(f, "{range:?}"),
201-
F32Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
202-
F64Range(lo, hi, end) => write!(f, "{lo}{end}{hi}"),
203-
Str(value) => write!(f, "{value:?}"),
204-
Opaque(..) => write!(f, "<constant pattern>"),
205-
Or => {
206-
for pat in fields {
207-
write!(f, "{}{:?}", start_or_continue(" | "), pat)?;
208-
}
209-
Ok(())
210-
}
211-
Wildcard | Missing | NonExhaustive | Hidden | PrivateUninhabited => {
212-
write!(f, "_ : {:?}", pat.ty())
213-
}
214-
}
145+
self.ctor().fmt_fields(f, self.ty(), fields.into_iter())
215146
}
216147
}
217148

@@ -294,7 +225,6 @@ impl<'p, Cx: PatCx> fmt::Debug for PatOrWild<'p, Cx> {
294225

295226
/// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics
296227
/// purposes. As such they don't use interning and can be cloned.
297-
#[derive(Debug)]
298228
pub struct WitnessPat<Cx: PatCx> {
299229
ctor: Constructor<Cx>,
300230
pub(crate) fields: Vec<WitnessPat<Cx>>,
@@ -338,3 +268,10 @@ impl<Cx: PatCx> WitnessPat<Cx> {
338268
self.fields.iter()
339269
}
340270
}
271+
272+
/// This is best effort and not good enough for a `Display` impl.
273+
impl<Cx: PatCx> fmt::Debug for WitnessPat<Cx> {
274+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
275+
self.ctor().fmt_fields(f, self.ty(), self.fields.iter())
276+
}
277+
}

compiler/rustc_pattern_analysis/src/rustc.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -873,13 +873,14 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
873873

874874
fn write_variant_name(
875875
f: &mut fmt::Formatter<'_>,
876-
pat: &crate::pat::DeconstructedPat<Self>,
876+
ctor: &crate::constructor::Constructor<Self>,
877+
ty: &Self::Ty,
877878
) -> fmt::Result {
878-
if let ty::Adt(adt, _) = pat.ty().kind() {
879+
if let ty::Adt(adt, _) = ty.kind() {
879880
if adt.is_box() {
880881
write!(f, "Box")?
881882
} else {
882-
let variant = adt.variant(Self::variant_index_for_adt(pat.ctor(), *adt));
883+
let variant = adt.variant(Self::variant_index_for_adt(ctor, *adt));
883884
write!(f, "{}", variant.name)?;
884885
}
885886
}

0 commit comments

Comments
 (0)