1
Fork 0

Auto merge of #111748 - nnethercote:Cow-DiagnosticMessage, r=WaffleLapkin

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.

r? `@WaffleLapkin`
This commit is contained in:
bors 2023-05-29 07:10:44 +00:00
commit 70e04bd88d
45 changed files with 308 additions and 287 deletions

View file

@ -18,7 +18,7 @@ pub fn expand_compile_error<'cx>(
reason = "diagnostic message is specified by user"
)]
#[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
cx.span_err(sp, var.as_str());
cx.span_err(sp, var.to_string());
DummyResult::any(sp)
}

View file

@ -377,7 +377,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
rustc::untranslatable_diagnostic,
reason = "cannot translate user-provided messages"
)]
handler.struct_diagnostic(msg.as_str())
handler.struct_diagnostic(msg.to_string())
} else {
handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
};

View file

@ -893,7 +893,7 @@ fn link_natively<'a>(
linker_path: &linker_path,
exit_status: prog.status,
command: &cmd,
escaped_output: &escaped_output,
escaped_output,
};
sess.diagnostic().emit_err(err);
// If MSVC's `link.exe` was expected but the return code

View file

@ -1800,7 +1800,7 @@ impl SharedEmitterMain {
handler.emit_diagnostic(&mut d);
}
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
let mut err = match level {
Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(),

View file

@ -336,7 +336,7 @@ pub struct LinkingFailed<'a> {
pub linker_path: &'a PathBuf,
pub exit_status: ExitStatus,
pub command: &'a Command,
pub escaped_output: &'a str,
pub escaped_output: String,
}
impl IntoDiagnostic<'_> for LinkingFailed<'_> {
@ -345,11 +345,13 @@ impl IntoDiagnostic<'_> for LinkingFailed<'_> {
diag.set_arg("linker_path", format!("{}", self.linker_path.display()));
diag.set_arg("exit_status", format!("{}", self.exit_status));
diag.note(format!("{:?}", self.command)).note(self.escaped_output);
let contains_undefined_ref = self.escaped_output.contains("undefined reference to");
diag.note(format!("{:?}", self.command)).note(self.escaped_output.to_string());
// Trying to match an error from OS linkers
// which by now we have no way to translate.
if self.escaped_output.contains("undefined reference to") {
if contains_undefined_ref {
diag.note(fluent::codegen_ssa_extern_funcs_not_found)
.note(fluent::codegen_ssa_specify_libraries_to_link)
.note(fluent::codegen_ssa_use_cargo_directive);

View file

@ -1258,7 +1258,7 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
if let Some(msg) = info.payload().downcast_ref::<String>() {
if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
// the error code is already going to be reported when the panic unwinds up the stack
let _ = early_error_no_abort(ErrorOutputType::default(), msg.as_str());
let _ = early_error_no_abort(ErrorOutputType::default(), msg.clone());
return;
}
};

View file

@ -263,8 +263,7 @@ type FluentId = Cow<'static, str>;
#[rustc_diagnostic_item = "SubdiagnosticMessage"]
pub enum SubdiagnosticMessage {
/// Non-translatable diagnostic message.
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
Str(String),
Str(Cow<'static, str>),
/// Translatable message which has already been translated eagerly.
///
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
@ -275,8 +274,7 @@ pub enum SubdiagnosticMessage {
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
/// stores messages which have been translated eagerly.
// FIXME(#100717): can a `Cow<'static, str>` be used here?
Eager(String),
Eager(Cow<'static, str>),
/// Identifier of a Fluent message. Instances of this variant are generated by the
/// `Subdiagnostic` derive.
FluentIdentifier(FluentId),
@ -290,17 +288,17 @@ pub enum SubdiagnosticMessage {
impl From<String> for SubdiagnosticMessage {
fn from(s: String) -> Self {
SubdiagnosticMessage::Str(s)
SubdiagnosticMessage::Str(Cow::Owned(s))
}
}
impl<'a> From<&'a str> for SubdiagnosticMessage {
fn from(s: &'a str) -> Self {
SubdiagnosticMessage::Str(s.to_string())
impl From<&'static str> for SubdiagnosticMessage {
fn from(s: &'static str) -> Self {
SubdiagnosticMessage::Str(Cow::Borrowed(s))
}
}
impl From<Cow<'static, str>> for SubdiagnosticMessage {
fn from(s: Cow<'static, str>) -> Self {
SubdiagnosticMessage::Str(s.to_string())
SubdiagnosticMessage::Str(s)
}
}
@ -312,8 +310,7 @@ impl From<Cow<'static, str>> for SubdiagnosticMessage {
#[rustc_diagnostic_item = "DiagnosticMessage"]
pub enum DiagnosticMessage {
/// Non-translatable diagnostic message.
// FIXME(#100717): can a `Cow<'static, str>` be used here?
Str(String),
Str(Cow<'static, str>),
/// Translatable message which has already been translated eagerly.
///
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
@ -324,8 +321,7 @@ pub enum DiagnosticMessage {
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
/// stores messages which have been translated eagerly.
// FIXME(#100717): can a `Cow<'static, str>` be used here?
Eager(String),
Eager(Cow<'static, str>),
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
/// message.
///
@ -363,17 +359,17 @@ impl DiagnosticMessage {
impl From<String> for DiagnosticMessage {
fn from(s: String) -> Self {
DiagnosticMessage::Str(s)
DiagnosticMessage::Str(Cow::Owned(s))
}
}
impl<'a> From<&'a str> for DiagnosticMessage {
fn from(s: &'a str) -> Self {
DiagnosticMessage::Str(s.to_string())
impl From<&'static str> for DiagnosticMessage {
fn from(s: &'static str) -> Self {
DiagnosticMessage::Str(Cow::Borrowed(s))
}
}
impl From<Cow<'static, str>> for DiagnosticMessage {
fn from(s: Cow<'static, str>) -> Self {
DiagnosticMessage::Str(s.to_string())
DiagnosticMessage::Str(s)
}
}

View file

@ -352,14 +352,9 @@ impl Diagnostic {
/// Labels all the given spans with the provided label.
/// See [`Self::span_label()`] for more information.
pub fn span_labels(
&mut self,
spans: impl IntoIterator<Item = Span>,
label: impl AsRef<str>,
) -> &mut Self {
let label = label.as_ref();
pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
for span in spans {
self.span_label(span, label);
self.span_label(span, label.to_string());
}
self
}
@ -394,17 +389,18 @@ impl Diagnostic {
expected: DiagnosticStyledString,
found: DiagnosticStyledString,
) -> &mut Self {
let mut msg: Vec<_> = vec![("required when trying to coerce from type `", Style::NoStyle)];
let mut msg: Vec<_> =
vec![(Cow::from("required when trying to coerce from type `"), Style::NoStyle)];
msg.extend(expected.0.iter().map(|x| match *x {
StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle),
StringPart::Highlighted(ref s) => (Cow::from(s.clone()), Style::Highlight),
}));
msg.push(("` to type '", Style::NoStyle));
msg.push((Cow::from("` to type '"), Style::NoStyle));
msg.extend(found.0.iter().map(|x| match *x {
StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle),
StringPart::Highlighted(ref s) => (Cow::from(s.clone()), Style::Highlight),
}));
msg.push(("`", Style::NoStyle));
msg.push((Cow::from("`"), Style::NoStyle));
// For now, just attach these as notes
self.highlighted_note(msg);

View file

@ -558,7 +558,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
}
// Take the `Diagnostic` by replacing it with a dummy.
let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::Str("".to_string()));
let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::from(""));
let diagnostic = std::mem::replace(&mut *self.inner.diagnostic, dummy);
// Disable the ICE on `Drop`.
@ -627,7 +627,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
pub fn span_labels(
&mut self,
spans: impl IntoIterator<Item = Span>,
label: impl AsRef<str>,
label: &str,
) -> &mut Self);
forward!(pub fn note_expected_found(
@ -781,8 +781,8 @@ impl Drop for DiagnosticBuilderInner<'_> {
if !panicking() {
handler.emit_diagnostic(&mut Diagnostic::new(
Level::Bug,
DiagnosticMessage::Str(
"the following error was constructed but not emitted".to_string(),
DiagnosticMessage::from(
"the following error was constructed but not emitted",
),
));
handler.emit_diagnostic(&mut self.diagnostic);

View file

@ -367,7 +367,7 @@ pub trait Emitter: Translate {
children.push(SubDiagnostic {
level: Level::Note,
message: vec![(DiagnosticMessage::Str(msg), Style::NoStyle)],
message: vec![(DiagnosticMessage::from(msg), Style::NoStyle)],
span: MultiSpan::new(),
render_span: None,
});

View file

@ -628,7 +628,7 @@ impl Handler {
message: DiagnosticMessage,
args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
) -> SubdiagnosticMessage {
SubdiagnosticMessage::Eager(self.eagerly_translate_to_string(message, args))
SubdiagnosticMessage::Eager(Cow::from(self.eagerly_translate_to_string(message, args)))
}
/// Translate `message` eagerly with `args` to `String`.
@ -1450,14 +1450,14 @@ impl HandlerInner {
self.emit_stashed_diagnostics();
let warnings = match self.deduplicated_warn_count {
0 => String::new(),
1 => "1 warning emitted".to_string(),
count => format!("{count} warnings emitted"),
0 => Cow::from(""),
1 => Cow::from("1 warning emitted"),
count => Cow::from(format!("{count} warnings emitted")),
};
let errors = match self.deduplicated_err_count {
0 => String::new(),
1 => "aborting due to previous error".to_string(),
count => format!("aborting due to {count} previous errors"),
0 => Cow::from(""),
1 => Cow::from("aborting due to previous error"),
count => Cow::from(format!("aborting due to {count} previous errors")),
};
if self.treat_err_as_bug() {
return;

View file

@ -1154,7 +1154,7 @@ impl<'a> ExtCtxt<'a> {
// Fixme: does this result in errors?
self.expansions.clear();
}
pub fn bug(&self, msg: &str) -> ! {
pub fn bug(&self, msg: &'static str) -> ! {
self.sess.parse_sess.span_diagnostic.bug(msg);
}
pub fn trace_macros(&self) -> bool {
@ -1224,7 +1224,7 @@ pub fn resolve_path(
pub fn expr_to_spanned_string<'a>(
cx: &'a mut ExtCtxt<'_>,
expr: P<ast::Expr>,
err_msg: &str,
err_msg: &'static str,
) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a, ErrorGuaranteed>, bool)>> {
// Perform eager expansion on the expression.
// We want to be able to handle e.g., `concat!("foo", "bar")`.
@ -1262,7 +1262,7 @@ pub fn expr_to_spanned_string<'a>(
pub fn expr_to_string(
cx: &mut ExtCtxt<'_>,
expr: P<ast::Expr>,
err_msg: &str,
err_msg: &'static str,
) -> Option<(Symbol, ast::StrStyle)> {
expr_to_spanned_string(cx, expr, err_msg)
.map_err(|err| {

View file

@ -170,7 +170,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
}
Error(err_sp, msg) => {
let span = err_sp.substitute_dummy(self.root_span);
self.cx.struct_span_err(span, msg.as_str()).emit();
self.cx.struct_span_err(span, msg.clone()).emit();
self.result = Some(DummyResult::any(span));
}
ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)),
@ -222,7 +222,7 @@ pub(super) fn emit_frag_parse_err(
{
let msg = &e.message[0];
e.message[0] = (
DiagnosticMessage::Str(format!(
DiagnosticMessage::from(format!(
"macro expansion ends with an incomplete expression: {}",
message.replace(", found `<eof>`", ""),
)),
@ -313,9 +313,9 @@ pub(super) fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: S
/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For
/// other tokens, this is "unexpected token...".
pub(super) fn parse_failure_msg(tok: &Token) -> String {
pub(super) fn parse_failure_msg(tok: &Token) -> Cow<'static, str> {
match tok.kind {
token::Eof => "unexpected end of macro invocation".to_string(),
_ => format!("no rules expected the token `{}`", pprust::token_to_string(tok),),
token::Eof => Cow::from("unexpected end of macro invocation"),
_ => Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok))),
}
}

View file

@ -25,6 +25,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
};
use std::borrow::Cow;
use std::iter;
/// Checks that a method from an impl conforms to the signature of
@ -684,7 +685,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
&cause,
hir.get_if_local(impl_m.def_id)
.and_then(|node| node.fn_decl())
.map(|decl| (decl.output.span(), "return type in trait".to_owned())),
.map(|decl| (decl.output.span(), Cow::from("return type in trait"))),
Some(infer::ValuePairs::Terms(ExpectedFound {
expected: trait_return_ty.into(),
found: impl_return_ty.into(),
@ -963,7 +964,7 @@ fn report_trait_method_mismatch<'tcx>(
infcx.err_ctxt().note_type_err(
&mut diag,
&cause,
trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
trait_err_span.map(|sp| (sp, Cow::from("type in trait"))),
Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })),
terr,
false,
@ -1731,7 +1732,7 @@ pub(super) fn compare_impl_const_raw(
infcx.err_ctxt().note_type_err(
&mut diag,
&cause,
trait_c_span.map(|span| (span, "type in trait".to_owned())),
trait_c_span.map(|span| (span, Cow::from("type in trait"))),
Some(infer::ValuePairs::Terms(ExpectedFound {
expected: trait_ty.into(),
found: impl_ty.into(),

View file

@ -121,10 +121,11 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
if has_safe_attr != is_in_list {
tcx.sess.struct_span_err(
tcx.def_span(intrinsic_id),
DiagnosticMessage::Str(format!(
"intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
tcx.item_name(intrinsic_id)
))).emit();
DiagnosticMessage::from(format!(
"intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
tcx.item_name(intrinsic_id)
)
)).emit();
}
is_in_list

View file

@ -122,7 +122,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
self.fcx
.need_type_info_err_in_generator(self.kind, span, unresolved_term)
.span_note(yield_data.span, &*note)
.span_note(yield_data.span, note)
.emit();
}
} else {
@ -686,7 +686,7 @@ fn check_must_not_suspend_def(
// Add optional reason note
if let Some(note) = attr.value_str() {
// FIXME(guswynn): consider formatting this better
lint.span_note(data.source_span, note.as_str());
lint.span_note(data.source_span, note.to_string());
}
// Add some quick suggestions on what to do

View file

@ -76,6 +76,7 @@ use rustc_middle::ty::{
};
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
use std::borrow::Cow;
use std::ops::{ControlFlow, Deref};
use std::path::PathBuf;
use std::{cmp, fmt, iter};
@ -1470,7 +1471,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&self,
diag: &mut Diagnostic,
cause: &ObligationCause<'tcx>,
secondary_span: Option<(Span, String)>,
secondary_span: Option<(Span, Cow<'static, str>)>,
mut values: Option<ValuePairs<'tcx>>,
terr: TypeError<'tcx>,
swap_secondary_and_primary: bool,
@ -1629,7 +1630,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
};
let mut label_or_note = |span: Span, msg: &str| {
let mut label_or_note = |span: Span, msg: Cow<'static, str>| {
if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() {
diag.span_label(span, msg);
} else {
@ -1643,15 +1644,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
..
})) = values
{
format!("expected this to be `{}`", expected)
Cow::from(format!("expected this to be `{}`", expected))
} else {
terr.to_string(self.tcx).to_string()
terr.to_string(self.tcx)
};
label_or_note(sp, &terr);
label_or_note(span, &msg);
label_or_note(sp, terr);
label_or_note(span, msg);
} else {
label_or_note(span, &terr.to_string(self.tcx));
label_or_note(sp, &msg);
label_or_note(span, terr.to_string(self.tcx));
label_or_note(sp, msg);
}
} else {
if let Some(values) = values
@ -1663,12 +1664,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
if expected == found {
label_or_note(span, &terr.to_string(self.tcx));
label_or_note(span, terr.to_string(self.tcx));
} else {
label_or_note(span, &format!("expected {expected}, found {found}"));
label_or_note(span, Cow::from(format!("expected {expected}, found {found}")));
}
} else {
label_or_note(span, &terr.to_string(self.tcx));
label_or_note(span, terr.to_string(self.tcx));
}
}

View file

@ -234,13 +234,13 @@ impl<T> Trait<T> for X {
);
}
(_, ty::Alias(ty::Projection | ty::Inherent, proj_ty)) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
let msg = format!(
let msg = || format!(
"consider constraining the associated type `{}` to `{}`",
values.found, values.expected,
);
if !(self.suggest_constraining_opaque_associated_type(
diag,
&msg,
msg,
proj_ty,
values.expected,
) || self.suggest_constraint(
@ -250,7 +250,7 @@ impl<T> Trait<T> for X {
proj_ty,
values.expected,
)) {
diag.help(msg);
diag.help(msg());
diag.note(
"for more information, visit \
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
@ -308,7 +308,7 @@ impl<T> Trait<T> for X {
fn suggest_constraint(
&self,
diag: &mut Diagnostic,
msg: &str,
msg: impl Fn() -> String,
body_owner_def_id: DefId,
proj_ty: &ty::AliasTy<'tcx>,
ty: Ty<'tcx>,
@ -340,7 +340,7 @@ impl<T> Trait<T> for X {
assoc,
assoc_substs,
ty,
msg,
&msg,
false,
) {
return true;
@ -374,10 +374,12 @@ impl<T> Trait<T> for X {
) {
let tcx = self.tcx;
let msg = format!(
"consider constraining the associated type `{}` to `{}`",
values.expected, values.found
);
let msg = || {
format!(
"consider constraining the associated type `{}` to `{}`",
values.expected, values.found
)
};
let body_owner = tcx.hir().get_if_local(body_owner_def_id);
let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
@ -428,10 +430,11 @@ impl<T> Trait<T> for X {
if callable_scope {
diag.help(format!(
"{} or calling a method that returns `{}`",
msg, values.expected
msg(),
values.expected
));
} else {
diag.help(msg);
diag.help(msg());
}
diag.note(
"for more information, visit \
@ -463,7 +466,7 @@ fn foo(&self) -> Self::T { String::new() }
fn suggest_constraining_opaque_associated_type(
&self,
diag: &mut Diagnostic,
msg: &str,
msg: impl Fn() -> String,
proj_ty: &ty::AliasTy<'tcx>,
ty: Ty<'tcx>,
) -> bool {
@ -635,7 +638,7 @@ fn foo(&self) -> Self::T { String::new() }
assoc: ty::AssocItem,
assoc_substs: &[ty::GenericArg<'tcx>],
ty: Ty<'tcx>,
msg: &str,
msg: impl Fn() -> String,
is_bound_surely_present: bool,
) -> bool {
// FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
@ -678,7 +681,7 @@ fn foo(&self) -> Self::T { String::new() }
assoc: ty::AssocItem,
assoc_substs: &[ty::GenericArg<'tcx>],
ty: Ty<'tcx>,
msg: &str,
msg: impl Fn() -> String,
) -> bool {
let tcx = self.tcx;
@ -693,7 +696,7 @@ fn foo(&self) -> Self::T { String::new() }
let item_args = self.format_generic_args(assoc_substs);
(span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(tcx), item_args, ty))
};
diag.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect);
diag.span_suggestion_verbose(span, msg(), sugg, MaybeIncorrect);
return true;
}
false

View file

@ -39,7 +39,7 @@ impl AddToDiagnostic for OverruledAttributeSub {
diag.span_label(span, fluent::lint_node_source);
if let Some(rationale) = reason {
#[allow(rustc::untranslatable_diagnostic)]
diag.note(rationale.as_str());
diag.note(rationale.to_string());
}
}
OverruledAttributeSub::CommandLineSource => {

View file

@ -1527,7 +1527,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
// check for #[must_use = "..."]
if let Some(note) = self.note {
diag.note(note.as_str());
diag.note(note.to_string());
}
if let Some(sugg) = self.suggestion {
diag.subdiagnostic(sugg);

View file

@ -251,7 +251,7 @@ pub fn explain_lint_level_source(
}
LintLevelSource::Node { name: lint_attr_name, span, reason, .. } => {
if let Some(rationale) = reason {
err.note(rationale.as_str());
err.note(rationale.to_string());
}
err.span_note_once(span, "the lint level is defined here");
if lint_attr_name.as_str() != name {

View file

@ -104,7 +104,7 @@ pub fn report_unstable(
suggestion: Option<(Span, String, String, Applicability)>,
is_soft: bool,
span: Span,
soft_handler: impl FnOnce(&'static Lint, Span, &str),
soft_handler: impl FnOnce(&'static Lint, Span, String),
) {
let msg = match reason {
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
@ -112,7 +112,7 @@ pub fn report_unstable(
};
if is_soft {
soft_handler(SOFT_UNSTABLE, span, &msg)
soft_handler(SOFT_UNSTABLE, span, msg)
} else {
let mut err =
feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), msg);
@ -225,7 +225,7 @@ pub fn deprecation_message_and_lint(
pub fn early_report_deprecation(
lint_buffer: &mut LintBuffer,
message: &str,
message: String,
suggestion: Option<Symbol>,
lint: &'static Lint,
span: Span,
@ -241,7 +241,7 @@ pub fn early_report_deprecation(
fn late_report_deprecation(
tcx: TyCtxt<'_>,
message: &str,
message: String,
suggestion: Option<Symbol>,
lint: &'static Lint,
span: Span,
@ -396,7 +396,7 @@ impl<'tcx> TyCtxt<'tcx> {
late_report_deprecation(
self,
&deprecation_message(
deprecation_message(
is_in_effect,
depr_attr.since,
depr_attr.note,
@ -619,7 +619,7 @@ impl<'tcx> TyCtxt<'tcx> {
allow_unstable: AllowUnstable,
unmarked: impl FnOnce(Span, DefId),
) -> bool {
let soft_handler = |lint, span, msg: &_| {
let soft_handler = |lint, span, msg: String| {
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |lint| lint)
};
let eval_result =

View file

@ -732,7 +732,11 @@ impl<'tcx> TyCtxt<'tcx> {
/// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
/// `msg` to ensure it gets used.
#[track_caller]
pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
pub fn mk_re_error_with_message<S: Into<MultiSpan>>(
self,
span: S,
msg: &'static str,
) -> Region<'tcx> {
let reported = self.sess.delay_span_bug(span, msg);
self.mk_re_error(reported)
}
@ -759,7 +763,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
ty: Ty<'tcx>,
span: S,
msg: &str,
msg: &'static str,
) -> Const<'tcx> {
let reported = self.sess.delay_span_bug(span, msg);
self.mk_const(ty::ConstKind::Error(reported), ty)

View file

@ -1,5 +1,6 @@
//! Diagnostics related methods for `Ty`.
use std::borrow::Cow;
use std::ops::ControlFlow;
use crate::ty::{
@ -384,22 +385,18 @@ pub fn suggest_constraining_type_params<'a>(
if suggestions.len() == 1 {
let (span, suggestion, msg) = suggestions.pop().unwrap();
let s;
let msg = match msg {
SuggestChangingConstraintsMessage::RestrictBoundFurther => {
"consider further restricting this bound"
Cow::from("consider further restricting this bound")
}
SuggestChangingConstraintsMessage::RestrictType { ty } => {
s = format!("consider restricting type parameter `{}`", ty);
&s
Cow::from(format!("consider restricting type parameter `{}`", ty))
}
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
s = format!("consider further restricting type parameter `{}`", ty);
&s
Cow::from(format!("consider further restricting type parameter `{}`", ty))
}
SuggestChangingConstraintsMessage::RemovingQSized => {
"consider removing the `?Sized` bound to make the type parameter `Sized`"
Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`")
}
};

View file

@ -23,6 +23,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym, Ident};
use std::borrow::Cow;
use std::mem;
use thin_vec::{thin_vec, ThinVec};
@ -364,7 +365,7 @@ impl<'a> Parser<'a> {
// `let...else if`. Emit the same error that `parse_block()` would,
// but explicitly point out that this pattern is not allowed.
let msg = "conditional `else if` is not supported for `let...else`";
return Err(self.error_block_no_opening_brace_msg(msg));
return Err(self.error_block_no_opening_brace_msg(Cow::from(msg)));
}
let els = self.parse_block()?;
self.check_let_else_init_bool_expr(&init);
@ -438,7 +439,7 @@ impl<'a> Parser<'a> {
fn error_block_no_opening_brace_msg(
&mut self,
msg: &str,
msg: Cow<'static, str>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let sp = self.token.span;
let mut e = self.struct_span_err(sp, msg);
@ -502,7 +503,7 @@ impl<'a> Parser<'a> {
fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
let tok = super::token_descr(&self.token);
let msg = format!("expected `{{`, found {}", tok);
Err(self.error_block_no_opening_brace_msg(&msg))
Err(self.error_block_no_opening_brace_msg(Cow::from(msg)))
}
/// Parses a block. Inner attributes are allowed.

View file

@ -2540,7 +2540,7 @@ fn show_candidates(
err.note(msg);
}
if let Some(note) = (*note).as_deref() {
err.note(note);
err.note(note.to_string());
}
} else {
let (_, descr_first, _, _) = &inaccessible_path_strings[0];

View file

@ -29,6 +29,7 @@ use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use std::borrow::Cow;
use std::iter;
use std::ops::Deref;
@ -1248,7 +1249,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}),
) if followed_by_brace => {
if let Some(sp) = closing_brace {
err.span_label(span, fallback_label);
err.span_label(span, fallback_label.to_string());
err.multipart_suggestion(
"surround the struct literal with parentheses",
vec![
@ -1320,7 +1321,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
);
}
_ => {
err.span_label(span, fallback_label);
err.span_label(span, fallback_label.to_string());
}
}
};
@ -1333,7 +1334,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}))
| PathSource::Struct,
) => {
err.span_label(span, fallback_label);
err.span_label(span, fallback_label.to_string());
err.span_suggestion_verbose(
span.shrink_to_hi(),
"use `!` to invoke the macro",
@ -1345,7 +1346,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}
(Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
err.span_label(span, fallback_label);
err.span_label(span, fallback_label.to_string());
}
(Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
err.span_label(span, "type aliases cannot be used as traits");
@ -1513,7 +1514,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
);
}
(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }, _) if ns == ValueNS => {
err.span_label(span, fallback_label);
err.span_label(span, fallback_label.to_string());
err.note("can't use `Self` as a constructor, you must use the implemented struct");
}
(Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), _) if ns == ValueNS => {
@ -2243,7 +2244,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
&self,
err: &mut Diagnostic,
name: Option<&str>,
suggest: impl Fn(&mut Diagnostic, bool, Span, &str, String) -> bool,
suggest: impl Fn(&mut Diagnostic, bool, Span, Cow<'static, str>, String) -> bool,
) {
let mut suggest_note = true;
for rib in self.lifetime_ribs.iter().rev() {
@ -2288,22 +2289,23 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
(span, sugg)
};
if higher_ranked {
let message = format!(
let message = Cow::from(format!(
"consider making the {} lifetime-generic with a new `{}` lifetime",
kind.descr(),
name.unwrap_or("'a"),
);
should_continue = suggest(err, true, span, &message, sugg);
));
should_continue = suggest(err, true, span, message, sugg);
err.note_once(
"for more information on higher-ranked polymorphism, visit \
https://doc.rust-lang.org/nomicon/hrtb.html",
);
} else if let Some(name) = name {
let message = format!("consider introducing lifetime `{}` here", name);
should_continue = suggest(err, false, span, &message, sugg);
let message =
Cow::from(format!("consider introducing lifetime `{}` here", name));
should_continue = suggest(err, false, span, message, sugg);
} else {
let message = "consider introducing a named lifetime parameter";
should_continue = suggest(err, false, span, &message, sugg);
let message = Cow::from("consider introducing a named lifetime parameter");
should_continue = suggest(err, false, span, message, sugg);
}
}
LifetimeRibKind::Item => break,

View file

@ -827,7 +827,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if !is_allowed(feature) && !allowed_by_implication {
let lint_buffer = &mut self.lint_buffer;
let soft_handler =
|lint, span, msg: &_| lint_buffer.buffer_lint(lint, node_id, span, msg);
|lint, span, msg: String| lint_buffer.buffer_lint(lint, node_id, span, msg);
stability::report_unstable(
self.tcx.sess,
feature,
@ -846,7 +846,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path);
stability::early_report_deprecation(
&mut self.lint_buffer,
&message,
message,
depr.suggestion,
lint,
span,

View file

@ -123,7 +123,7 @@ pub fn feature_err_issue(
/// Construct a future incompatibility diagnostic for a feature gate.
///
/// This diagnostic is only a warning and *does not cause compilation to fail*.
pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &str) {
pub fn feature_warn(sess: &ParseSess, feature: Symbol, span: Span, explain: &'static str) {
feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
}
@ -140,7 +140,7 @@ pub fn feature_warn_issue(
feature: Symbol,
span: Span,
issue: GateIssue,
explain: &str,
explain: &'static str,
) {
let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);

View file

@ -10,7 +10,6 @@
use core::fmt::Display;
use rustc_data_structures::base_n;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::DiagnosticMessage;
use rustc_hir as hir;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
use rustc_middle::ty::{
@ -534,10 +533,7 @@ fn encode_ty<'tcx>(
tcx.sess
.struct_span_err(
cfi_encoding.span,
DiagnosticMessage::Str(format!(
"invalid `cfi_encoding` for `{:?}`",
ty.kind()
)),
format!("invalid `cfi_encoding` for `{:?}`", ty.kind()),
)
.emit();
}
@ -589,10 +585,7 @@ fn encode_ty<'tcx>(
tcx.sess
.struct_span_err(
cfi_encoding.span,
DiagnosticMessage::Str(format!(
"invalid `cfi_encoding` for `{:?}`",
ty.kind()
)),
format!("invalid `cfi_encoding` for `{:?}`", ty.kind()),
)
.emit();
}

View file

@ -42,6 +42,7 @@ use rustc_session::Limit;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::symbol::sym;
use rustc_span::{ExpnKind, Span, DUMMY_SP};
use std::borrow::Cow;
use std::fmt;
use std::iter;
use std::ops::ControlFlow;
@ -1602,7 +1603,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}),
) => Some((
ty.span,
with_forced_trimmed_paths!(format!(
with_forced_trimmed_paths!(Cow::from(format!(
"type mismatch resolving `{}`",
self.resolve_vars_if_possible(predicate)
.print(FmtPrinter::new_with_limit(
@ -1612,7 +1613,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
))
.unwrap()
.into_buffer()
)),
))),
)),
_ => None,
}

View file

@ -38,6 +38,7 @@ use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
use rustc_target::spec::abi;
use std::borrow::Cow;
use std::iter;
use std::ops::Deref;
@ -186,7 +187,12 @@ pub trait TypeErrCtxtExt<'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool;
fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Option<Symbol>;
fn get_closure_name(
&self,
def_id: DefId,
err: &mut Diagnostic,
msg: Cow<'static, str>,
) -> Option<Symbol>;
fn suggest_fn_call(
&self,
@ -857,7 +863,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
/// Given a closure's `DefId`, return the given name of the closure.
///
/// This doesn't account for reassignments, but it's only used for suggestions.
fn get_closure_name(&self, def_id: DefId, err: &mut Diagnostic, msg: &str) -> Option<Symbol> {
fn get_closure_name(
&self,
def_id: DefId,
err: &mut Diagnostic,
msg: Cow<'static, str>,
) -> Option<Symbol> {
let get_name = |err: &mut Diagnostic, kind: &hir::PatKind<'_>| -> Option<Symbol> {
// Get the local name of this closure. This can be inaccurate because
// of the possibility of reassignment, but this should be good enough.
@ -934,17 +945,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let msg = match def_id_or_name {
DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
DefKind::Ctor(CtorOf::Struct, _) => {
"use parentheses to construct this tuple struct".to_string()
Cow::from("use parentheses to construct this tuple struct")
}
DefKind::Ctor(CtorOf::Variant, _) => {
"use parentheses to construct this tuple variant".to_string()
Cow::from("use parentheses to construct this tuple variant")
}
kind => format!(
kind => Cow::from(format!(
"use parentheses to call this {}",
self.tcx.def_kind_descr(kind, def_id)
),
)),
},
DefIdOrName::Name(name) => format!("use parentheses to call this {name}"),
DefIdOrName::Name(name) => Cow::from(format!("use parentheses to call this {name}")),
};
let args = inputs
@ -979,7 +990,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
..
})) => {
err.span_label(*fn_decl_span, "consider calling this closure");
let Some(name) = self.get_closure_name(def_id, err, &msg) else {
let Some(name) = self.get_closure_name(def_id, err, msg.clone()) else {
return false;
};
name.to_string()
@ -1341,7 +1352,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.note(msg);
} else {
err.message =
vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
vec![(rustc_errors::DiagnosticMessage::from(msg), Style::NoStyle)];
}
err.span_label(
span,
@ -2958,7 +2969,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
for ty in bound_tys.skip_binder() {
with_forced_trimmed_paths!(write!(msg, "`{}`, ", ty).unwrap());
}
err.note(msg.trim_end_matches(", "))
err.note(msg.trim_end_matches(", ").to_string())
}
ty::GeneratorWitnessMIR(def_id, substs) => {
use std::fmt::Write;
@ -2972,7 +2983,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let ty = bty.subst(tcx, substs);
write!(msg, "`{}`, ", ty).unwrap();
}
err.note(msg.trim_end_matches(", "))
err.note(msg.trim_end_matches(", ").to_string())
}
ty::Generator(def_id, _, _) => {
let sp = self.tcx.def_span(def_id);

View file

@ -41,7 +41,12 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
/// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
/// trait aliases.
pub fn label_with_exp_info(&self, diag: &mut Diagnostic, top_label: &str, use_desc: &str) {
pub fn label_with_exp_info(
&self,
diag: &mut Diagnostic,
top_label: &'static str,
use_desc: &str,
) {
diag.span_label(self.top().1, top_label);
if self.path.len() > 1 {
for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {