Skip to content

Commit 70e04bd

Browse files
committed
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`
2 parents dc0943d + 781111e commit 70e04bd

File tree

45 files changed

+308
-287
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+308
-287
lines changed

compiler/rustc_builtin_macros/src/compile_error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub fn expand_compile_error<'cx>(
1818
reason = "diagnostic message is specified by user"
1919
)]
2020
#[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
21-
cx.span_err(sp, var.as_str());
21+
cx.span_err(sp, var.to_string());
2222

2323
DummyResult::any(sp)
2424
}

compiler/rustc_builtin_macros/src/errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
377377
rustc::untranslatable_diagnostic,
378378
reason = "cannot translate user-provided messages"
379379
)]
380-
handler.struct_diagnostic(msg.as_str())
380+
handler.struct_diagnostic(msg.to_string())
381381
} else {
382382
handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
383383
};

compiler/rustc_codegen_ssa/src/back/link.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ fn link_natively<'a>(
893893
linker_path: &linker_path,
894894
exit_status: prog.status,
895895
command: &cmd,
896-
escaped_output: &escaped_output,
896+
escaped_output,
897897
};
898898
sess.diagnostic().emit_err(err);
899899
// If MSVC's `link.exe` was expected but the return code

compiler/rustc_codegen_ssa/src/back/write.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1800,7 +1800,7 @@ impl SharedEmitterMain {
18001800
handler.emit_diagnostic(&mut d);
18011801
}
18021802
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
1803-
let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
1803+
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
18041804

18051805
let mut err = match level {
18061806
Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(),

compiler/rustc_codegen_ssa/src/errors.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ pub struct LinkingFailed<'a> {
336336
pub linker_path: &'a PathBuf,
337337
pub exit_status: ExitStatus,
338338
pub command: &'a Command,
339-
pub escaped_output: &'a str,
339+
pub escaped_output: String,
340340
}
341341

342342
impl IntoDiagnostic<'_> for LinkingFailed<'_> {
@@ -345,11 +345,13 @@ impl IntoDiagnostic<'_> for LinkingFailed<'_> {
345345
diag.set_arg("linker_path", format!("{}", self.linker_path.display()));
346346
diag.set_arg("exit_status", format!("{}", self.exit_status));
347347

348-
diag.note(format!("{:?}", self.command)).note(self.escaped_output);
348+
let contains_undefined_ref = self.escaped_output.contains("undefined reference to");
349+
350+
diag.note(format!("{:?}", self.command)).note(self.escaped_output.to_string());
349351

350352
// Trying to match an error from OS linkers
351353
// which by now we have no way to translate.
352-
if self.escaped_output.contains("undefined reference to") {
354+
if contains_undefined_ref {
353355
diag.note(fluent::codegen_ssa_extern_funcs_not_found)
354356
.note(fluent::codegen_ssa_specify_libraries_to_link)
355357
.note(fluent::codegen_ssa_use_cargo_directive);

compiler/rustc_driver_impl/src/lib.rs

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

compiler/rustc_error_messages/src/lib.rs

+14-18
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,7 @@ type FluentId = Cow<'static, str>;
263263
#[rustc_diagnostic_item = "SubdiagnosticMessage"]
264264
pub enum SubdiagnosticMessage {
265265
/// Non-translatable diagnostic message.
266-
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
267-
Str(String),
266+
Str(Cow<'static, str>),
268267
/// Translatable message which has already been translated eagerly.
269268
///
270269
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
@@ -275,8 +274,7 @@ pub enum SubdiagnosticMessage {
275274
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
276275
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
277276
/// stores messages which have been translated eagerly.
278-
// FIXME(#100717): can a `Cow<'static, str>` be used here?
279-
Eager(String),
277+
Eager(Cow<'static, str>),
280278
/// Identifier of a Fluent message. Instances of this variant are generated by the
281279
/// `Subdiagnostic` derive.
282280
FluentIdentifier(FluentId),
@@ -290,17 +288,17 @@ pub enum SubdiagnosticMessage {
290288

291289
impl From<String> for SubdiagnosticMessage {
292290
fn from(s: String) -> Self {
293-
SubdiagnosticMessage::Str(s)
291+
SubdiagnosticMessage::Str(Cow::Owned(s))
294292
}
295293
}
296-
impl<'a> From<&'a str> for SubdiagnosticMessage {
297-
fn from(s: &'a str) -> Self {
298-
SubdiagnosticMessage::Str(s.to_string())
294+
impl From<&'static str> for SubdiagnosticMessage {
295+
fn from(s: &'static str) -> Self {
296+
SubdiagnosticMessage::Str(Cow::Borrowed(s))
299297
}
300298
}
301299
impl From<Cow<'static, str>> for SubdiagnosticMessage {
302300
fn from(s: Cow<'static, str>) -> Self {
303-
SubdiagnosticMessage::Str(s.to_string())
301+
SubdiagnosticMessage::Str(s)
304302
}
305303
}
306304

@@ -312,8 +310,7 @@ impl From<Cow<'static, str>> for SubdiagnosticMessage {
312310
#[rustc_diagnostic_item = "DiagnosticMessage"]
313311
pub enum DiagnosticMessage {
314312
/// Non-translatable diagnostic message.
315-
// FIXME(#100717): can a `Cow<'static, str>` be used here?
316-
Str(String),
313+
Str(Cow<'static, str>),
317314
/// Translatable message which has already been translated eagerly.
318315
///
319316
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
@@ -324,8 +321,7 @@ pub enum DiagnosticMessage {
324321
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
325322
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
326323
/// stores messages which have been translated eagerly.
327-
// FIXME(#100717): can a `Cow<'static, str>` be used here?
328-
Eager(String),
324+
Eager(Cow<'static, str>),
329325
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
330326
/// message.
331327
///
@@ -363,17 +359,17 @@ impl DiagnosticMessage {
363359

364360
impl From<String> for DiagnosticMessage {
365361
fn from(s: String) -> Self {
366-
DiagnosticMessage::Str(s)
362+
DiagnosticMessage::Str(Cow::Owned(s))
367363
}
368364
}
369-
impl<'a> From<&'a str> for DiagnosticMessage {
370-
fn from(s: &'a str) -> Self {
371-
DiagnosticMessage::Str(s.to_string())
365+
impl From<&'static str> for DiagnosticMessage {
366+
fn from(s: &'static str) -> Self {
367+
DiagnosticMessage::Str(Cow::Borrowed(s))
372368
}
373369
}
374370
impl From<Cow<'static, str>> for DiagnosticMessage {
375371
fn from(s: Cow<'static, str>) -> Self {
376-
DiagnosticMessage::Str(s.to_string())
372+
DiagnosticMessage::Str(s)
377373
}
378374
}
379375

compiler/rustc_errors/src/diagnostic.rs

+10-14
Original file line numberDiff line numberDiff line change
@@ -352,14 +352,9 @@ impl Diagnostic {
352352

353353
/// Labels all the given spans with the provided label.
354354
/// See [`Self::span_label()`] for more information.
355-
pub fn span_labels(
356-
&mut self,
357-
spans: impl IntoIterator<Item = Span>,
358-
label: impl AsRef<str>,
359-
) -> &mut Self {
360-
let label = label.as_ref();
355+
pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
361356
for span in spans {
362-
self.span_label(span, label);
357+
self.span_label(span, label.to_string());
363358
}
364359
self
365360
}
@@ -394,17 +389,18 @@ impl Diagnostic {
394389
expected: DiagnosticStyledString,
395390
found: DiagnosticStyledString,
396391
) -> &mut Self {
397-
let mut msg: Vec<_> = vec![("required when trying to coerce from type `", Style::NoStyle)];
392+
let mut msg: Vec<_> =
393+
vec![(Cow::from("required when trying to coerce from type `"), Style::NoStyle)];
398394
msg.extend(expected.0.iter().map(|x| match *x {
399-
StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
400-
StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
395+
StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle),
396+
StringPart::Highlighted(ref s) => (Cow::from(s.clone()), Style::Highlight),
401397
}));
402-
msg.push(("` to type '", Style::NoStyle));
398+
msg.push((Cow::from("` to type '"), Style::NoStyle));
403399
msg.extend(found.0.iter().map(|x| match *x {
404-
StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
405-
StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
400+
StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle),
401+
StringPart::Highlighted(ref s) => (Cow::from(s.clone()), Style::Highlight),
406402
}));
407-
msg.push(("`", Style::NoStyle));
403+
msg.push((Cow::from("`"), Style::NoStyle));
408404

409405
// For now, just attach these as notes
410406
self.highlighted_note(msg);

compiler/rustc_errors/src/diagnostic_builder.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
558558
}
559559

560560
// Take the `Diagnostic` by replacing it with a dummy.
561-
let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::Str("".to_string()));
561+
let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::from(""));
562562
let diagnostic = std::mem::replace(&mut *self.inner.diagnostic, dummy);
563563

564564
// Disable the ICE on `Drop`.
@@ -627,7 +627,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
627627
pub fn span_labels(
628628
&mut self,
629629
spans: impl IntoIterator<Item = Span>,
630-
label: impl AsRef<str>,
630+
label: &str,
631631
) -> &mut Self);
632632

633633
forward!(pub fn note_expected_found(
@@ -781,8 +781,8 @@ impl Drop for DiagnosticBuilderInner<'_> {
781781
if !panicking() {
782782
handler.emit_diagnostic(&mut Diagnostic::new(
783783
Level::Bug,
784-
DiagnosticMessage::Str(
785-
"the following error was constructed but not emitted".to_string(),
784+
DiagnosticMessage::from(
785+
"the following error was constructed but not emitted",
786786
),
787787
));
788788
handler.emit_diagnostic(&mut self.diagnostic);

compiler/rustc_errors/src/emitter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ pub trait Emitter: Translate {
367367

368368
children.push(SubDiagnostic {
369369
level: Level::Note,
370-
message: vec![(DiagnosticMessage::Str(msg), Style::NoStyle)],
370+
message: vec![(DiagnosticMessage::from(msg), Style::NoStyle)],
371371
span: MultiSpan::new(),
372372
render_span: None,
373373
});

compiler/rustc_errors/src/lib.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ impl Handler {
628628
message: DiagnosticMessage,
629629
args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
630630
) -> SubdiagnosticMessage {
631-
SubdiagnosticMessage::Eager(self.eagerly_translate_to_string(message, args))
631+
SubdiagnosticMessage::Eager(Cow::from(self.eagerly_translate_to_string(message, args)))
632632
}
633633

634634
/// Translate `message` eagerly with `args` to `String`.
@@ -1450,14 +1450,14 @@ impl HandlerInner {
14501450
self.emit_stashed_diagnostics();
14511451

14521452
let warnings = match self.deduplicated_warn_count {
1453-
0 => String::new(),
1454-
1 => "1 warning emitted".to_string(),
1455-
count => format!("{count} warnings emitted"),
1453+
0 => Cow::from(""),
1454+
1 => Cow::from("1 warning emitted"),
1455+
count => Cow::from(format!("{count} warnings emitted")),
14561456
};
14571457
let errors = match self.deduplicated_err_count {
1458-
0 => String::new(),
1459-
1 => "aborting due to previous error".to_string(),
1460-
count => format!("aborting due to {count} previous errors"),
1458+
0 => Cow::from(""),
1459+
1 => Cow::from("aborting due to previous error"),
1460+
count => Cow::from(format!("aborting due to {count} previous errors")),
14611461
};
14621462
if self.treat_err_as_bug() {
14631463
return;

compiler/rustc_expand/src/base.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ impl<'a> ExtCtxt<'a> {
11541154
// Fixme: does this result in errors?
11551155
self.expansions.clear();
11561156
}
1157-
pub fn bug(&self, msg: &str) -> ! {
1157+
pub fn bug(&self, msg: &'static str) -> ! {
11581158
self.sess.parse_sess.span_diagnostic.bug(msg);
11591159
}
11601160
pub fn trace_macros(&self) -> bool {
@@ -1224,7 +1224,7 @@ pub fn resolve_path(
12241224
pub fn expr_to_spanned_string<'a>(
12251225
cx: &'a mut ExtCtxt<'_>,
12261226
expr: P<ast::Expr>,
1227-
err_msg: &str,
1227+
err_msg: &'static str,
12281228
) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a, ErrorGuaranteed>, bool)>> {
12291229
// Perform eager expansion on the expression.
12301230
// We want to be able to handle e.g., `concat!("foo", "bar")`.
@@ -1262,7 +1262,7 @@ pub fn expr_to_spanned_string<'a>(
12621262
pub fn expr_to_string(
12631263
cx: &mut ExtCtxt<'_>,
12641264
expr: P<ast::Expr>,
1265-
err_msg: &str,
1265+
err_msg: &'static str,
12661266
) -> Option<(Symbol, ast::StrStyle)> {
12671267
expr_to_spanned_string(cx, expr, err_msg)
12681268
.map_err(|err| {

compiler/rustc_expand/src/mbe/diagnostics.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
170170
}
171171
Error(err_sp, msg) => {
172172
let span = err_sp.substitute_dummy(self.root_span);
173-
self.cx.struct_span_err(span, msg.as_str()).emit();
173+
self.cx.struct_span_err(span, msg.clone()).emit();
174174
self.result = Some(DummyResult::any(span));
175175
}
176176
ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)),
@@ -222,7 +222,7 @@ pub(super) fn emit_frag_parse_err(
222222
{
223223
let msg = &e.message[0];
224224
e.message[0] = (
225-
DiagnosticMessage::Str(format!(
225+
DiagnosticMessage::from(format!(
226226
"macro expansion ends with an incomplete expression: {}",
227227
message.replace(", found `<eof>`", ""),
228228
)),
@@ -313,9 +313,9 @@ pub(super) fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: S
313313

314314
/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For
315315
/// other tokens, this is "unexpected token...".
316-
pub(super) fn parse_failure_msg(tok: &Token) -> String {
316+
pub(super) fn parse_failure_msg(tok: &Token) -> Cow<'static, str> {
317317
match tok.kind {
318-
token::Eof => "unexpected end of macro invocation".to_string(),
319-
_ => format!("no rules expected the token `{}`", pprust::token_to_string(tok),),
318+
token::Eof => Cow::from("unexpected end of macro invocation"),
319+
_ => Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok))),
320320
}
321321
}

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
2525
use rustc_trait_selection::traits::{
2626
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
2727
};
28+
use std::borrow::Cow;
2829
use std::iter;
2930

3031
/// 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>(
684685
&cause,
685686
hir.get_if_local(impl_m.def_id)
686687
.and_then(|node| node.fn_decl())
687-
.map(|decl| (decl.output.span(), "return type in trait".to_owned())),
688+
.map(|decl| (decl.output.span(), Cow::from("return type in trait"))),
688689
Some(infer::ValuePairs::Terms(ExpectedFound {
689690
expected: trait_return_ty.into(),
690691
found: impl_return_ty.into(),
@@ -963,7 +964,7 @@ fn report_trait_method_mismatch<'tcx>(
963964
infcx.err_ctxt().note_type_err(
964965
&mut diag,
965966
&cause,
966-
trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
967+
trait_err_span.map(|sp| (sp, Cow::from("type in trait"))),
967968
Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })),
968969
terr,
969970
false,
@@ -1731,7 +1732,7 @@ pub(super) fn compare_impl_const_raw(
17311732
infcx.err_ctxt().note_type_err(
17321733
&mut diag,
17331734
&cause,
1734-
trait_c_span.map(|span| (span, "type in trait".to_owned())),
1735+
trait_c_span.map(|span| (span, Cow::from("type in trait"))),
17351736
Some(infer::ValuePairs::Terms(ExpectedFound {
17361737
expected: trait_ty.into(),
17371738
found: impl_ty.into(),

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,11 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
121121
if has_safe_attr != is_in_list {
122122
tcx.sess.struct_span_err(
123123
tcx.def_span(intrinsic_id),
124-
DiagnosticMessage::Str(format!(
125-
"intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
126-
tcx.item_name(intrinsic_id)
127-
))).emit();
124+
DiagnosticMessage::from(format!(
125+
"intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
126+
tcx.item_name(intrinsic_id)
127+
)
128+
)).emit();
128129
}
129130

130131
is_in_list

compiler/rustc_hir_typeck/src/generator_interior/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
122122

123123
self.fcx
124124
.need_type_info_err_in_generator(self.kind, span, unresolved_term)
125-
.span_note(yield_data.span, &*note)
125+
.span_note(yield_data.span, note)
126126
.emit();
127127
}
128128
} else {
@@ -686,7 +686,7 @@ fn check_must_not_suspend_def(
686686
// Add optional reason note
687687
if let Some(note) = attr.value_str() {
688688
// FIXME(guswynn): consider formatting this better
689-
lint.span_note(data.source_span, note.as_str());
689+
lint.span_note(data.source_span, note.to_string());
690690
}
691691

692692
// Add some quick suggestions on what to do

0 commit comments

Comments
 (0)