mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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:
parent
1c53407e8c
commit
781111ef35
@ -18,7 +18,7 @@ pub fn expand_compile_error<'cx>(
|
|||||||
reason = "diagnostic message is specified by user"
|
reason = "diagnostic message is specified by user"
|
||||||
)]
|
)]
|
||||||
#[expect(rustc::untranslatable_diagnostic, 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)
|
DummyResult::any(sp)
|
||||||
}
|
}
|
||||||
|
@ -377,7 +377,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
|
|||||||
rustc::untranslatable_diagnostic,
|
rustc::untranslatable_diagnostic,
|
||||||
reason = "cannot translate user-provided messages"
|
reason = "cannot translate user-provided messages"
|
||||||
)]
|
)]
|
||||||
handler.struct_diagnostic(msg.as_str())
|
handler.struct_diagnostic(msg.to_string())
|
||||||
} else {
|
} else {
|
||||||
handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
|
handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
|
||||||
};
|
};
|
||||||
|
@ -893,7 +893,7 @@ fn link_natively<'a>(
|
|||||||
linker_path: &linker_path,
|
linker_path: &linker_path,
|
||||||
exit_status: prog.status,
|
exit_status: prog.status,
|
||||||
command: &cmd,
|
command: &cmd,
|
||||||
escaped_output: &escaped_output,
|
escaped_output,
|
||||||
};
|
};
|
||||||
sess.diagnostic().emit_err(err);
|
sess.diagnostic().emit_err(err);
|
||||||
// If MSVC's `link.exe` was expected but the return code
|
// If MSVC's `link.exe` was expected but the return code
|
||||||
|
@ -1800,7 +1800,7 @@ impl SharedEmitterMain {
|
|||||||
handler.emit_diagnostic(&mut d);
|
handler.emit_diagnostic(&mut d);
|
||||||
}
|
}
|
||||||
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
|
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 {
|
let mut err = match level {
|
||||||
Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(),
|
Level::Error { lint: false } => sess.struct_err(msg).forget_guarantee(),
|
||||||
|
@ -336,7 +336,7 @@ pub struct LinkingFailed<'a> {
|
|||||||
pub linker_path: &'a PathBuf,
|
pub linker_path: &'a PathBuf,
|
||||||
pub exit_status: ExitStatus,
|
pub exit_status: ExitStatus,
|
||||||
pub command: &'a Command,
|
pub command: &'a Command,
|
||||||
pub escaped_output: &'a str,
|
pub escaped_output: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoDiagnostic<'_> for LinkingFailed<'_> {
|
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("linker_path", format!("{}", self.linker_path.display()));
|
||||||
diag.set_arg("exit_status", format!("{}", self.exit_status));
|
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
|
// Trying to match an error from OS linkers
|
||||||
// which by now we have no way to translate.
|
// 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)
|
diag.note(fluent::codegen_ssa_extern_funcs_not_found)
|
||||||
.note(fluent::codegen_ssa_specify_libraries_to_link)
|
.note(fluent::codegen_ssa_specify_libraries_to_link)
|
||||||
.note(fluent::codegen_ssa_use_cargo_directive);
|
.note(fluent::codegen_ssa_use_cargo_directive);
|
||||||
|
@ -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 let Some(msg) = info.payload().downcast_ref::<String>() {
|
||||||
if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
|
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
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -263,8 +263,7 @@ type FluentId = Cow<'static, str>;
|
|||||||
#[rustc_diagnostic_item = "SubdiagnosticMessage"]
|
#[rustc_diagnostic_item = "SubdiagnosticMessage"]
|
||||||
pub enum SubdiagnosticMessage {
|
pub enum SubdiagnosticMessage {
|
||||||
/// Non-translatable diagnostic message.
|
/// Non-translatable diagnostic message.
|
||||||
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
|
Str(Cow<'static, str>),
|
||||||
Str(String),
|
|
||||||
/// Translatable message which has already been translated eagerly.
|
/// Translatable message which has already been translated eagerly.
|
||||||
///
|
///
|
||||||
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
|
/// 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
|
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
|
||||||
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
|
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
|
||||||
/// stores messages which have been translated eagerly.
|
/// stores messages which have been translated eagerly.
|
||||||
// FIXME(#100717): can a `Cow<'static, str>` be used here?
|
Eager(Cow<'static, str>),
|
||||||
Eager(String),
|
|
||||||
/// Identifier of a Fluent message. Instances of this variant are generated by the
|
/// Identifier of a Fluent message. Instances of this variant are generated by the
|
||||||
/// `Subdiagnostic` derive.
|
/// `Subdiagnostic` derive.
|
||||||
FluentIdentifier(FluentId),
|
FluentIdentifier(FluentId),
|
||||||
@ -290,17 +288,17 @@ pub enum SubdiagnosticMessage {
|
|||||||
|
|
||||||
impl From<String> for SubdiagnosticMessage {
|
impl From<String> for SubdiagnosticMessage {
|
||||||
fn from(s: String) -> Self {
|
fn from(s: String) -> Self {
|
||||||
SubdiagnosticMessage::Str(s)
|
SubdiagnosticMessage::Str(Cow::Owned(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> From<&'a str> for SubdiagnosticMessage {
|
impl From<&'static str> for SubdiagnosticMessage {
|
||||||
fn from(s: &'a str) -> Self {
|
fn from(s: &'static str) -> Self {
|
||||||
SubdiagnosticMessage::Str(s.to_string())
|
SubdiagnosticMessage::Str(Cow::Borrowed(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<Cow<'static, str>> for SubdiagnosticMessage {
|
impl From<Cow<'static, str>> for SubdiagnosticMessage {
|
||||||
fn from(s: Cow<'static, str>) -> Self {
|
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"]
|
#[rustc_diagnostic_item = "DiagnosticMessage"]
|
||||||
pub enum DiagnosticMessage {
|
pub enum DiagnosticMessage {
|
||||||
/// Non-translatable diagnostic message.
|
/// Non-translatable diagnostic message.
|
||||||
// FIXME(#100717): can a `Cow<'static, str>` be used here?
|
Str(Cow<'static, str>),
|
||||||
Str(String),
|
|
||||||
/// Translatable message which has already been translated eagerly.
|
/// Translatable message which has already been translated eagerly.
|
||||||
///
|
///
|
||||||
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
|
/// 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
|
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
|
||||||
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
|
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
|
||||||
/// stores messages which have been translated eagerly.
|
/// stores messages which have been translated eagerly.
|
||||||
// FIXME(#100717): can a `Cow<'static, str>` be used here?
|
Eager(Cow<'static, str>),
|
||||||
Eager(String),
|
|
||||||
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
|
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
|
||||||
/// message.
|
/// message.
|
||||||
///
|
///
|
||||||
@ -363,17 +359,17 @@ impl DiagnosticMessage {
|
|||||||
|
|
||||||
impl From<String> for DiagnosticMessage {
|
impl From<String> for DiagnosticMessage {
|
||||||
fn from(s: String) -> Self {
|
fn from(s: String) -> Self {
|
||||||
DiagnosticMessage::Str(s)
|
DiagnosticMessage::Str(Cow::Owned(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> From<&'a str> for DiagnosticMessage {
|
impl From<&'static str> for DiagnosticMessage {
|
||||||
fn from(s: &'a str) -> Self {
|
fn from(s: &'static str) -> Self {
|
||||||
DiagnosticMessage::Str(s.to_string())
|
DiagnosticMessage::Str(Cow::Borrowed(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<Cow<'static, str>> for DiagnosticMessage {
|
impl From<Cow<'static, str>> for DiagnosticMessage {
|
||||||
fn from(s: Cow<'static, str>) -> Self {
|
fn from(s: Cow<'static, str>) -> Self {
|
||||||
DiagnosticMessage::Str(s.to_string())
|
DiagnosticMessage::Str(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,14 +352,9 @@ impl Diagnostic {
|
|||||||
|
|
||||||
/// Labels all the given spans with the provided label.
|
/// Labels all the given spans with the provided label.
|
||||||
/// See [`Self::span_label()`] for more information.
|
/// See [`Self::span_label()`] for more information.
|
||||||
pub fn span_labels(
|
pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
|
||||||
&mut self,
|
|
||||||
spans: impl IntoIterator<Item = Span>,
|
|
||||||
label: impl AsRef<str>,
|
|
||||||
) -> &mut Self {
|
|
||||||
let label = label.as_ref();
|
|
||||||
for span in spans {
|
for span in spans {
|
||||||
self.span_label(span, label);
|
self.span_label(span, label.to_string());
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -394,17 +389,18 @@ impl Diagnostic {
|
|||||||
expected: DiagnosticStyledString,
|
expected: DiagnosticStyledString,
|
||||||
found: DiagnosticStyledString,
|
found: DiagnosticStyledString,
|
||||||
) -> &mut Self {
|
) -> &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 {
|
msg.extend(expected.0.iter().map(|x| match *x {
|
||||||
StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
|
StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle),
|
||||||
StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
|
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 {
|
msg.extend(found.0.iter().map(|x| match *x {
|
||||||
StringPart::Normal(ref s) => (s.as_str(), Style::NoStyle),
|
StringPart::Normal(ref s) => (Cow::from(s.clone()), Style::NoStyle),
|
||||||
StringPart::Highlighted(ref s) => (s.as_str(), Style::Highlight),
|
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
|
// For now, just attach these as notes
|
||||||
self.highlighted_note(msg);
|
self.highlighted_note(msg);
|
||||||
|
@ -558,7 +558,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Take the `Diagnostic` by replacing it with a dummy.
|
// 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);
|
let diagnostic = std::mem::replace(&mut *self.inner.diagnostic, dummy);
|
||||||
|
|
||||||
// Disable the ICE on `Drop`.
|
// Disable the ICE on `Drop`.
|
||||||
@ -627,7 +627,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
|||||||
pub fn span_labels(
|
pub fn span_labels(
|
||||||
&mut self,
|
&mut self,
|
||||||
spans: impl IntoIterator<Item = Span>,
|
spans: impl IntoIterator<Item = Span>,
|
||||||
label: impl AsRef<str>,
|
label: &str,
|
||||||
) -> &mut Self);
|
) -> &mut Self);
|
||||||
|
|
||||||
forward!(pub fn note_expected_found(
|
forward!(pub fn note_expected_found(
|
||||||
@ -781,8 +781,8 @@ impl Drop for DiagnosticBuilderInner<'_> {
|
|||||||
if !panicking() {
|
if !panicking() {
|
||||||
handler.emit_diagnostic(&mut Diagnostic::new(
|
handler.emit_diagnostic(&mut Diagnostic::new(
|
||||||
Level::Bug,
|
Level::Bug,
|
||||||
DiagnosticMessage::Str(
|
DiagnosticMessage::from(
|
||||||
"the following error was constructed but not emitted".to_string(),
|
"the following error was constructed but not emitted",
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
handler.emit_diagnostic(&mut self.diagnostic);
|
handler.emit_diagnostic(&mut self.diagnostic);
|
||||||
|
@ -367,7 +367,7 @@ pub trait Emitter: Translate {
|
|||||||
|
|
||||||
children.push(SubDiagnostic {
|
children.push(SubDiagnostic {
|
||||||
level: Level::Note,
|
level: Level::Note,
|
||||||
message: vec![(DiagnosticMessage::Str(msg), Style::NoStyle)],
|
message: vec![(DiagnosticMessage::from(msg), Style::NoStyle)],
|
||||||
span: MultiSpan::new(),
|
span: MultiSpan::new(),
|
||||||
render_span: None,
|
render_span: None,
|
||||||
});
|
});
|
||||||
|
@ -628,7 +628,7 @@ impl Handler {
|
|||||||
message: DiagnosticMessage,
|
message: DiagnosticMessage,
|
||||||
args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
|
args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
|
||||||
) -> SubdiagnosticMessage {
|
) -> 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`.
|
/// Translate `message` eagerly with `args` to `String`.
|
||||||
@ -1450,14 +1450,14 @@ impl HandlerInner {
|
|||||||
self.emit_stashed_diagnostics();
|
self.emit_stashed_diagnostics();
|
||||||
|
|
||||||
let warnings = match self.deduplicated_warn_count {
|
let warnings = match self.deduplicated_warn_count {
|
||||||
0 => String::new(),
|
0 => Cow::from(""),
|
||||||
1 => "1 warning emitted".to_string(),
|
1 => Cow::from("1 warning emitted"),
|
||||||
count => format!("{count} warnings emitted"),
|
count => Cow::from(format!("{count} warnings emitted")),
|
||||||
};
|
};
|
||||||
let errors = match self.deduplicated_err_count {
|
let errors = match self.deduplicated_err_count {
|
||||||
0 => String::new(),
|
0 => Cow::from(""),
|
||||||
1 => "aborting due to previous error".to_string(),
|
1 => Cow::from("aborting due to previous error"),
|
||||||
count => format!("aborting due to {count} previous errors"),
|
count => Cow::from(format!("aborting due to {count} previous errors")),
|
||||||
};
|
};
|
||||||
if self.treat_err_as_bug() {
|
if self.treat_err_as_bug() {
|
||||||
return;
|
return;
|
||||||
|
@ -1154,7 +1154,7 @@ impl<'a> ExtCtxt<'a> {
|
|||||||
// Fixme: does this result in errors?
|
// Fixme: does this result in errors?
|
||||||
self.expansions.clear();
|
self.expansions.clear();
|
||||||
}
|
}
|
||||||
pub fn bug(&self, msg: &str) -> ! {
|
pub fn bug(&self, msg: &'static str) -> ! {
|
||||||
self.sess.parse_sess.span_diagnostic.bug(msg);
|
self.sess.parse_sess.span_diagnostic.bug(msg);
|
||||||
}
|
}
|
||||||
pub fn trace_macros(&self) -> bool {
|
pub fn trace_macros(&self) -> bool {
|
||||||
@ -1224,7 +1224,7 @@ pub fn resolve_path(
|
|||||||
pub fn expr_to_spanned_string<'a>(
|
pub fn expr_to_spanned_string<'a>(
|
||||||
cx: &'a mut ExtCtxt<'_>,
|
cx: &'a mut ExtCtxt<'_>,
|
||||||
expr: P<ast::Expr>,
|
expr: P<ast::Expr>,
|
||||||
err_msg: &str,
|
err_msg: &'static str,
|
||||||
) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a, ErrorGuaranteed>, bool)>> {
|
) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a, ErrorGuaranteed>, bool)>> {
|
||||||
// Perform eager expansion on the expression.
|
// Perform eager expansion on the expression.
|
||||||
// We want to be able to handle e.g., `concat!("foo", "bar")`.
|
// 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(
|
pub fn expr_to_string(
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
expr: P<ast::Expr>,
|
expr: P<ast::Expr>,
|
||||||
err_msg: &str,
|
err_msg: &'static str,
|
||||||
) -> Option<(Symbol, ast::StrStyle)> {
|
) -> Option<(Symbol, ast::StrStyle)> {
|
||||||
expr_to_spanned_string(cx, expr, err_msg)
|
expr_to_spanned_string(cx, expr, err_msg)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
|
@ -170,7 +170,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
|
|||||||
}
|
}
|
||||||
Error(err_sp, msg) => {
|
Error(err_sp, msg) => {
|
||||||
let span = err_sp.substitute_dummy(self.root_span);
|
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));
|
self.result = Some(DummyResult::any(span));
|
||||||
}
|
}
|
||||||
ErrorReported(_) => self.result = Some(DummyResult::any(self.root_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];
|
let msg = &e.message[0];
|
||||||
e.message[0] = (
|
e.message[0] = (
|
||||||
DiagnosticMessage::Str(format!(
|
DiagnosticMessage::from(format!(
|
||||||
"macro expansion ends with an incomplete expression: {}",
|
"macro expansion ends with an incomplete expression: {}",
|
||||||
message.replace(", found `<eof>`", ""),
|
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
|
/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For
|
||||||
/// other tokens, this is "unexpected token...".
|
/// 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 {
|
match tok.kind {
|
||||||
token::Eof => "unexpected end of macro invocation".to_string(),
|
token::Eof => Cow::from("unexpected end of macro invocation"),
|
||||||
_ => format!("no rules expected the token `{}`", pprust::token_to_string(tok),),
|
_ => Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
|||||||
use rustc_trait_selection::traits::{
|
use rustc_trait_selection::traits::{
|
||||||
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
|
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
|
||||||
};
|
};
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
/// Checks that a method from an impl conforms to the signature of
|
/// 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,
|
&cause,
|
||||||
hir.get_if_local(impl_m.def_id)
|
hir.get_if_local(impl_m.def_id)
|
||||||
.and_then(|node| node.fn_decl())
|
.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 {
|
Some(infer::ValuePairs::Terms(ExpectedFound {
|
||||||
expected: trait_return_ty.into(),
|
expected: trait_return_ty.into(),
|
||||||
found: impl_return_ty.into(),
|
found: impl_return_ty.into(),
|
||||||
@ -963,7 +964,7 @@ fn report_trait_method_mismatch<'tcx>(
|
|||||||
infcx.err_ctxt().note_type_err(
|
infcx.err_ctxt().note_type_err(
|
||||||
&mut diag,
|
&mut diag,
|
||||||
&cause,
|
&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 })),
|
Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })),
|
||||||
terr,
|
terr,
|
||||||
false,
|
false,
|
||||||
@ -1731,7 +1732,7 @@ pub(super) fn compare_impl_const_raw(
|
|||||||
infcx.err_ctxt().note_type_err(
|
infcx.err_ctxt().note_type_err(
|
||||||
&mut diag,
|
&mut diag,
|
||||||
&cause,
|
&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 {
|
Some(infer::ValuePairs::Terms(ExpectedFound {
|
||||||
expected: trait_ty.into(),
|
expected: trait_ty.into(),
|
||||||
found: impl_ty.into(),
|
found: impl_ty.into(),
|
||||||
|
@ -121,10 +121,11 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
|
|||||||
if has_safe_attr != is_in_list {
|
if has_safe_attr != is_in_list {
|
||||||
tcx.sess.struct_span_err(
|
tcx.sess.struct_span_err(
|
||||||
tcx.def_span(intrinsic_id),
|
tcx.def_span(intrinsic_id),
|
||||||
DiagnosticMessage::Str(format!(
|
DiagnosticMessage::from(format!(
|
||||||
"intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
|
"intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
|
||||||
tcx.item_name(intrinsic_id)
|
tcx.item_name(intrinsic_id)
|
||||||
))).emit();
|
)
|
||||||
|
)).emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
is_in_list
|
is_in_list
|
||||||
|
@ -122,7 +122,7 @@ impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
|||||||
|
|
||||||
self.fcx
|
self.fcx
|
||||||
.need_type_info_err_in_generator(self.kind, span, unresolved_term)
|
.need_type_info_err_in_generator(self.kind, span, unresolved_term)
|
||||||
.span_note(yield_data.span, &*note)
|
.span_note(yield_data.span, note)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -686,7 +686,7 @@ fn check_must_not_suspend_def(
|
|||||||
// Add optional reason note
|
// Add optional reason note
|
||||||
if let Some(note) = attr.value_str() {
|
if let Some(note) = attr.value_str() {
|
||||||
// FIXME(guswynn): consider formatting this better
|
// 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
|
// Add some quick suggestions on what to do
|
||||||
|
@ -76,6 +76,7 @@ use rustc_middle::ty::{
|
|||||||
};
|
};
|
||||||
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
|
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::ops::{ControlFlow, Deref};
|
use std::ops::{ControlFlow, Deref};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::{cmp, fmt, iter};
|
use std::{cmp, fmt, iter};
|
||||||
@ -1470,7 +1471,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
diag: &mut Diagnostic,
|
diag: &mut Diagnostic,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
secondary_span: Option<(Span, String)>,
|
secondary_span: Option<(Span, Cow<'static, str>)>,
|
||||||
mut values: Option<ValuePairs<'tcx>>,
|
mut values: Option<ValuePairs<'tcx>>,
|
||||||
terr: TypeError<'tcx>,
|
terr: TypeError<'tcx>,
|
||||||
swap_secondary_and_primary: bool,
|
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() {
|
if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() {
|
||||||
diag.span_label(span, msg);
|
diag.span_label(span, msg);
|
||||||
} else {
|
} else {
|
||||||
@ -1643,15 +1644,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
..
|
..
|
||||||
})) = values
|
})) = values
|
||||||
{
|
{
|
||||||
format!("expected this to be `{}`", expected)
|
Cow::from(format!("expected this to be `{}`", expected))
|
||||||
} else {
|
} else {
|
||||||
terr.to_string(self.tcx).to_string()
|
terr.to_string(self.tcx)
|
||||||
};
|
};
|
||||||
label_or_note(sp, &terr);
|
label_or_note(sp, terr);
|
||||||
label_or_note(span, &msg);
|
label_or_note(span, msg);
|
||||||
} else {
|
} else {
|
||||||
label_or_note(span, &terr.to_string(self.tcx));
|
label_or_note(span, terr.to_string(self.tcx));
|
||||||
label_or_note(sp, &msg);
|
label_or_note(sp, msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let Some(values) = values
|
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 expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
|
||||||
let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
|
let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
|
||||||
if expected == found {
|
if expected == found {
|
||||||
label_or_note(span, &terr.to_string(self.tcx));
|
label_or_note(span, terr.to_string(self.tcx));
|
||||||
} else {
|
} else {
|
||||||
label_or_note(span, &format!("expected {expected}, found {found}"));
|
label_or_note(span, Cow::from(format!("expected {expected}, found {found}")));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
label_or_note(span, &terr.to_string(self.tcx));
|
label_or_note(span, terr.to_string(self.tcx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) => {
|
(_, 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 `{}`",
|
"consider constraining the associated type `{}` to `{}`",
|
||||||
values.found, values.expected,
|
values.found, values.expected,
|
||||||
);
|
);
|
||||||
if !(self.suggest_constraining_opaque_associated_type(
|
if !(self.suggest_constraining_opaque_associated_type(
|
||||||
diag,
|
diag,
|
||||||
&msg,
|
msg,
|
||||||
proj_ty,
|
proj_ty,
|
||||||
values.expected,
|
values.expected,
|
||||||
) || self.suggest_constraint(
|
) || self.suggest_constraint(
|
||||||
@ -250,7 +250,7 @@ impl<T> Trait<T> for X {
|
|||||||
proj_ty,
|
proj_ty,
|
||||||
values.expected,
|
values.expected,
|
||||||
)) {
|
)) {
|
||||||
diag.help(msg);
|
diag.help(msg());
|
||||||
diag.note(
|
diag.note(
|
||||||
"for more information, visit \
|
"for more information, visit \
|
||||||
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
|
https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
|
||||||
@ -308,7 +308,7 @@ impl<T> Trait<T> for X {
|
|||||||
fn suggest_constraint(
|
fn suggest_constraint(
|
||||||
&self,
|
&self,
|
||||||
diag: &mut Diagnostic,
|
diag: &mut Diagnostic,
|
||||||
msg: &str,
|
msg: impl Fn() -> String,
|
||||||
body_owner_def_id: DefId,
|
body_owner_def_id: DefId,
|
||||||
proj_ty: &ty::AliasTy<'tcx>,
|
proj_ty: &ty::AliasTy<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
@ -340,7 +340,7 @@ impl<T> Trait<T> for X {
|
|||||||
assoc,
|
assoc,
|
||||||
assoc_substs,
|
assoc_substs,
|
||||||
ty,
|
ty,
|
||||||
msg,
|
&msg,
|
||||||
false,
|
false,
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
@ -374,10 +374,12 @@ impl<T> Trait<T> for X {
|
|||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
let msg = format!(
|
let msg = || {
|
||||||
"consider constraining the associated type `{}` to `{}`",
|
format!(
|
||||||
values.expected, values.found
|
"consider constraining the associated type `{}` to `{}`",
|
||||||
);
|
values.expected, values.found
|
||||||
|
)
|
||||||
|
};
|
||||||
let body_owner = tcx.hir().get_if_local(body_owner_def_id);
|
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);
|
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 {
|
if callable_scope {
|
||||||
diag.help(format!(
|
diag.help(format!(
|
||||||
"{} or calling a method that returns `{}`",
|
"{} or calling a method that returns `{}`",
|
||||||
msg, values.expected
|
msg(),
|
||||||
|
values.expected
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
diag.help(msg);
|
diag.help(msg());
|
||||||
}
|
}
|
||||||
diag.note(
|
diag.note(
|
||||||
"for more information, visit \
|
"for more information, visit \
|
||||||
@ -463,7 +466,7 @@ fn foo(&self) -> Self::T { String::new() }
|
|||||||
fn suggest_constraining_opaque_associated_type(
|
fn suggest_constraining_opaque_associated_type(
|
||||||
&self,
|
&self,
|
||||||
diag: &mut Diagnostic,
|
diag: &mut Diagnostic,
|
||||||
msg: &str,
|
msg: impl Fn() -> String,
|
||||||
proj_ty: &ty::AliasTy<'tcx>,
|
proj_ty: &ty::AliasTy<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
@ -635,7 +638,7 @@ fn foo(&self) -> Self::T { String::new() }
|
|||||||
assoc: ty::AssocItem,
|
assoc: ty::AssocItem,
|
||||||
assoc_substs: &[ty::GenericArg<'tcx>],
|
assoc_substs: &[ty::GenericArg<'tcx>],
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
msg: &str,
|
msg: impl Fn() -> String,
|
||||||
is_bound_surely_present: bool,
|
is_bound_surely_present: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
|
// 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: ty::AssocItem,
|
||||||
assoc_substs: &[ty::GenericArg<'tcx>],
|
assoc_substs: &[ty::GenericArg<'tcx>],
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
msg: &str,
|
msg: impl Fn() -> String,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
@ -693,7 +696,7 @@ fn foo(&self) -> Self::T { String::new() }
|
|||||||
let item_args = self.format_generic_args(assoc_substs);
|
let item_args = self.format_generic_args(assoc_substs);
|
||||||
(span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(tcx), item_args, ty))
|
(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;
|
return true;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
@ -39,7 +39,7 @@ impl AddToDiagnostic for OverruledAttributeSub {
|
|||||||
diag.span_label(span, fluent::lint_node_source);
|
diag.span_label(span, fluent::lint_node_source);
|
||||||
if let Some(rationale) = reason {
|
if let Some(rationale) = reason {
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
diag.note(rationale.as_str());
|
diag.note(rationale.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OverruledAttributeSub::CommandLineSource => {
|
OverruledAttributeSub::CommandLineSource => {
|
||||||
|
@ -1527,7 +1527,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
|
|||||||
diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
|
diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
|
||||||
// check for #[must_use = "..."]
|
// check for #[must_use = "..."]
|
||||||
if let Some(note) = self.note {
|
if let Some(note) = self.note {
|
||||||
diag.note(note.as_str());
|
diag.note(note.to_string());
|
||||||
}
|
}
|
||||||
if let Some(sugg) = self.suggestion {
|
if let Some(sugg) = self.suggestion {
|
||||||
diag.subdiagnostic(sugg);
|
diag.subdiagnostic(sugg);
|
||||||
|
@ -251,7 +251,7 @@ pub fn explain_lint_level_source(
|
|||||||
}
|
}
|
||||||
LintLevelSource::Node { name: lint_attr_name, span, reason, .. } => {
|
LintLevelSource::Node { name: lint_attr_name, span, reason, .. } => {
|
||||||
if let Some(rationale) = 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");
|
err.span_note_once(span, "the lint level is defined here");
|
||||||
if lint_attr_name.as_str() != name {
|
if lint_attr_name.as_str() != name {
|
||||||
|
@ -104,7 +104,7 @@ pub fn report_unstable(
|
|||||||
suggestion: Option<(Span, String, String, Applicability)>,
|
suggestion: Option<(Span, String, String, Applicability)>,
|
||||||
is_soft: bool,
|
is_soft: bool,
|
||||||
span: Span,
|
span: Span,
|
||||||
soft_handler: impl FnOnce(&'static Lint, Span, &str),
|
soft_handler: impl FnOnce(&'static Lint, Span, String),
|
||||||
) {
|
) {
|
||||||
let msg = match reason {
|
let msg = match reason {
|
||||||
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
|
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
|
||||||
@ -112,7 +112,7 @@ pub fn report_unstable(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if is_soft {
|
if is_soft {
|
||||||
soft_handler(SOFT_UNSTABLE, span, &msg)
|
soft_handler(SOFT_UNSTABLE, span, msg)
|
||||||
} else {
|
} else {
|
||||||
let mut err =
|
let mut err =
|
||||||
feature_err_issue(&sess.parse_sess, feature, span, GateIssue::Library(issue), msg);
|
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(
|
pub fn early_report_deprecation(
|
||||||
lint_buffer: &mut LintBuffer,
|
lint_buffer: &mut LintBuffer,
|
||||||
message: &str,
|
message: String,
|
||||||
suggestion: Option<Symbol>,
|
suggestion: Option<Symbol>,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -241,7 +241,7 @@ pub fn early_report_deprecation(
|
|||||||
|
|
||||||
fn late_report_deprecation(
|
fn late_report_deprecation(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
message: &str,
|
message: String,
|
||||||
suggestion: Option<Symbol>,
|
suggestion: Option<Symbol>,
|
||||||
lint: &'static Lint,
|
lint: &'static Lint,
|
||||||
span: Span,
|
span: Span,
|
||||||
@ -396,7 +396,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
|
|
||||||
late_report_deprecation(
|
late_report_deprecation(
|
||||||
self,
|
self,
|
||||||
&deprecation_message(
|
deprecation_message(
|
||||||
is_in_effect,
|
is_in_effect,
|
||||||
depr_attr.since,
|
depr_attr.since,
|
||||||
depr_attr.note,
|
depr_attr.note,
|
||||||
@ -619,7 +619,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
allow_unstable: AllowUnstable,
|
allow_unstable: AllowUnstable,
|
||||||
unmarked: impl FnOnce(Span, DefId),
|
unmarked: impl FnOnce(Span, DefId),
|
||||||
) -> bool {
|
) -> 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)
|
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |lint| lint)
|
||||||
};
|
};
|
||||||
let eval_result =
|
let eval_result =
|
||||||
|
@ -732,7 +732,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
/// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
|
/// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
|
||||||
/// `msg` to ensure it gets used.
|
/// `msg` to ensure it gets used.
|
||||||
#[track_caller]
|
#[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);
|
let reported = self.sess.delay_span_bug(span, msg);
|
||||||
self.mk_re_error(reported)
|
self.mk_re_error(reported)
|
||||||
}
|
}
|
||||||
@ -759,7 +763,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
self,
|
self,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
span: S,
|
span: S,
|
||||||
msg: &str,
|
msg: &'static str,
|
||||||
) -> Const<'tcx> {
|
) -> Const<'tcx> {
|
||||||
let reported = self.sess.delay_span_bug(span, msg);
|
let reported = self.sess.delay_span_bug(span, msg);
|
||||||
self.mk_const(ty::ConstKind::Error(reported), ty)
|
self.mk_const(ty::ConstKind::Error(reported), ty)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! Diagnostics related methods for `Ty`.
|
//! Diagnostics related methods for `Ty`.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
@ -384,22 +385,18 @@ pub fn suggest_constraining_type_params<'a>(
|
|||||||
|
|
||||||
if suggestions.len() == 1 {
|
if suggestions.len() == 1 {
|
||||||
let (span, suggestion, msg) = suggestions.pop().unwrap();
|
let (span, suggestion, msg) = suggestions.pop().unwrap();
|
||||||
|
|
||||||
let s;
|
|
||||||
let msg = match msg {
|
let msg = match msg {
|
||||||
SuggestChangingConstraintsMessage::RestrictBoundFurther => {
|
SuggestChangingConstraintsMessage::RestrictBoundFurther => {
|
||||||
"consider further restricting this bound"
|
Cow::from("consider further restricting this bound")
|
||||||
}
|
}
|
||||||
SuggestChangingConstraintsMessage::RestrictType { ty } => {
|
SuggestChangingConstraintsMessage::RestrictType { ty } => {
|
||||||
s = format!("consider restricting type parameter `{}`", ty);
|
Cow::from(format!("consider restricting type parameter `{}`", ty))
|
||||||
&s
|
|
||||||
}
|
}
|
||||||
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
|
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
|
||||||
s = format!("consider further restricting type parameter `{}`", ty);
|
Cow::from(format!("consider further restricting type parameter `{}`", ty))
|
||||||
&s
|
|
||||||
}
|
}
|
||||||
SuggestChangingConstraintsMessage::RemovingQSized => {
|
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`")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
|
|||||||
use rustc_span::source_map::{BytePos, Span};
|
use rustc_span::source_map::{BytePos, Span};
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use thin_vec::{thin_vec, ThinVec};
|
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,
|
// `let...else if`. Emit the same error that `parse_block()` would,
|
||||||
// but explicitly point out that this pattern is not allowed.
|
// but explicitly point out that this pattern is not allowed.
|
||||||
let msg = "conditional `else if` is not supported for `let...else`";
|
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()?;
|
let els = self.parse_block()?;
|
||||||
self.check_let_else_init_bool_expr(&init);
|
self.check_let_else_init_bool_expr(&init);
|
||||||
@ -438,7 +439,7 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
fn error_block_no_opening_brace_msg(
|
fn error_block_no_opening_brace_msg(
|
||||||
&mut self,
|
&mut self,
|
||||||
msg: &str,
|
msg: Cow<'static, str>,
|
||||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||||
let sp = self.token.span;
|
let sp = self.token.span;
|
||||||
let mut e = self.struct_span_err(sp, msg);
|
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> {
|
fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
|
||||||
let tok = super::token_descr(&self.token);
|
let tok = super::token_descr(&self.token);
|
||||||
let msg = format!("expected `{{`, found {}", tok);
|
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.
|
/// Parses a block. Inner attributes are allowed.
|
||||||
|
@ -2540,7 +2540,7 @@ fn show_candidates(
|
|||||||
err.note(msg);
|
err.note(msg);
|
||||||
}
|
}
|
||||||
if let Some(note) = (*note).as_deref() {
|
if let Some(note) = (*note).as_deref() {
|
||||||
err.note(note);
|
err.note(note.to_string());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let (_, descr_first, _, _) = &inaccessible_path_strings[0];
|
let (_, descr_first, _, _) = &inaccessible_path_strings[0];
|
||||||
|
@ -29,6 +29,7 @@ use rustc_span::hygiene::MacroKind;
|
|||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
@ -1248,7 +1249,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||||||
}),
|
}),
|
||||||
) if followed_by_brace => {
|
) if followed_by_brace => {
|
||||||
if let Some(sp) = closing_brace {
|
if let Some(sp) = closing_brace {
|
||||||
err.span_label(span, fallback_label);
|
err.span_label(span, fallback_label.to_string());
|
||||||
err.multipart_suggestion(
|
err.multipart_suggestion(
|
||||||
"surround the struct literal with parentheses",
|
"surround the struct literal with parentheses",
|
||||||
vec![
|
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,
|
| PathSource::Struct,
|
||||||
) => {
|
) => {
|
||||||
err.span_label(span, fallback_label);
|
err.span_label(span, fallback_label.to_string());
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
span.shrink_to_hi(),
|
span.shrink_to_hi(),
|
||||||
"use `!` to invoke the macro",
|
"use `!` to invoke the macro",
|
||||||
@ -1345,7 +1346,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
|
(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(_)) => {
|
(Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
|
||||||
err.span_label(span, "type aliases cannot be used as traits");
|
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 => {
|
(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");
|
err.note("can't use `Self` as a constructor, you must use the implemented struct");
|
||||||
}
|
}
|
||||||
(Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), _) if ns == ValueNS => {
|
(Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), _) if ns == ValueNS => {
|
||||||
@ -2243,7 +2244,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
name: Option<&str>,
|
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;
|
let mut suggest_note = true;
|
||||||
for rib in self.lifetime_ribs.iter().rev() {
|
for rib in self.lifetime_ribs.iter().rev() {
|
||||||
@ -2288,22 +2289,23 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
|||||||
(span, sugg)
|
(span, sugg)
|
||||||
};
|
};
|
||||||
if higher_ranked {
|
if higher_ranked {
|
||||||
let message = format!(
|
let message = Cow::from(format!(
|
||||||
"consider making the {} lifetime-generic with a new `{}` lifetime",
|
"consider making the {} lifetime-generic with a new `{}` lifetime",
|
||||||
kind.descr(),
|
kind.descr(),
|
||||||
name.unwrap_or("'a"),
|
name.unwrap_or("'a"),
|
||||||
);
|
));
|
||||||
should_continue = suggest(err, true, span, &message, sugg);
|
should_continue = suggest(err, true, span, message, sugg);
|
||||||
err.note_once(
|
err.note_once(
|
||||||
"for more information on higher-ranked polymorphism, visit \
|
"for more information on higher-ranked polymorphism, visit \
|
||||||
https://doc.rust-lang.org/nomicon/hrtb.html",
|
https://doc.rust-lang.org/nomicon/hrtb.html",
|
||||||
);
|
);
|
||||||
} else if let Some(name) = name {
|
} else if let Some(name) = name {
|
||||||
let message = format!("consider introducing lifetime `{}` here", name);
|
let message =
|
||||||
should_continue = suggest(err, false, span, &message, sugg);
|
Cow::from(format!("consider introducing lifetime `{}` here", name));
|
||||||
|
should_continue = suggest(err, false, span, message, sugg);
|
||||||
} else {
|
} else {
|
||||||
let message = "consider introducing a named lifetime parameter";
|
let message = Cow::from("consider introducing a named lifetime parameter");
|
||||||
should_continue = suggest(err, false, span, &message, sugg);
|
should_continue = suggest(err, false, span, message, sugg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LifetimeRibKind::Item => break,
|
LifetimeRibKind::Item => break,
|
||||||
|
@ -827,7 +827,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
if !is_allowed(feature) && !allowed_by_implication {
|
if !is_allowed(feature) && !allowed_by_implication {
|
||||||
let lint_buffer = &mut self.lint_buffer;
|
let lint_buffer = &mut self.lint_buffer;
|
||||||
let soft_handler =
|
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(
|
stability::report_unstable(
|
||||||
self.tcx.sess,
|
self.tcx.sess,
|
||||||
feature,
|
feature,
|
||||||
@ -846,7 +846,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path);
|
let (message, lint) = stability::deprecation_message_and_lint(depr, "macro", &path);
|
||||||
stability::early_report_deprecation(
|
stability::early_report_deprecation(
|
||||||
&mut self.lint_buffer,
|
&mut self.lint_buffer,
|
||||||
&message,
|
message,
|
||||||
depr.suggestion,
|
depr.suggestion,
|
||||||
lint,
|
lint,
|
||||||
span,
|
span,
|
||||||
|
@ -123,7 +123,7 @@ pub fn feature_err_issue(
|
|||||||
/// Construct a future incompatibility diagnostic for a feature gate.
|
/// Construct a future incompatibility diagnostic for a feature gate.
|
||||||
///
|
///
|
||||||
/// This diagnostic is only a warning and *does not cause compilation to fail*.
|
/// 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);
|
feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ pub fn feature_warn_issue(
|
|||||||
feature: Symbol,
|
feature: Symbol,
|
||||||
span: Span,
|
span: Span,
|
||||||
issue: GateIssue,
|
issue: GateIssue,
|
||||||
explain: &str,
|
explain: &'static str,
|
||||||
) {
|
) {
|
||||||
let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
|
let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
|
||||||
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
|
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
use core::fmt::Display;
|
use core::fmt::Display;
|
||||||
use rustc_data_structures::base_n;
|
use rustc_data_structures::base_n;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::DiagnosticMessage;
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
@ -534,10 +533,7 @@ fn encode_ty<'tcx>(
|
|||||||
tcx.sess
|
tcx.sess
|
||||||
.struct_span_err(
|
.struct_span_err(
|
||||||
cfi_encoding.span,
|
cfi_encoding.span,
|
||||||
DiagnosticMessage::Str(format!(
|
format!("invalid `cfi_encoding` for `{:?}`", ty.kind()),
|
||||||
"invalid `cfi_encoding` for `{:?}`",
|
|
||||||
ty.kind()
|
|
||||||
)),
|
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
@ -589,10 +585,7 @@ fn encode_ty<'tcx>(
|
|||||||
tcx.sess
|
tcx.sess
|
||||||
.struct_span_err(
|
.struct_span_err(
|
||||||
cfi_encoding.span,
|
cfi_encoding.span,
|
||||||
DiagnosticMessage::Str(format!(
|
format!("invalid `cfi_encoding` for `{:?}`", ty.kind()),
|
||||||
"invalid `cfi_encoding` for `{:?}`",
|
|
||||||
ty.kind()
|
|
||||||
)),
|
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ use rustc_session::Limit;
|
|||||||
use rustc_span::def_id::LOCAL_CRATE;
|
use rustc_span::def_id::LOCAL_CRATE;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::{ExpnKind, Span, DUMMY_SP};
|
use rustc_span::{ExpnKind, Span, DUMMY_SP};
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
@ -1602,7 +1603,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
}),
|
}),
|
||||||
) => Some((
|
) => Some((
|
||||||
ty.span,
|
ty.span,
|
||||||
with_forced_trimmed_paths!(format!(
|
with_forced_trimmed_paths!(Cow::from(format!(
|
||||||
"type mismatch resolving `{}`",
|
"type mismatch resolving `{}`",
|
||||||
self.resolve_vars_if_possible(predicate)
|
self.resolve_vars_if_possible(predicate)
|
||||||
.print(FmtPrinter::new_with_limit(
|
.print(FmtPrinter::new_with_limit(
|
||||||
@ -1612,7 +1613,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
))
|
))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_buffer()
|
.into_buffer()
|
||||||
)),
|
))),
|
||||||
)),
|
)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ use rustc_span::def_id::LocalDefId;
|
|||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
|
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
@ -186,7 +187,12 @@ pub trait TypeErrCtxtExt<'tcx> {
|
|||||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||||
) -> bool;
|
) -> 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(
|
fn suggest_fn_call(
|
||||||
&self,
|
&self,
|
||||||
@ -857,7 +863,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
/// Given a closure's `DefId`, return the given name of the closure.
|
/// 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.
|
/// 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> {
|
let get_name = |err: &mut Diagnostic, kind: &hir::PatKind<'_>| -> Option<Symbol> {
|
||||||
// Get the local name of this closure. This can be inaccurate because
|
// Get the local name of this closure. This can be inaccurate because
|
||||||
// of the possibility of reassignment, but this should be good enough.
|
// 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 {
|
let msg = match def_id_or_name {
|
||||||
DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
|
DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
|
||||||
DefKind::Ctor(CtorOf::Struct, _) => {
|
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, _) => {
|
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 {}",
|
"use parentheses to call this {}",
|
||||||
self.tcx.def_kind_descr(kind, def_id)
|
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
|
let args = inputs
|
||||||
@ -979,7 +990,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
..
|
..
|
||||||
})) => {
|
})) => {
|
||||||
err.span_label(*fn_decl_span, "consider calling this closure");
|
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;
|
return false;
|
||||||
};
|
};
|
||||||
name.to_string()
|
name.to_string()
|
||||||
@ -1341,7 +1352,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
err.note(msg);
|
err.note(msg);
|
||||||
} else {
|
} else {
|
||||||
err.message =
|
err.message =
|
||||||
vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
|
vec![(rustc_errors::DiagnosticMessage::from(msg), Style::NoStyle)];
|
||||||
}
|
}
|
||||||
err.span_label(
|
err.span_label(
|
||||||
span,
|
span,
|
||||||
@ -2958,7 +2969,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
for ty in bound_tys.skip_binder() {
|
for ty in bound_tys.skip_binder() {
|
||||||
with_forced_trimmed_paths!(write!(msg, "`{}`, ", ty).unwrap());
|
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) => {
|
ty::GeneratorWitnessMIR(def_id, substs) => {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
@ -2972,7 +2983,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
let ty = bty.subst(tcx, substs);
|
let ty = bty.subst(tcx, substs);
|
||||||
write!(msg, "`{}`, ", ty).unwrap();
|
write!(msg, "`{}`, ", ty).unwrap();
|
||||||
}
|
}
|
||||||
err.note(msg.trim_end_matches(", "))
|
err.note(msg.trim_end_matches(", ").to_string())
|
||||||
}
|
}
|
||||||
ty::Generator(def_id, _, _) => {
|
ty::Generator(def_id, _, _) => {
|
||||||
let sp = self.tcx.def_span(def_id);
|
let sp = self.tcx.def_span(def_id);
|
||||||
|
@ -41,7 +41,12 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
|
|||||||
|
|
||||||
/// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
|
/// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
|
||||||
/// trait aliases.
|
/// 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);
|
diag.span_label(self.top().1, top_label);
|
||||||
if self.path.len() > 1 {
|
if self.path.len() > 1 {
|
||||||
for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
|
for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
|
||||||
|
@ -781,7 +781,7 @@ impl<'tcx> ExtraInfo<'tcx> {
|
|||||||
ExtraInfo { def_id, sp, tcx }
|
ExtraInfo { def_id, sp, tcx }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_invalid_codeblock_attr(&self, msg: String, help: &str) {
|
fn error_invalid_codeblock_attr(&self, msg: String, help: &'static str) {
|
||||||
if let Some(def_id) = self.def_id.as_local() {
|
if let Some(def_id) = self.def_id.as_local() {
|
||||||
self.tcx.struct_span_lint_hir(
|
self.tcx.struct_span_lint_hir(
|
||||||
crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
|
crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
|
||||||
|
@ -842,7 +842,7 @@ impl PreprocessingError {
|
|||||||
match self {
|
match self {
|
||||||
PreprocessingError::MultipleAnchors => report_multiple_anchors(cx, diag_info),
|
PreprocessingError::MultipleAnchors => report_multiple_anchors(cx, diag_info),
|
||||||
PreprocessingError::Disambiguator(range, msg) => {
|
PreprocessingError::Disambiguator(range, msg) => {
|
||||||
disambiguator_error(cx, diag_info, range.clone(), msg.as_str())
|
disambiguator_error(cx, diag_info, range.clone(), msg.clone())
|
||||||
}
|
}
|
||||||
PreprocessingError::MalformedGenerics(err, path_str) => {
|
PreprocessingError::MalformedGenerics(err, path_str) => {
|
||||||
report_malformed_generics(cx, diag_info, *err, path_str)
|
report_malformed_generics(cx, diag_info, *err, path_str)
|
||||||
|
@ -20,19 +20,20 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) {
|
|||||||
};
|
};
|
||||||
let dox = item.doc_value();
|
let dox = item.doc_value();
|
||||||
if !dox.is_empty() {
|
if !dox.is_empty() {
|
||||||
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
|
let report_diag =
|
||||||
let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
|
|cx: &DocContext<'_>, msg: &'static str, url: &str, range: Range<usize>| {
|
||||||
.unwrap_or_else(|| item.attr_span(cx.tcx));
|
let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
|
||||||
cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| {
|
.unwrap_or_else(|| item.attr_span(cx.tcx));
|
||||||
lint.note("bare URLs are not automatically turned into clickable links")
|
cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| {
|
||||||
.span_suggestion(
|
lint.note("bare URLs are not automatically turned into clickable links")
|
||||||
sp,
|
.span_suggestion(
|
||||||
"use an automatic link instead",
|
sp,
|
||||||
format!("<{}>", url),
|
"use an automatic link instead",
|
||||||
Applicability::MachineApplicable,
|
format!("<{}>", url),
|
||||||
)
|
Applicability::MachineApplicable,
|
||||||
});
|
)
|
||||||
};
|
});
|
||||||
|
};
|
||||||
|
|
||||||
let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
|
let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
|
||||||
|
|
||||||
@ -72,7 +73,7 @@ fn find_raw_urls(
|
|||||||
cx: &DocContext<'_>,
|
cx: &DocContext<'_>,
|
||||||
text: &str,
|
text: &str,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
f: &impl Fn(&DocContext<'_>, &str, &str, Range<usize>),
|
f: &impl Fn(&DocContext<'_>, &'static str, &str, Range<usize>),
|
||||||
) {
|
) {
|
||||||
trace!("looking for raw urls in {}", text);
|
trace!("looking for raw urls in {}", text);
|
||||||
// For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
|
// For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
|
||||||
|
@ -17,90 +17,96 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
|
|||||||
else { return };
|
else { return };
|
||||||
let dox = item.doc_value();
|
let dox = item.doc_value();
|
||||||
if !dox.is_empty() {
|
if !dox.is_empty() {
|
||||||
let report_diag = |msg: &str, range: &Range<usize>, is_open_tag: bool| {
|
let report_diag = |msg: String, range: &Range<usize>, is_open_tag: bool| {
|
||||||
let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs) {
|
let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs) {
|
||||||
Some(sp) => sp,
|
Some(sp) => sp,
|
||||||
None => item.attr_span(tcx),
|
None => item.attr_span(tcx),
|
||||||
};
|
};
|
||||||
tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, msg, |lint| {
|
tcx.struct_span_lint_hir(
|
||||||
use rustc_lint_defs::Applicability;
|
crate::lint::INVALID_HTML_TAGS,
|
||||||
// If a tag looks like `<this>`, it might actually be a generic.
|
hir_id,
|
||||||
// We don't try to detect stuff `<like, this>` because that's not valid HTML,
|
sp,
|
||||||
// and we don't try to detect stuff `<like this>` because that's not valid Rust.
|
msg.to_string(),
|
||||||
let mut generics_end = range.end;
|
|lint| {
|
||||||
if let Some(Some(mut generics_start)) = (is_open_tag
|
use rustc_lint_defs::Applicability;
|
||||||
&& dox[..generics_end].ends_with('>'))
|
// If a tag looks like `<this>`, it might actually be a generic.
|
||||||
.then(|| extract_path_backwards(&dox, range.start))
|
// We don't try to detect stuff `<like, this>` because that's not valid HTML,
|
||||||
{
|
// and we don't try to detect stuff `<like this>` because that's not valid Rust.
|
||||||
while generics_start != 0
|
let mut generics_end = range.end;
|
||||||
&& generics_end < dox.len()
|
if let Some(Some(mut generics_start)) = (is_open_tag
|
||||||
&& dox.as_bytes()[generics_start - 1] == b'<'
|
&& dox[..generics_end].ends_with('>'))
|
||||||
&& dox.as_bytes()[generics_end] == b'>'
|
.then(|| extract_path_backwards(&dox, range.start))
|
||||||
{
|
{
|
||||||
generics_end += 1;
|
while generics_start != 0
|
||||||
generics_start -= 1;
|
&& generics_end < dox.len()
|
||||||
if let Some(new_start) = extract_path_backwards(&dox, generics_start) {
|
&& dox.as_bytes()[generics_start - 1] == b'<'
|
||||||
generics_start = new_start;
|
&& dox.as_bytes()[generics_end] == b'>'
|
||||||
|
{
|
||||||
|
generics_end += 1;
|
||||||
|
generics_start -= 1;
|
||||||
|
if let Some(new_start) = extract_path_backwards(&dox, generics_start) {
|
||||||
|
generics_start = new_start;
|
||||||
|
}
|
||||||
|
if let Some(new_end) = extract_path_forward(&dox, generics_end) {
|
||||||
|
generics_end = new_end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(new_end) = extract_path_forward(&dox, generics_end) {
|
if let Some(new_end) = extract_path_forward(&dox, generics_end) {
|
||||||
generics_end = new_end;
|
generics_end = new_end;
|
||||||
}
|
}
|
||||||
|
let generics_sp = match source_span_for_markdown_range(
|
||||||
|
tcx,
|
||||||
|
&dox,
|
||||||
|
&(generics_start..generics_end),
|
||||||
|
&item.attrs,
|
||||||
|
) {
|
||||||
|
Some(sp) => sp,
|
||||||
|
None => item.attr_span(tcx),
|
||||||
|
};
|
||||||
|
// Sometimes, we only extract part of a path. For example, consider this:
|
||||||
|
//
|
||||||
|
// <[u32] as IntoIter<u32>>::Item
|
||||||
|
// ^^^^^ unclosed HTML tag `u32`
|
||||||
|
//
|
||||||
|
// We don't have any code for parsing fully-qualified trait paths.
|
||||||
|
// In theory, we could add it, but doing it correctly would require
|
||||||
|
// parsing the entire path grammar, which is problematic because of
|
||||||
|
// overlap between the path grammar and Markdown.
|
||||||
|
//
|
||||||
|
// The example above shows that ambiguity. Is `[u32]` intended to be an
|
||||||
|
// intra-doc link to the u32 primitive, or is it intended to be a slice?
|
||||||
|
//
|
||||||
|
// If the below conditional were removed, we would suggest this, which is
|
||||||
|
// not what the user probably wants.
|
||||||
|
//
|
||||||
|
// <[u32] as `IntoIter<u32>`>::Item
|
||||||
|
//
|
||||||
|
// We know that the user actually wants to wrap the whole thing in a code
|
||||||
|
// block, but the only reason we know that is because `u32` does not, in
|
||||||
|
// fact, implement IntoIter. If the example looks like this:
|
||||||
|
//
|
||||||
|
// <[Vec<i32>] as IntoIter<i32>::Item
|
||||||
|
//
|
||||||
|
// The ideal fix would be significantly different.
|
||||||
|
if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
|
||||||
|
|| (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
|
||||||
|
{
|
||||||
|
return lint;
|
||||||
|
}
|
||||||
|
// multipart form is chosen here because ``Vec<i32>`` would be confusing.
|
||||||
|
lint.multipart_suggestion(
|
||||||
|
"try marking as source code",
|
||||||
|
vec![
|
||||||
|
(generics_sp.shrink_to_lo(), String::from("`")),
|
||||||
|
(generics_sp.shrink_to_hi(), String::from("`")),
|
||||||
|
],
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if let Some(new_end) = extract_path_forward(&dox, generics_end) {
|
|
||||||
generics_end = new_end;
|
|
||||||
}
|
|
||||||
let generics_sp = match source_span_for_markdown_range(
|
|
||||||
tcx,
|
|
||||||
&dox,
|
|
||||||
&(generics_start..generics_end),
|
|
||||||
&item.attrs,
|
|
||||||
) {
|
|
||||||
Some(sp) => sp,
|
|
||||||
None => item.attr_span(tcx),
|
|
||||||
};
|
|
||||||
// Sometimes, we only extract part of a path. For example, consider this:
|
|
||||||
//
|
|
||||||
// <[u32] as IntoIter<u32>>::Item
|
|
||||||
// ^^^^^ unclosed HTML tag `u32`
|
|
||||||
//
|
|
||||||
// We don't have any code for parsing fully-qualified trait paths.
|
|
||||||
// In theory, we could add it, but doing it correctly would require
|
|
||||||
// parsing the entire path grammar, which is problematic because of
|
|
||||||
// overlap between the path grammar and Markdown.
|
|
||||||
//
|
|
||||||
// The example above shows that ambiguity. Is `[u32]` intended to be an
|
|
||||||
// intra-doc link to the u32 primitive, or is it intended to be a slice?
|
|
||||||
//
|
|
||||||
// If the below conditional were removed, we would suggest this, which is
|
|
||||||
// not what the user probably wants.
|
|
||||||
//
|
|
||||||
// <[u32] as `IntoIter<u32>`>::Item
|
|
||||||
//
|
|
||||||
// We know that the user actually wants to wrap the whole thing in a code
|
|
||||||
// block, but the only reason we know that is because `u32` does not, in
|
|
||||||
// fact, implement IntoIter. If the example looks like this:
|
|
||||||
//
|
|
||||||
// <[Vec<i32>] as IntoIter<i32>::Item
|
|
||||||
//
|
|
||||||
// The ideal fix would be significantly different.
|
|
||||||
if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
|
|
||||||
|| (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
|
|
||||||
{
|
|
||||||
return lint;
|
|
||||||
}
|
|
||||||
// multipart form is chosen here because ``Vec<i32>`` would be confusing.
|
|
||||||
lint.multipart_suggestion(
|
|
||||||
"try marking as source code",
|
|
||||||
vec![
|
|
||||||
(generics_sp.shrink_to_lo(), String::from("`")),
|
|
||||||
(generics_sp.shrink_to_hi(), String::from("`")),
|
|
||||||
],
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
lint
|
lint
|
||||||
});
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut tags = Vec::new();
|
let mut tags = Vec::new();
|
||||||
@ -147,11 +153,11 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
|
|||||||
let t = t.to_lowercase();
|
let t = t.to_lowercase();
|
||||||
!ALLOWED_UNCLOSED.contains(&t.as_str())
|
!ALLOWED_UNCLOSED.contains(&t.as_str())
|
||||||
}) {
|
}) {
|
||||||
report_diag(&format!("unclosed HTML tag `{}`", tag), range, true);
|
report_diag(format!("unclosed HTML tag `{}`", tag), range, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(range) = is_in_comment {
|
if let Some(range) = is_in_comment {
|
||||||
report_diag("Unclosed HTML comment", &range, false);
|
report_diag("Unclosed HTML comment".to_string(), &range, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,7 +171,7 @@ fn drop_tag(
|
|||||||
tags: &mut Vec<(String, Range<usize>)>,
|
tags: &mut Vec<(String, Range<usize>)>,
|
||||||
tag_name: String,
|
tag_name: String,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
f: &impl Fn(&str, &Range<usize>, bool),
|
f: &impl Fn(String, &Range<usize>, bool),
|
||||||
) {
|
) {
|
||||||
let tag_name_low = tag_name.to_lowercase();
|
let tag_name_low = tag_name.to_lowercase();
|
||||||
if let Some(pos) = tags.iter().rposition(|(t, _)| t.to_lowercase() == tag_name_low) {
|
if let Some(pos) = tags.iter().rposition(|(t, _)| t.to_lowercase() == tag_name_low) {
|
||||||
@ -186,14 +192,14 @@ fn drop_tag(
|
|||||||
// `tags` is used as a queue, meaning that everything after `pos` is included inside it.
|
// `tags` is used as a queue, meaning that everything after `pos` is included inside it.
|
||||||
// So `<h2><h3></h2>` will look like `["h2", "h3"]`. So when closing `h2`, we will still
|
// So `<h2><h3></h2>` will look like `["h2", "h3"]`. So when closing `h2`, we will still
|
||||||
// have `h3`, meaning the tag wasn't closed as it should have.
|
// have `h3`, meaning the tag wasn't closed as it should have.
|
||||||
f(&format!("unclosed HTML tag `{}`", last_tag_name), &last_tag_span, true);
|
f(format!("unclosed HTML tag `{}`", last_tag_name), &last_tag_span, true);
|
||||||
}
|
}
|
||||||
// Remove the `tag_name` that was originally closed
|
// Remove the `tag_name` that was originally closed
|
||||||
tags.pop();
|
tags.pop();
|
||||||
} else {
|
} else {
|
||||||
// It can happen for example in this case: `<h2></script></h2>` (the `h2` tag isn't required
|
// It can happen for example in this case: `<h2></script></h2>` (the `h2` tag isn't required
|
||||||
// but it helps for the visualization).
|
// but it helps for the visualization).
|
||||||
f(&format!("unopened HTML tag `{}`", tag_name), &range, false);
|
f(format!("unopened HTML tag `{}`", tag_name), &range, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +267,7 @@ fn extract_html_tag(
|
|||||||
range: &Range<usize>,
|
range: &Range<usize>,
|
||||||
start_pos: usize,
|
start_pos: usize,
|
||||||
iter: &mut Peekable<CharIndices<'_>>,
|
iter: &mut Peekable<CharIndices<'_>>,
|
||||||
f: &impl Fn(&str, &Range<usize>, bool),
|
f: &impl Fn(String, &Range<usize>, bool),
|
||||||
) {
|
) {
|
||||||
let mut tag_name = String::new();
|
let mut tag_name = String::new();
|
||||||
let mut is_closing = false;
|
let mut is_closing = false;
|
||||||
@ -347,7 +353,7 @@ fn extract_html_tag(
|
|||||||
if let Some(quote_pos) = quote_pos {
|
if let Some(quote_pos) = quote_pos {
|
||||||
let qr = Range { start: quote_pos, end: quote_pos };
|
let qr = Range { start: quote_pos, end: quote_pos };
|
||||||
f(
|
f(
|
||||||
&format!("unclosed quoted HTML attribute on tag `{}`", tag_name),
|
format!("unclosed quoted HTML attribute on tag `{}`", tag_name),
|
||||||
&qr,
|
&qr,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
@ -360,7 +366,7 @@ fn extract_html_tag(
|
|||||||
at == "svg" || at == "math"
|
at == "svg" || at == "math"
|
||||||
});
|
});
|
||||||
if !valid {
|
if !valid {
|
||||||
f(&format!("invalid self-closing HTML tag `{}`", tag_name), &r, false);
|
f(format!("invalid self-closing HTML tag `{}`", tag_name), &r, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tags.push((tag_name, r));
|
tags.push((tag_name, r));
|
||||||
@ -378,7 +384,7 @@ fn extract_tags(
|
|||||||
text: &str,
|
text: &str,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
is_in_comment: &mut Option<Range<usize>>,
|
is_in_comment: &mut Option<Range<usize>>,
|
||||||
f: &impl Fn(&str, &Range<usize>, bool),
|
f: &impl Fn(String, &Range<usize>, bool),
|
||||||
) {
|
) {
|
||||||
let mut iter = text.char_indices().peekable();
|
let mut iter = text.char_indices().peekable();
|
||||||
|
|
||||||
|
@ -373,7 +373,7 @@ fn suggest_insertion(
|
|||||||
lint: &mut DiagnosticBuilder<'_, ()>,
|
lint: &mut DiagnosticBuilder<'_, ()>,
|
||||||
insert_index: usize,
|
insert_index: usize,
|
||||||
suggestion: char,
|
suggestion: char,
|
||||||
message: &str,
|
message: &'static str,
|
||||||
) {
|
) {
|
||||||
/// Maximum bytes of context to show around the insertion.
|
/// Maximum bytes of context to show around the insertion.
|
||||||
const CONTEXT_MAX_LEN: usize = 80;
|
const CONTEXT_MAX_LEN: usize = 80;
|
||||||
|
@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
|
|||||||
|
|
||||||
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`");
|
||||||
|
@ -26,7 +26,6 @@ use rustc_span::{sym, Span};
|
|||||||
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 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
|||||||
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 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
|||||||
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,
|
||||||
);
|
);
|
||||||
|
@ -163,7 +163,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
|
|||||||
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,
|
||||||
);
|
);
|
||||||
|
@ -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 @@ where
|
|||||||
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 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -741,7 +741,7 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
|
|||||||
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 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
|
|||||||
})
|
})
|
||||||
.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 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.span_suggestion(remove_span, msg, "", applicability);
|
self.span_suggestion(remove_span, msg.to_string(), "", applicability);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ pub fn report_error<'tcx, 'mir>(
|
|||||||
msg.insert(0, e.to_string());
|
msg.insert(0, e.to_string());
|
||||||
report_msg(
|
report_msg(
|
||||||
DiagLevel::Error,
|
DiagLevel::Error,
|
||||||
&if let Some(title) = title { format!("{title}: {}", msg[0]) } else { msg[0].clone() },
|
if let Some(title) = title { format!("{title}: {}", msg[0]) } else { msg[0].clone() },
|
||||||
msg,
|
msg,
|
||||||
vec![],
|
vec![],
|
||||||
helps,
|
helps,
|
||||||
@ -359,7 +359,7 @@ pub fn report_leaks<'mir, 'tcx>(
|
|||||||
any_pruned |= pruned;
|
any_pruned |= pruned;
|
||||||
report_msg(
|
report_msg(
|
||||||
DiagLevel::Error,
|
DiagLevel::Error,
|
||||||
&format!(
|
format!(
|
||||||
"memory leaked: {id:?} ({}, size: {:?}, align: {:?}), allocated here:",
|
"memory leaked: {id:?} ({}, size: {:?}, align: {:?}), allocated here:",
|
||||||
kind,
|
kind,
|
||||||
alloc.size().bytes(),
|
alloc.size().bytes(),
|
||||||
@ -386,7 +386,7 @@ pub fn report_leaks<'mir, 'tcx>(
|
|||||||
/// additional `span_label` or `note` call.
|
/// additional `span_label` or `note` call.
|
||||||
pub fn report_msg<'tcx>(
|
pub fn report_msg<'tcx>(
|
||||||
diag_level: DiagLevel,
|
diag_level: DiagLevel,
|
||||||
title: &str,
|
title: String,
|
||||||
span_msg: Vec<String>,
|
span_msg: Vec<String>,
|
||||||
notes: Vec<(Option<SpanData>, String)>,
|
notes: Vec<(Option<SpanData>, String)>,
|
||||||
helps: Vec<(Option<SpanData>, String)>,
|
helps: Vec<(Option<SpanData>, String)>,
|
||||||
@ -463,15 +463,16 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
|||||||
let (stacktrace, _was_pruned) = prune_stacktrace(stacktrace, self);
|
let (stacktrace, _was_pruned) = prune_stacktrace(stacktrace, self);
|
||||||
|
|
||||||
let (title, diag_level) = match &e {
|
let (title, diag_level) = match &e {
|
||||||
RejectedIsolatedOp(_) => ("operation rejected by isolation", DiagLevel::Warning),
|
RejectedIsolatedOp(_) =>
|
||||||
Int2Ptr { .. } => ("integer-to-pointer cast", DiagLevel::Warning),
|
("operation rejected by isolation".to_string(), DiagLevel::Warning),
|
||||||
|
Int2Ptr { .. } => ("integer-to-pointer cast".to_string(), DiagLevel::Warning),
|
||||||
CreatedPointerTag(..)
|
CreatedPointerTag(..)
|
||||||
| PoppedPointerTag(..)
|
| PoppedPointerTag(..)
|
||||||
| CreatedCallId(..)
|
| CreatedCallId(..)
|
||||||
| CreatedAlloc(..)
|
| CreatedAlloc(..)
|
||||||
| FreedAlloc(..)
|
| FreedAlloc(..)
|
||||||
| ProgressReport { .. }
|
| ProgressReport { .. }
|
||||||
| WeakMemoryOutdatedLoad => ("tracking was triggered", DiagLevel::Note),
|
| WeakMemoryOutdatedLoad => ("tracking was triggered".to_string(), DiagLevel::Note),
|
||||||
};
|
};
|
||||||
|
|
||||||
let msg = match &e {
|
let msg = match &e {
|
||||||
@ -571,7 +572,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
let stacktrace = this.generate_stacktrace();
|
let stacktrace = this.generate_stacktrace();
|
||||||
report_msg(
|
report_msg(
|
||||||
DiagLevel::Note,
|
DiagLevel::Note,
|
||||||
"the place in the program where the ICE was triggered",
|
"the place in the program where the ICE was triggered".to_string(),
|
||||||
vec![],
|
vec![],
|
||||||
vec![],
|
vec![],
|
||||||
vec![],
|
vec![],
|
||||||
|
@ -23,7 +23,7 @@ LL | arg: NotIntoDiagnosticArg,
|
|||||||
|
|
|
|
||||||
= help: normalized in stderr
|
= help: normalized in stderr
|
||||||
note: required by a bound in `Diagnostic::set_arg`
|
note: required by a bound in `Diagnostic::set_arg`
|
||||||
--> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:964:5
|
--> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:960:5
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user