Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit ccfd94e

Browse files
committed
Break up print::Pat printing into several helper functions
1 parent 6a2cd0d commit ccfd94e

File tree

1 file changed

+142
-113
lines changed
  • compiler/rustc_pattern_analysis/src/rustc

1 file changed

+142
-113
lines changed

compiler/rustc_pattern_analysis/src/rustc/print.rs

Lines changed: 142 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -64,130 +64,159 @@ pub(crate) enum PatKind<'tcx> {
6464

6565
impl<'tcx> fmt::Display for Pat<'tcx> {
6666
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67-
// Printing lists is a chore.
68-
let mut first = true;
69-
let mut start_or_continue = |s| {
70-
if first {
71-
first = false;
72-
""
73-
} else {
74-
s
75-
}
76-
};
77-
let mut start_or_comma = || start_or_continue(", ");
78-
7967
match self.kind {
8068
PatKind::Wild => write!(f, "_"),
8169
PatKind::Never => write!(f, "!"),
8270
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
83-
let variant_and_name = match self.kind {
84-
PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
85-
let variant = adt_def.variant(variant_index);
86-
let adt_did = adt_def.did();
87-
let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
88-
|| tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
89-
{
90-
variant.name.to_string()
91-
} else {
92-
format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
93-
};
94-
Some((variant, name))
95-
}),
96-
_ => self.ty.ty_adt_def().and_then(|adt_def| {
97-
if !adt_def.is_enum() {
98-
ty::tls::with(|tcx| {
99-
Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
100-
})
101-
} else {
102-
None
103-
}
104-
}),
105-
};
106-
107-
if let Some((variant, name)) = &variant_and_name {
108-
write!(f, "{name}")?;
109-
110-
// Only for Adt we can have `S {...}`,
111-
// which we handle separately here.
112-
if variant.ctor.is_none() {
113-
write!(f, " {{ ")?;
114-
115-
let mut printed = 0;
116-
for p in subpatterns {
117-
if let PatKind::Wild = p.pattern.kind {
118-
continue;
119-
}
120-
let name = variant.fields[p.field].name;
121-
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
122-
printed += 1;
123-
}
124-
125-
let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
126-
if printed < variant.fields.len() && (!is_union || printed == 0) {
127-
write!(f, "{}..", start_or_comma())?;
128-
}
129-
130-
return write!(f, " }}");
131-
}
132-
}
133-
134-
let num_fields =
135-
variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
136-
if num_fields != 0 || variant_and_name.is_none() {
137-
write!(f, "(")?;
138-
for i in 0..num_fields {
139-
write!(f, "{}", start_or_comma())?;
140-
141-
// Common case: the field is where we expect it.
142-
if let Some(p) = subpatterns.get(i) {
143-
if p.field.index() == i {
144-
write!(f, "{}", p.pattern)?;
145-
continue;
146-
}
147-
}
148-
149-
// Otherwise, we have to go looking for it.
150-
if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
151-
write!(f, "{}", p.pattern)?;
152-
} else {
153-
write!(f, "_")?;
154-
}
155-
}
156-
write!(f, ")")?;
157-
}
158-
159-
Ok(())
160-
}
161-
PatKind::Deref { ref subpattern } => {
162-
match self.ty.kind() {
163-
ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
164-
ty::Ref(_, _, mutbl) => {
165-
write!(f, "&{}", mutbl.prefix_str())?;
166-
}
167-
_ => bug!("{} is a bad Deref pattern type", self.ty),
168-
}
169-
write!(f, "{subpattern}")
71+
write_struct_like(f, self.ty, &self.kind, subpatterns)
17072
}
73+
PatKind::Deref { ref subpattern } => write_ref_like(f, self.ty, subpattern),
17174
PatKind::Constant { value } => write!(f, "{value}"),
17275
PatKind::Range(ref range) => write!(f, "{range}"),
17376
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
174-
write!(f, "[")?;
175-
for p in prefix.iter() {
176-
write!(f, "{}{}", start_or_comma(), p)?;
177-
}
178-
if let Some(ref slice) = *slice {
179-
write!(f, "{}", start_or_comma())?;
180-
match slice.kind {
181-
PatKind::Wild => {}
182-
_ => write!(f, "{slice}")?,
183-
}
184-
write!(f, "..")?;
77+
write_slice_like(f, prefix, slice, suffix)
78+
}
79+
}
80+
}
81+
}
82+
83+
/// Returns a closure that will return `""` when called the first time,
84+
/// and then return `", "` when called any subsequent times.
85+
/// Useful for printing comma-separated lists.
86+
fn start_or_comma() -> impl FnMut() -> &'static str {
87+
let mut first = true;
88+
move || {
89+
if first {
90+
first = false;
91+
""
92+
} else {
93+
", "
94+
}
95+
}
96+
}
97+
98+
fn write_struct_like<'tcx>(
99+
f: &mut impl fmt::Write,
100+
ty: Ty<'tcx>,
101+
kind: &PatKind<'tcx>,
102+
subpatterns: &[FieldPat<'tcx>],
103+
) -> fmt::Result {
104+
let variant_and_name = match *kind {
105+
PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
106+
let variant = adt_def.variant(variant_index);
107+
let adt_did = adt_def.did();
108+
let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
109+
|| tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
110+
{
111+
variant.name.to_string()
112+
} else {
113+
format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
114+
};
115+
Some((variant, name))
116+
}),
117+
_ => ty.ty_adt_def().and_then(|adt_def| {
118+
if !adt_def.is_enum() {
119+
ty::tls::with(|tcx| {
120+
Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
121+
})
122+
} else {
123+
None
124+
}
125+
}),
126+
};
127+
128+
let mut start_or_comma = start_or_comma();
129+
130+
if let Some((variant, name)) = &variant_and_name {
131+
write!(f, "{name}")?;
132+
133+
// Only for Adt we can have `S {...}`,
134+
// which we handle separately here.
135+
if variant.ctor.is_none() {
136+
write!(f, " {{ ")?;
137+
138+
let mut printed = 0;
139+
for p in subpatterns {
140+
if let PatKind::Wild = p.pattern.kind {
141+
continue;
185142
}
186-
for p in suffix.iter() {
187-
write!(f, "{}{}", start_or_comma(), p)?;
143+
let name = variant.fields[p.field].name;
144+
write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
145+
printed += 1;
146+
}
147+
148+
let is_union = ty.ty_adt_def().is_some_and(|adt| adt.is_union());
149+
if printed < variant.fields.len() && (!is_union || printed == 0) {
150+
write!(f, "{}..", start_or_comma())?;
151+
}
152+
153+
return write!(f, " }}");
154+
}
155+
}
156+
157+
let num_fields = variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
158+
if num_fields != 0 || variant_and_name.is_none() {
159+
write!(f, "(")?;
160+
for i in 0..num_fields {
161+
write!(f, "{}", start_or_comma())?;
162+
163+
// Common case: the field is where we expect it.
164+
if let Some(p) = subpatterns.get(i) {
165+
if p.field.index() == i {
166+
write!(f, "{}", p.pattern)?;
167+
continue;
188168
}
189-
write!(f, "]")
169+
}
170+
171+
// Otherwise, we have to go looking for it.
172+
if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
173+
write!(f, "{}", p.pattern)?;
174+
} else {
175+
write!(f, "_")?;
190176
}
191177
}
178+
write!(f, ")")?;
179+
}
180+
181+
Ok(())
182+
}
183+
184+
fn write_ref_like<'tcx>(
185+
f: &mut impl fmt::Write,
186+
ty: Ty<'tcx>,
187+
subpattern: &Pat<'tcx>,
188+
) -> fmt::Result {
189+
match ty.kind() {
190+
ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
191+
ty::Ref(_, _, mutbl) => {
192+
write!(f, "&{}", mutbl.prefix_str())?;
193+
}
194+
_ => bug!("{ty} is a bad ref pattern type"),
195+
}
196+
write!(f, "{subpattern}")
197+
}
198+
199+
fn write_slice_like<'tcx>(
200+
f: &mut impl fmt::Write,
201+
prefix: &[Box<Pat<'tcx>>],
202+
slice: &Option<Box<Pat<'tcx>>>,
203+
suffix: &[Box<Pat<'tcx>>],
204+
) -> fmt::Result {
205+
let mut start_or_comma = start_or_comma();
206+
write!(f, "[")?;
207+
for p in prefix.iter() {
208+
write!(f, "{}{}", start_or_comma(), p)?;
209+
}
210+
if let Some(ref slice) = *slice {
211+
write!(f, "{}", start_or_comma())?;
212+
match slice.kind {
213+
PatKind::Wild => {}
214+
_ => write!(f, "{slice}")?,
215+
}
216+
write!(f, "..")?;
217+
}
218+
for p in suffix.iter() {
219+
write!(f, "{}{}", start_or_comma(), p)?;
192220
}
221+
write!(f, "]")
193222
}

0 commit comments

Comments
 (0)