Use Cow in {D,Subd}iagnosticMessage.

Each of `{D,Subd}iagnosticMessage::{Str,Eager}` has a comment:
```
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
```
This commit answers that question in the affirmative. It's not the most
compelling change ever, but it might be worth merging.

This requires changing the `impl<'a> From<&'a str>` impls to `impl
From<&'static str>`, which involves a bunch of knock-on changes that
require/result in call sites being a little more precise about exactly
what kind of string they use to create errors, and not just `&str`. This
will result in fewer unnecessary allocations, though this will not have
any notable perf effects given that these are error paths.

Note that I was lazy within Clippy, using `to_string` in a few places to
preserve the existing string imprecision. I could have used `impl
Into<{D,Subd}iagnosticMessage>` in various places as is done in the
compiler, but that would have required changes to *many* call sites
(mostly changing `&format("...")` to `format!("...")`) which didn't seem
worthwhile.
This commit is contained in:
Nicholas Nethercote 2023-05-04 10:55:21 +10:00
parent a37852e54b
commit 53f1e6b7ef
5 changed files with 21 additions and 22 deletions

View File

@ -154,7 +154,7 @@ fn check_fn(
if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, &self.msrv) { if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, &self.msrv) {
if cx.tcx.is_const_fn_raw(def_id.to_def_id()) { if cx.tcx.is_const_fn_raw(def_id.to_def_id()) {
cx.tcx.sess.span_err(span, err.as_ref()); cx.tcx.sess.span_err(span, err);
} }
} else { } else {
span_lint(cx, MISSING_CONST_FOR_FN, span, "this could be a `const fn`"); span_lint(cx, MISSING_CONST_FOR_FN, span, "this could be a `const fn`");

View File

@ -26,7 +26,6 @@
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy; use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy;
use std::borrow::Cow;
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -240,9 +239,8 @@ fn check_fn(
snippet_opt(cx, span) snippet_opt(cx, span)
.map_or( .map_or(
"change the call to".into(), "change the call to".into(),
|x| Cow::from(format!("change `{x}` to")), |x| format!("change `{x}` to"),
) ),
.as_ref(),
suggestion, suggestion,
Applicability::Unspecified, Applicability::Unspecified,
); );
@ -270,9 +268,8 @@ fn check_fn(
snippet_opt(cx, span) snippet_opt(cx, span)
.map_or( .map_or(
"change the call to".into(), "change the call to".into(),
|x| Cow::from(format!("change `{x}` to")) |x| format!("change `{x}` to")
) ),
.as_ref(),
suggestion, suggestion,
Applicability::Unspecified, Applicability::Unspecified,
); );

View File

@ -163,7 +163,7 @@ fn check_fn(
span_lint_and_then(cx, UNNECESSARY_WRAPS, span, lint_msg.as_str(), |diag| { span_lint_and_then(cx, UNNECESSARY_WRAPS, span, lint_msg.as_str(), |diag| {
diag.span_suggestion( diag.span_suggestion(
fn_decl.output.span(), fn_decl.output.span(),
return_type_sugg_msg.as_str(), return_type_sugg_msg,
return_type_sugg, return_type_sugg,
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );

View File

@ -46,7 +46,7 @@ fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) {
/// | ^^^^^^^^^^^^^^^^^^^^^^^ /// | ^^^^^^^^^^^^^^^^^^^^^^^
/// ``` /// ```
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: &str) { pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: &str) {
cx.struct_span_lint(lint, sp, msg, |diag| { cx.struct_span_lint(lint, sp, msg.to_string(), |diag| {
docs_link(diag, lint); docs_link(diag, lint);
diag diag
}); });
@ -80,11 +80,12 @@ pub fn span_lint_and_help<T: LintContext>(
help_span: Option<Span>, help_span: Option<Span>,
help: &str, help: &str,
) { ) {
cx.struct_span_lint(lint, span, msg, |diag| { cx.struct_span_lint(lint, span, msg.to_string(), |diag| {
let help = help.to_string();
if let Some(help_span) = help_span { if let Some(help_span) = help_span {
diag.span_help(help_span, help); diag.span_help(help_span, help.to_string());
} else { } else {
diag.help(help); diag.help(help.to_string());
} }
docs_link(diag, lint); docs_link(diag, lint);
diag diag
@ -122,7 +123,8 @@ pub fn span_lint_and_note<T: LintContext>(
note_span: Option<Span>, note_span: Option<Span>,
note: &str, note: &str,
) { ) {
cx.struct_span_lint(lint, span, msg, |diag| { cx.struct_span_lint(lint, span, msg.to_string(), |diag| {
let note = note.to_string();
if let Some(note_span) = note_span { if let Some(note_span) = note_span {
diag.span_note(note_span, note); diag.span_note(note_span, note);
} else { } else {
@ -143,7 +145,7 @@ pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str
S: Into<MultiSpan>, S: Into<MultiSpan>,
F: FnOnce(&mut Diagnostic), F: FnOnce(&mut Diagnostic),
{ {
cx.struct_span_lint(lint, sp, msg, |diag| { cx.struct_span_lint(lint, sp, msg.to_string(), |diag| {
f(diag); f(diag);
docs_link(diag, lint); docs_link(diag, lint);
diag diag
@ -151,7 +153,7 @@ pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str
} }
pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |diag| { cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| {
docs_link(diag, lint); docs_link(diag, lint);
diag diag
}); });
@ -165,7 +167,7 @@ pub fn span_lint_hir_and_then(
msg: &str, msg: &str,
f: impl FnOnce(&mut Diagnostic), f: impl FnOnce(&mut Diagnostic),
) { ) {
cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |diag| { cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| {
f(diag); f(diag);
docs_link(diag, lint); docs_link(diag, lint);
diag diag
@ -202,7 +204,7 @@ pub fn span_lint_and_sugg<T: LintContext>(
applicability: Applicability, applicability: Applicability,
) { ) {
span_lint_and_then(cx, lint, sp, msg, |diag| { span_lint_and_then(cx, lint, sp, msg, |diag| {
diag.span_suggestion(sp, help, sugg, applicability); diag.span_suggestion(sp, help.to_string(), sugg, applicability);
}); });
} }
@ -232,5 +234,5 @@ pub fn multispan_sugg_with_applicability<I>(
) where ) where
I: IntoIterator<Item = (Span, String)>, I: IntoIterator<Item = (Span, String)>,
{ {
diag.multipart_suggestion(help_msg, sugg.into_iter().collect(), applicability); diag.multipart_suggestion(help_msg.to_string(), sugg.into_iter().collect(), applicability);
} }

View File

@ -741,7 +741,7 @@ fn suggest_item_with_attr<D: Display + ?Sized>(
if let Some(indent) = indentation(cx, item) { if let Some(indent) = indentation(cx, item) {
let span = item.with_hi(item.lo()); let span = item.with_hi(item.lo());
self.span_suggestion(span, msg, format!("{attr}\n{indent}"), applicability); self.span_suggestion(span, msg.to_string(), format!("{attr}\n{indent}"), applicability);
} }
} }
@ -762,7 +762,7 @@ fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str
}) })
.collect::<String>(); .collect::<String>();
self.span_suggestion(span, msg, format!("{new_item}\n{indent}"), applicability); self.span_suggestion(span, msg.to_string(), format!("{new_item}\n{indent}"), applicability);
} }
} }
@ -779,7 +779,7 @@ fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability:
} }
} }
self.span_suggestion(remove_span, msg, "", applicability); self.span_suggestion(remove_span, msg.to_string(), "", applicability);
} }
} }