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

@ -213,7 +213,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
for structs containing the field being coerced, \
ZST fields with 1 byte alignment, and nothing else",
)
.note(&format!(
.note(format!(
"extra field `{}` of type `{}` is not allowed",
field.name, ty_a,
))
@ -241,7 +241,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
for a coercion between structures with a single field \
being coerced",
)
.note(&format!(
.note(format!(
"currently, {} fields need coercions: {}",
coerced_fields.len(),
coerced_fields
@ -298,7 +298,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err.to_string()));
tcx.sess.fatal(format!("`CoerceUnsized` implementation {}", err.to_string()));
});
let source = tcx.type_of(impl_did).subst_identity();
@ -469,7 +469,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
"`CoerceUnsized` may only be implemented for \
a coercion between structures with one field being coerced",
)
.note(&format!(
.note(format!(
"currently, {} fields need coercions: {}",
diff_fields.len(),
diff_fields

View file

@ -146,7 +146,7 @@ impl<'tcx> InherentCollect<'tcx> {
);
err.help("consider using an extension trait instead");
if let ty::Ref(_, subty, _) = ty.kind() {
err.note(&format!(
err.note(format!(
"you could also try moving the reference to \
uses of `{}` (such as `self`) within the implementation",
subty

View file

@ -372,10 +372,10 @@ fn emit_orphan_check_error<'tcx>(
if is_target_ty {
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
err.span_label(self_ty_span, &msg);
err.span_label(self_ty_span, msg);
} else {
// Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
err.span_label(trait_span, &msg);
err.span_label(trait_span, msg);
}
}
err.note("define and implement a trait or new type instead");
@ -531,15 +531,15 @@ fn lint_auto_trait_impl<'tcx>(
let self_descr = tcx.def_descr(self_type_did);
match arg {
ty::util::NotUniqueParam::DuplicateParam(arg) => {
lint.note(&format!("`{}` is mentioned multiple times", arg));
lint.note(format!("`{}` is mentioned multiple times", arg));
}
ty::util::NotUniqueParam::NotParam(arg) => {
lint.note(&format!("`{}` is not a generic parameter", arg));
lint.note(format!("`{}` is not a generic parameter", arg));
}
}
lint.span_note(
item_span,
&format!(
format!(
"try using the same sequence of generic parameters as the {} definition",
self_descr,
),