Reduce intermediate allocations while printing witnesses

This commit is contained in:
iDawer 2022-06-25 20:08:00 +05:00
parent 4ff9bedbed
commit fb6278e750
2 changed files with 17 additions and 14 deletions

View file

@ -2,6 +2,7 @@
//! through the body using inference results: mismatched arg counts, missing //! through the body using inference results: mismatched arg counts, missing
//! fields, etc. //! fields, etc.
use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use hir_def::{path::path, resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule}; use hir_def::{path::path, resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule};
@ -378,6 +379,15 @@ fn missing_match_arms<'p>(
witnesses: Vec<DeconstructedPat<'p>>, witnesses: Vec<DeconstructedPat<'p>>,
arms: &[MatchArm], arms: &[MatchArm],
) -> String { ) -> 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() { let non_empty_enum = match scrut_ty.as_adt() {
Some((AdtId::EnumId(e), _)) => !cx.db.enum_data(e).variants.is_empty(), Some((AdtId::EnumId(e), _)) => !cx.db.enum_data(e).variants.is_empty(),
_ => false, _ => false,
@ -385,25 +395,18 @@ fn missing_match_arms<'p>(
if arms.is_empty() && !non_empty_enum { if arms.is_empty() && !non_empty_enum {
format!("type `{}` is non-empty", scrut_ty.display(cx.db)) format!("type `{}` is non-empty", scrut_ty.display(cx.db))
} else { } else {
let pat_display = |witness| DisplayWitness(witness, cx);
const LIMIT: usize = 3; const LIMIT: usize = 3;
match &*witnesses { 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 => { [head @ .., tail] if head.len() < LIMIT => {
let head: Vec<_> = head.iter().map(|w| w.to_pat(cx)).collect(); let head = head.iter().map(pat_display);
format!( format!("`{}` and `{}` not covered", head.format("`, `"), pat_display(tail))
"`{}` and `{}` not covered",
head.iter().map(|p| p.display(cx.db)).join("`, `"),
tail.to_pat(&cx).display(cx.db)
)
} }
_ => { _ => {
let (head, tail) = witnesses.split_at(LIMIT); let (head, tail) = witnesses.split_at(LIMIT);
let head: Vec<_> = head.iter().map(|w| w.to_pat(cx)).collect(); let head = head.iter().map(pat_display);
format!( format!("`{}` and {} more not covered", head.format("`, `"), tail.len())
"`{}` and {} more not covered",
head.iter().map(|p| p.display(cx.db)).join("`, `"),
tail.len()
)
} }
} }
} }

View file

@ -400,7 +400,7 @@ impl<F> HirDisplay for WriteWith<F>
where where
F: Fn(&mut HirFormatter) -> Result<(), HirDisplayError>, 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) (self.0)(f)
} }
} }