about summary refs log tree commit diff
diff options
context:
space:
mode:
authoriDawer <ilnur.iskhakov.oss@outlook.com>2022-06-25 20:08:00 +0500
committeriDawer <ilnur.iskhakov.oss@outlook.com>2022-06-25 20:08:00 +0500
commitfb6278e750b48d0478a696fa666b443a045f1c8c (patch)
tree0b73b0526f8b6ceeb7dcd41c89e20e1ed7420c47
parent4ff9bedbedb6dedf46e03d7ce2648e24514f9ba8 (diff)
downloadrust-fb6278e750b48d0478a696fa666b443a045f1c8c.tar.gz
rust-fb6278e750b48d0478a696fa666b443a045f1c8c.zip
Reduce intermediate allocations while printing witnesses
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs29
-rw-r--r--crates/hir-ty/src/diagnostics/match_check.rs2
2 files changed, 17 insertions, 14 deletions
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index e9743b4dfe7..8cca522aef6 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -2,6 +2,7 @@
 //! through the body using inference results: mismatched arg counts, missing
 //! fields, etc.
 
+use std::fmt;
 use std::sync::Arc;
 
 use hir_def::{path::path, resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule};
@@ -378,6 +379,15 @@ fn missing_match_arms<'p>(
     witnesses: Vec<DeconstructedPat<'p>>,
     arms: &[MatchArm],
 ) -> String {
+    struct DisplayWitness<'a, 'p>(&'a DeconstructedPat<'p>, &'a MatchCheckCtx<'a, 'p>);
+    impl<'a, 'p> fmt::Display for DisplayWitness<'a, 'p> {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            let DisplayWitness(witness, cx) = *self;
+            let pat = witness.to_pat(cx);
+            write!(f, "{}", pat.display(cx.db))
+        }
+    }
+
     let non_empty_enum = match scrut_ty.as_adt() {
         Some((AdtId::EnumId(e), _)) => !cx.db.enum_data(e).variants.is_empty(),
         _ => false,
@@ -385,25 +395,18 @@ fn missing_match_arms<'p>(
     if arms.is_empty() && !non_empty_enum {
         format!("type `{}` is non-empty", scrut_ty.display(cx.db))
     } else {
+        let pat_display = |witness| DisplayWitness(witness, cx);
         const LIMIT: usize = 3;
         match &*witnesses {
-            [witness] => format!("`{}` not covered", witness.to_pat(&cx).display(cx.db)),
+            [witness] => format!("`{}` not covered", pat_display(witness)),
             [head @ .., tail] if head.len() < LIMIT => {
-                let head: Vec<_> = head.iter().map(|w| w.to_pat(cx)).collect();
-                format!(
-                    "`{}` and `{}` not covered",
-                    head.iter().map(|p| p.display(cx.db)).join("`, `"),
-                    tail.to_pat(&cx).display(cx.db)
-                )
+                let head = head.iter().map(pat_display);
+                format!("`{}` and `{}` not covered", head.format("`, `"), pat_display(tail))
             }
             _ => {
                 let (head, tail) = witnesses.split_at(LIMIT);
-                let head: Vec<_> = head.iter().map(|w| w.to_pat(cx)).collect();
-                format!(
-                    "`{}` and {} more not covered",
-                    head.iter().map(|p| p.display(cx.db)).join("`, `"),
-                    tail.len()
-                )
+                let head = head.iter().map(pat_display);
+                format!("`{}` and {} more not covered", head.format("`, `"), tail.len())
             }
         }
     }
diff --git a/crates/hir-ty/src/diagnostics/match_check.rs b/crates/hir-ty/src/diagnostics/match_check.rs
index 276246f266c..61cab7be033 100644
--- a/crates/hir-ty/src/diagnostics/match_check.rs
+++ b/crates/hir-ty/src/diagnostics/match_check.rs
@@ -400,7 +400,7 @@ impl<F> HirDisplay for WriteWith<F>
 where
     F: Fn(&mut HirFormatter) -> Result<(), HirDisplayError>,
 {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
         (self.0)(f)
     }
 }