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 d36bde7db0
commit 431cce1540
5 changed files with 8 additions and 8 deletions

View File

@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
if let PredicateKind::Clause(Clause::Trait(trait_pred)) =
obligation.predicate.kind().skip_binder()
{
db.note(&format!(
db.note(format!(
"`{}` doesn't implement `{}`",
trait_pred.self_ty(),
trait_pred.trait_ref.print_only_trait_path(),

View File

@ -353,7 +353,7 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se
pub fn read_conf(sess: &Session, path: &io::Result<(Option<PathBuf>, Vec<String>)>) -> Conf {
if let Ok((_, warnings)) = path {
for warning in warnings {
sess.warn(warning);
sess.warn(warning.clone());
}
}
let file_name = match path {

View File

@ -175,13 +175,13 @@ fn check_manual_split_once_indirect(
let remove_msg = format!("remove the `{iter_ident}` usages");
diag.span_suggestion(
first.span,
&remove_msg,
remove_msg.clone(),
"",
app,
);
diag.span_suggestion(
second.span,
&remove_msg,
remove_msg,
"",
app,
);

View File

@ -131,13 +131,13 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
for field in non_send_fields {
diag.span_note(
field.def.span,
&format!("it is not safe to send field `{}` to another thread", field.def.ident.name),
format!("it is not safe to send field `{}` to another thread", field.def.ident.name),
);
match field.generic_params.len() {
0 => diag.help("use a thread-safe type that implements `Send`"),
1 if is_ty_param(field.ty) => diag.help(&format!("add `{}: Send` bound in `Send` impl", field.ty)),
_ => diag.help(&format!(
1 if is_ty_param(field.ty) => diag.help(format!("add `{}: Send` bound in `Send` impl", field.ty)),
_ => diag.help(format!(
"add bounds on type parameter{} `{}` that satisfy `{}: Send`",
if field.generic_params.len() > 1 { "s" } else { "" },
field.generic_params_string(),

View File

@ -133,7 +133,7 @@ pub fn get_unique_attr<'a>(
let mut unique_attr: Option<&ast::Attribute> = None;
for attr in get_attr(sess, attrs, name) {
if let Some(duplicate) = unique_attr {
sess.struct_span_err(attr.span, &format!("`{name}` is defined multiple times"))
sess.struct_span_err(attr.span, format!("`{name}` is defined multiple times"))
.span_note(duplicate.span, "first definition found here")
.emit();
} else {