summary refs log tree commit diff
path: root/compiler/rustc_pattern_analysis
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2024-08-02 19:55:16 +1000
committerZalathar <Zalathar@users.noreply.github.com>2024-08-07 20:52:46 +1000
commitccfd94e33473b610127aec56ab72c9eef4a9d1c8 (patch)
tree0985cb5c3483f07495f635efc34ecd44450937c1 /compiler/rustc_pattern_analysis
parent6a2cd0d50c9b7e1243d948641758c76d1f22e25e (diff)
downloadrust-ccfd94e33473b610127aec56ab72c9eef4a9d1c8.tar.gz
rust-ccfd94e33473b610127aec56ab72c9eef4a9d1c8.zip
Break up `print::Pat` printing into several helper functions
Diffstat (limited to 'compiler/rustc_pattern_analysis')
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc/print.rs255
1 files changed, 142 insertions, 113 deletions
diff --git a/compiler/rustc_pattern_analysis/src/rustc/print.rs b/compiler/rustc_pattern_analysis/src/rustc/print.rs
index 4b76764e8b1..59e6b1480c7 100644
--- a/compiler/rustc_pattern_analysis/src/rustc/print.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc/print.rs
@@ -64,130 +64,159 @@ pub(crate) enum PatKind<'tcx> {
 
 impl<'tcx> fmt::Display for Pat<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Printing lists is a chore.
-        let mut first = true;
-        let mut start_or_continue = |s| {
-            if first {
-                first = false;
-                ""
-            } else {
-                s
-            }
-        };
-        let mut start_or_comma = || start_or_continue(", ");
-
         match self.kind {
             PatKind::Wild => write!(f, "_"),
             PatKind::Never => write!(f, "!"),
             PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
-                let variant_and_name = match self.kind {
-                    PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
-                        let variant = adt_def.variant(variant_index);
-                        let adt_did = adt_def.did();
-                        let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
-                            || tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
-                        {
-                            variant.name.to_string()
-                        } else {
-                            format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
-                        };
-                        Some((variant, name))
-                    }),
-                    _ => self.ty.ty_adt_def().and_then(|adt_def| {
-                        if !adt_def.is_enum() {
-                            ty::tls::with(|tcx| {
-                                Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
-                            })
-                        } else {
-                            None
-                        }
-                    }),
-                };
-
-                if let Some((variant, name)) = &variant_and_name {
-                    write!(f, "{name}")?;
-
-                    // Only for Adt we can have `S {...}`,
-                    // which we handle separately here.
-                    if variant.ctor.is_none() {
-                        write!(f, " {{ ")?;
-
-                        let mut printed = 0;
-                        for p in subpatterns {
-                            if let PatKind::Wild = p.pattern.kind {
-                                continue;
-                            }
-                            let name = variant.fields[p.field].name;
-                            write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
-                            printed += 1;
-                        }
-
-                        let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
-                        if printed < variant.fields.len() && (!is_union || printed == 0) {
-                            write!(f, "{}..", start_or_comma())?;
-                        }
-
-                        return write!(f, " }}");
-                    }
-                }
-
-                let num_fields =
-                    variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
-                if num_fields != 0 || variant_and_name.is_none() {
-                    write!(f, "(")?;
-                    for i in 0..num_fields {
-                        write!(f, "{}", start_or_comma())?;
-
-                        // Common case: the field is where we expect it.
-                        if let Some(p) = subpatterns.get(i) {
-                            if p.field.index() == i {
-                                write!(f, "{}", p.pattern)?;
-                                continue;
-                            }
-                        }
-
-                        // Otherwise, we have to go looking for it.
-                        if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
-                            write!(f, "{}", p.pattern)?;
-                        } else {
-                            write!(f, "_")?;
-                        }
-                    }
-                    write!(f, ")")?;
-                }
-
-                Ok(())
-            }
-            PatKind::Deref { ref subpattern } => {
-                match self.ty.kind() {
-                    ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
-                    ty::Ref(_, _, mutbl) => {
-                        write!(f, "&{}", mutbl.prefix_str())?;
-                    }
-                    _ => bug!("{} is a bad Deref pattern type", self.ty),
-                }
-                write!(f, "{subpattern}")
+                write_struct_like(f, self.ty, &self.kind, subpatterns)
             }
+            PatKind::Deref { ref subpattern } => write_ref_like(f, self.ty, subpattern),
             PatKind::Constant { value } => write!(f, "{value}"),
             PatKind::Range(ref range) => write!(f, "{range}"),
             PatKind::Slice { ref prefix, ref slice, ref suffix } => {
-                write!(f, "[")?;
-                for p in prefix.iter() {
-                    write!(f, "{}{}", start_or_comma(), p)?;
-                }
-                if let Some(ref slice) = *slice {
-                    write!(f, "{}", start_or_comma())?;
-                    match slice.kind {
-                        PatKind::Wild => {}
-                        _ => write!(f, "{slice}")?,
-                    }
-                    write!(f, "..")?;
+                write_slice_like(f, prefix, slice, suffix)
+            }
+        }
+    }
+}
+
+/// Returns a closure that will return `""` when called the first time,
+/// and then return `", "` when called any subsequent times.
+/// Useful for printing comma-separated lists.
+fn start_or_comma() -> impl FnMut() -> &'static str {
+    let mut first = true;
+    move || {
+        if first {
+            first = false;
+            ""
+        } else {
+            ", "
+        }
+    }
+}
+
+fn write_struct_like<'tcx>(
+    f: &mut impl fmt::Write,
+    ty: Ty<'tcx>,
+    kind: &PatKind<'tcx>,
+    subpatterns: &[FieldPat<'tcx>],
+) -> fmt::Result {
+    let variant_and_name = match *kind {
+        PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
+            let variant = adt_def.variant(variant_index);
+            let adt_did = adt_def.did();
+            let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
+                || tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
+            {
+                variant.name.to_string()
+            } else {
+                format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
+            };
+            Some((variant, name))
+        }),
+        _ => ty.ty_adt_def().and_then(|adt_def| {
+            if !adt_def.is_enum() {
+                ty::tls::with(|tcx| {
+                    Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
+                })
+            } else {
+                None
+            }
+        }),
+    };
+
+    let mut start_or_comma = start_or_comma();
+
+    if let Some((variant, name)) = &variant_and_name {
+        write!(f, "{name}")?;
+
+        // Only for Adt we can have `S {...}`,
+        // which we handle separately here.
+        if variant.ctor.is_none() {
+            write!(f, " {{ ")?;
+
+            let mut printed = 0;
+            for p in subpatterns {
+                if let PatKind::Wild = p.pattern.kind {
+                    continue;
                 }
-                for p in suffix.iter() {
-                    write!(f, "{}{}", start_or_comma(), p)?;
+                let name = variant.fields[p.field].name;
+                write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
+                printed += 1;
+            }
+
+            let is_union = ty.ty_adt_def().is_some_and(|adt| adt.is_union());
+            if printed < variant.fields.len() && (!is_union || printed == 0) {
+                write!(f, "{}..", start_or_comma())?;
+            }
+
+            return write!(f, " }}");
+        }
+    }
+
+    let num_fields = variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
+    if num_fields != 0 || variant_and_name.is_none() {
+        write!(f, "(")?;
+        for i in 0..num_fields {
+            write!(f, "{}", start_or_comma())?;
+
+            // Common case: the field is where we expect it.
+            if let Some(p) = subpatterns.get(i) {
+                if p.field.index() == i {
+                    write!(f, "{}", p.pattern)?;
+                    continue;
                 }
-                write!(f, "]")
+            }
+
+            // Otherwise, we have to go looking for it.
+            if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
+                write!(f, "{}", p.pattern)?;
+            } else {
+                write!(f, "_")?;
             }
         }
+        write!(f, ")")?;
+    }
+
+    Ok(())
+}
+
+fn write_ref_like<'tcx>(
+    f: &mut impl fmt::Write,
+    ty: Ty<'tcx>,
+    subpattern: &Pat<'tcx>,
+) -> fmt::Result {
+    match ty.kind() {
+        ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
+        ty::Ref(_, _, mutbl) => {
+            write!(f, "&{}", mutbl.prefix_str())?;
+        }
+        _ => bug!("{ty} is a bad ref pattern type"),
+    }
+    write!(f, "{subpattern}")
+}
+
+fn write_slice_like<'tcx>(
+    f: &mut impl fmt::Write,
+    prefix: &[Box<Pat<'tcx>>],
+    slice: &Option<Box<Pat<'tcx>>>,
+    suffix: &[Box<Pat<'tcx>>],
+) -> fmt::Result {
+    let mut start_or_comma = start_or_comma();
+    write!(f, "[")?;
+    for p in prefix.iter() {
+        write!(f, "{}{}", start_or_comma(), p)?;
+    }
+    if let Some(ref slice) = *slice {
+        write!(f, "{}", start_or_comma())?;
+        match slice.kind {
+            PatKind::Wild => {}
+            _ => write!(f, "{slice}")?,
+        }
+        write!(f, "..")?;
+    }
+    for p in suffix.iter() {
+        write!(f, "{}{}", start_or_comma(), p)?;
     }
+    write!(f, "]")
 }