1
Fork 0

Restrict From<S> for {D,Subd}iagnosticMessage.

Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.

This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.

As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
This commit is contained in:
Nicholas Nethercote 2023-04-20 13:26:58 +10:00
parent a368898de7
commit 6b62f37402
177 changed files with 791 additions and 787 deletions

View file

@ -672,7 +672,7 @@ fn non_exhaustive_match<'p, 'tcx>(
ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local());
adt_defined_here(cx, &mut err, scrut_ty, &witnesses);
err.note(&format!(
err.note(format!(
"the matched value is of type `{}`{}",
scrut_ty,
if is_variant_list_non_exhaustive { ", which is marked as non-exhaustive" } else { "" }
@ -682,13 +682,13 @@ fn non_exhaustive_match<'p, 'tcx>(
&& witnesses.len() == 1
&& matches!(witnesses[0].ctor(), Constructor::NonExhaustive)
{
err.note(&format!(
err.note(format!(
"`{}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \
exhaustively",
scrut_ty,
));
if cx.tcx.sess.is_nightly_build() {
err.help(&format!(
err.help(format!(
"add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \
enable precise `{}` matching",
scrut_ty,
@ -793,9 +793,9 @@ fn non_exhaustive_match<'p, 'tcx>(
},
);
if let Some((span, sugg)) = suggestion {
err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders);
} else {
err.help(&msg);
err.help(msg);
}
err.emit();
}
@ -857,7 +857,7 @@ fn adt_defined_here<'p, 'tcx>(
for pat in spans {
span.push_span_label(pat, "not covered");
}
err.span_note(span, &format!("`{}` defined here", ty));
err.span_note(span, format!("`{}` defined here", ty));
}
}

View file

@ -229,7 +229,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
self.lower_pattern_range(ty, lc, hc, end, lo_span, lo_expr, hi_expr)
}
None => {
let msg = &format!(
let msg = format!(
"found bad range pattern `{:?}` outside of error recovery",
(&lo, &hi),
);