1
Fork 0

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 1c53407e8c
commit 781111ef35
45 changed files with 308 additions and 287 deletions

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) {