summary refs log tree commit diff
path: root/compiler/rustc_pattern_analysis
diff options
context:
space:
mode:
authorJubilee <46493976+workingjubilee@users.noreply.github.com>2024-08-15 18:44:16 -0700
committerGitHub <noreply@github.com>2024-08-15 18:44:16 -0700
commit5858329f1adf44ba39815d2040a0cb1478d37bc8 (patch)
treef6b0aae76936f9775a67d2296473bc5b7904c81c /compiler/rustc_pattern_analysis
parent4fd4da9e23492da01af5bd6e804eb8cec1ee1c76 (diff)
parentfc55129774c8209d46d89b8a27b13fb7d8ce2b44 (diff)
downloadrust-5858329f1adf44ba39815d2040a0cb1478d37bc8.tar.gz
rust-5858329f1adf44ba39815d2040a0cb1478d37bc8.zip
Rollup merge of #128965 - Zalathar:no-pat, r=Nadrieril
Remove `print::Pat` from the printing of `WitnessPat`

After the preliminary work done in #128536, we can now get rid of `print::Pat` entirely.

- First, we introduce a variant `PatKind::Print(String)`.
- Then we incrementally remove each other variant of `PatKind`, by having the relevant code produce `PatKind::Print` instead.
- Once `PatKind::Print` is the only remaining variant, it becomes easy to remove `print::Pat` and replace it with `String`.

There is more cleanup that I have in mind, but this seemed like a natural stopping point for one PR.

r? ```@Nadrieril```
Diffstat (limited to 'compiler/rustc_pattern_analysis')
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs83
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc/print.rs89
2 files changed, 60 insertions, 112 deletions
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index bcd3d3092c3..d7885e05a2f 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -774,17 +774,16 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
         }
     }
 
-    /// Convert to a [`print::Pat`] for diagnostic purposes.
-    fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> print::Pat<'tcx> {
-        use print::{Pat, PatKind};
+    /// Prints an [`IntRange`] to a string for diagnostic purposes.
+    fn print_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> String {
         use MaybeInfiniteInt::*;
         let cx = self;
-        let kind = if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) {
-            PatKind::Wild
+        if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) {
+            "_".to_string()
         } else if range.is_singleton() {
             let lo = cx.hoist_pat_range_bdy(range.lo, ty);
             let value = lo.as_finite().unwrap();
-            PatKind::Constant { value }
+            value.to_string()
         } else {
             // We convert to an inclusive range for diagnostics.
             let mut end = rustc_hir::RangeEnd::Included;
@@ -807,32 +806,24 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                 range.hi
             };
             let hi = cx.hoist_pat_range_bdy(hi, ty);
-            PatKind::Range(Box::new(PatRange { lo, hi, end, ty: ty.inner() }))
-        };
-
-        Pat { ty: ty.inner(), kind }
+            PatRange { lo, hi, end, ty: ty.inner() }.to_string()
+        }
     }
 
     /// Prints a [`WitnessPat`] to an owned string, for diagnostic purposes.
+    ///
+    /// This panics for patterns that don't appear in diagnostics, like float ranges.
     pub fn print_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> String {
-        // This works by converting the witness pattern to a `print::Pat`
-        // and then printing that, but callers don't need to know that.
-        self.hoist_witness_pat(pat).to_string()
-    }
-
-    /// Convert to a [`print::Pat`] for diagnostic purposes. This panics for patterns that don't
-    /// appear in diagnostics, like float ranges.
-    fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> print::Pat<'tcx> {
-        use print::{FieldPat, Pat, PatKind};
         let cx = self;
-        let hoist = |p| Box::new(cx.hoist_witness_pat(p));
-        let kind = match pat.ctor() {
-            Bool(b) => PatKind::Constant { value: mir::Const::from_bool(cx.tcx, *b) },
-            IntRange(range) => return self.hoist_pat_range(range, *pat.ty()),
+        let print = |p| cx.print_witness_pat(p);
+        match pat.ctor() {
+            Bool(b) => b.to_string(),
+            Str(s) => s.to_string(),
+            IntRange(range) => return self.print_pat_range(range, *pat.ty()),
             Struct if pat.ty().is_box() => {
                 // Outside of the `alloc` crate, the only way to create a struct pattern
                 // of type `Box` is to use a `box` pattern via #[feature(box_patterns)].
-                PatKind::Box { subpattern: hoist(&pat.fields[0]) }
+                format!("box {}", print(&pat.fields[0]))
             }
             Struct | Variant(_) | UnionField => {
                 let enum_info = match *pat.ty().kind() {
@@ -847,12 +838,29 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                 let subpatterns = pat
                     .iter_fields()
                     .enumerate()
-                    .map(|(i, pat)| FieldPat { field: FieldIdx::new(i), pattern: hoist(pat) })
+                    .map(|(i, pat)| print::FieldPat {
+                        field: FieldIdx::new(i),
+                        pattern: print(pat),
+                        is_wildcard: would_print_as_wildcard(cx.tcx, pat),
+                    })
                     .collect::<Vec<_>>();
 
-                PatKind::StructLike { enum_info, subpatterns }
+                let mut s = String::new();
+                print::write_struct_like(
+                    &mut s,
+                    self.tcx,
+                    pat.ty().inner(),
+                    &enum_info,
+                    &subpatterns,
+                )
+                .unwrap();
+                s
+            }
+            Ref => {
+                let mut s = String::new();
+                print::write_ref_like(&mut s, pat.ty().inner(), &print(&pat.fields[0])).unwrap();
+                s
             }
-            Ref => PatKind::Deref { subpattern: hoist(&pat.fields[0]) },
             Slice(slice) => {
                 let (prefix_len, has_dot_dot) = match slice.kind {
                     SliceKind::FixedLen(len) => (len, false),
@@ -879,14 +887,15 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
                     }
                 }
 
-                let prefix = prefix.iter().map(hoist).collect();
-                let suffix = suffix.iter().map(hoist).collect();
+                let prefix = prefix.iter().map(print).collect::<Vec<_>>();
+                let suffix = suffix.iter().map(print).collect::<Vec<_>>();
 
-                PatKind::Slice { prefix, has_dot_dot, suffix }
+                let mut s = String::new();
+                print::write_slice_like(&mut s, &prefix, has_dot_dot, &suffix).unwrap();
+                s
             }
-            &Str(value) => PatKind::Constant { value },
-            Never if self.tcx.features().never_patterns => PatKind::Never,
-            Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
+            Never if self.tcx.features().never_patterns => "!".to_string(),
+            Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => "_".to_string(),
             Missing { .. } => bug!(
                 "trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
                 `Missing` should have been processed in `apply_constructors`"
@@ -894,9 +903,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
             F16Range(..) | F32Range(..) | F64Range(..) | F128Range(..) | Opaque(..) | Or => {
                 bug!("can't convert to pattern: {:?}", pat)
             }
-        };
-
-        Pat { ty: pat.ty().inner(), kind }
+        }
     }
 }
 
@@ -972,7 +979,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
         overlaps_on: IntRange,
         overlaps_with: &[&crate::pat::DeconstructedPat<Self>],
     ) {
-        let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty());
+        let overlap_as_pat = self.print_pat_range(&overlaps_on, *pat.ty());
         let overlaps: Vec<_> = overlaps_with
             .iter()
             .map(|pat| pat.data().span)
@@ -1012,7 +1019,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
             suggested_range.end = rustc_hir::RangeEnd::Included;
             suggested_range.to_string()
         };
-        let gap_as_pat = self.hoist_pat_range(&gap, *pat.ty());
+        let gap_as_pat = self.print_pat_range(&gap, *pat.ty());
         if gapped_with.is_empty() {
             // If `gapped_with` is empty, `gap == T::MAX`.
             self.tcx.emit_node_span_lint(
diff --git a/compiler/rustc_pattern_analysis/src/rustc/print.rs b/compiler/rustc_pattern_analysis/src/rustc/print.rs
index 7d638714605..17e389df17e 100644
--- a/compiler/rustc_pattern_analysis/src/rustc/print.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc/print.rs
@@ -11,75 +11,16 @@
 
 use std::fmt;
 
-use rustc_middle::thir::PatRange;
+use rustc_middle::bug;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
-use rustc_middle::{bug, mir};
 use rustc_span::sym;
 use rustc_target::abi::{FieldIdx, VariantIdx};
 
 #[derive(Clone, Debug)]
-pub(crate) struct FieldPat<'tcx> {
+pub(crate) struct FieldPat {
     pub(crate) field: FieldIdx,
-    pub(crate) pattern: Box<Pat<'tcx>>,
-}
-
-#[derive(Clone, Debug)]
-pub(crate) struct Pat<'tcx> {
-    pub(crate) ty: Ty<'tcx>,
-    pub(crate) kind: PatKind<'tcx>,
-}
-
-#[derive(Clone, Debug)]
-pub(crate) enum PatKind<'tcx> {
-    Wild,
-
-    StructLike {
-        enum_info: EnumInfo<'tcx>,
-        subpatterns: Vec<FieldPat<'tcx>>,
-    },
-
-    Box {
-        subpattern: Box<Pat<'tcx>>,
-    },
-
-    Deref {
-        subpattern: Box<Pat<'tcx>>,
-    },
-
-    Constant {
-        value: mir::Const<'tcx>,
-    },
-
-    Range(Box<PatRange<'tcx>>),
-
-    Slice {
-        prefix: Box<[Box<Pat<'tcx>>]>,
-        /// True if this slice-like pattern should include a `..` between the
-        /// prefix and suffix.
-        has_dot_dot: bool,
-        suffix: Box<[Box<Pat<'tcx>>]>,
-    },
-
-    Never,
-}
-
-impl<'tcx> fmt::Display for Pat<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.kind {
-            PatKind::Wild => write!(f, "_"),
-            PatKind::Never => write!(f, "!"),
-            PatKind::Box { ref subpattern } => write!(f, "box {subpattern}"),
-            PatKind::StructLike { ref enum_info, ref subpatterns } => {
-                ty::tls::with(|tcx| write_struct_like(f, tcx, self.ty, enum_info, 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, has_dot_dot, ref suffix } => {
-                write_slice_like(f, prefix, has_dot_dot, suffix)
-            }
-        }
-    }
+    pub(crate) pattern: String,
+    pub(crate) is_wildcard: bool,
 }
 
 /// Returns a closure that will return `""` when called the first time,
@@ -103,12 +44,12 @@ pub(crate) enum EnumInfo<'tcx> {
     NotEnum,
 }
 
-fn write_struct_like<'tcx>(
+pub(crate) fn write_struct_like<'tcx>(
     f: &mut impl fmt::Write,
     tcx: TyCtxt<'_>,
     ty: Ty<'tcx>,
     enum_info: &EnumInfo<'tcx>,
-    subpatterns: &[FieldPat<'tcx>],
+    subpatterns: &[FieldPat],
 ) -> fmt::Result {
     let variant_and_name = match *enum_info {
         EnumInfo::Enum { adt_def, variant_index } => {
@@ -139,12 +80,12 @@ fn write_struct_like<'tcx>(
             write!(f, " {{ ")?;
 
             let mut printed = 0;
-            for p in subpatterns {
-                if let PatKind::Wild = p.pattern.kind {
+            for &FieldPat { field, ref pattern, is_wildcard } in subpatterns {
+                if is_wildcard {
                     continue;
                 }
-                let name = variant.fields[p.field].name;
-                write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
+                let field_name = variant.fields[field].name;
+                write!(f, "{}{field_name}: {pattern}", start_or_comma())?;
                 printed += 1;
             }
 
@@ -184,10 +125,10 @@ fn write_struct_like<'tcx>(
     Ok(())
 }
 
-fn write_ref_like<'tcx>(
+pub(crate) fn write_ref_like<'tcx>(
     f: &mut impl fmt::Write,
     ty: Ty<'tcx>,
-    subpattern: &Pat<'tcx>,
+    subpattern: &str,
 ) -> fmt::Result {
     match ty.kind() {
         ty::Ref(_, _, mutbl) => {
@@ -198,11 +139,11 @@ fn write_ref_like<'tcx>(
     write!(f, "{subpattern}")
 }
 
-fn write_slice_like<'tcx>(
+pub(crate) fn write_slice_like(
     f: &mut impl fmt::Write,
-    prefix: &[Box<Pat<'tcx>>],
+    prefix: &[String],
     has_dot_dot: bool,
-    suffix: &[Box<Pat<'tcx>>],
+    suffix: &[String],
 ) -> fmt::Result {
     let mut start_or_comma = start_or_comma();
     write!(f, "[")?;