Auto merge of #101986 - WaffleLapkin:move_lint_note_to_the_bottom, r=estebank
Move lint level source explanation to the bottom So, uhhhhh r? `@estebank` ## User-facing change "note: `#[warn(...)]` on by default" and such are moved to the bottom of the diagnostic: ```diff - = note: `#[warn(unsupported_calling_conventions)]` on by default = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678> + = note: `#[warn(unsupported_calling_conventions)]` on by default ``` Why warning is enabled is the least important thing, so it shouldn't be the first note the user reads, IMO. ## Developer-facing change `struct_span_lint` and similar methods have a different signature. Before: `..., impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>)` After: `..., impl Into<DiagnosticMessage>, impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>) -> &'b mut DiagnosticBuilder<'a, ()>` The reason for this is that `struct_span_lint` needs to edit the diagnostic _after_ `decorate` closure is called. This also makes lint code a little bit nicer in my opinion. Another option is to use `impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) -> DiagnosticBuilder<'a, ()>` altough I don't _really_ see reasons to do `let lint = lint.build(message)` everywhere. ## Subtle problem By moving the message outside of the closure (that may not be called if the lint is disabled) `format!(...)` is executed earlier, possibly formatting `Ty` which may call a query that trims paths that crashes the compiler if there were no warnings... I don't think it's that big of a deal, considering that we move from `format!(...)` to `fluent` (which is lazy by-default) anyway, however this required adding a workaround which is unfortunate. ## P.S. I'm sorry, I do not how to make this PR smaller/easier to review. Changes to the lint API affect SO MUCH 😢
This commit is contained in:
commit
744e397d88
827 changed files with 3370 additions and 3210 deletions
|
@ -370,10 +370,13 @@ impl CheckAttrVisitor<'_> {
|
|||
b.push_str(&(allowed_target.to_string() + "s"));
|
||||
b
|
||||
});
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
lint.build(&format!("`#[{name}]` only has an effect on {}", supported_names))
|
||||
.emit();
|
||||
});
|
||||
self.tcx.struct_span_lint_hir(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span,
|
||||
&format!("`#[{name}]` only has an effect on {}", supported_names),
|
||||
|lint| lint,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -877,25 +880,31 @@ impl CheckAttrVisitor<'_> {
|
|||
hir_id: HirId,
|
||||
) -> bool {
|
||||
if hir_id != CRATE_HIR_ID {
|
||||
self.tcx.struct_span_lint_hir(INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), |lint| {
|
||||
let mut err = lint.build(fluent::passes::attr_crate_level);
|
||||
if attr.style == AttrStyle::Outer
|
||||
&& self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID
|
||||
{
|
||||
if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) {
|
||||
src.insert(1, '!');
|
||||
err.span_suggestion_verbose(
|
||||
attr.span,
|
||||
fluent::passes::suggestion,
|
||||
src,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.span_help(attr.span, fluent::passes::help);
|
||||
self.tcx.struct_span_lint_hir(
|
||||
INVALID_DOC_ATTRIBUTES,
|
||||
hir_id,
|
||||
meta.span(),
|
||||
fluent::passes::attr_crate_level,
|
||||
|err| {
|
||||
if attr.style == AttrStyle::Outer
|
||||
&& self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID
|
||||
{
|
||||
if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) {
|
||||
src.insert(1, '!');
|
||||
err.span_suggestion_verbose(
|
||||
attr.span,
|
||||
fluent::passes::suggestion,
|
||||
src,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.span_help(attr.span, fluent::passes::help);
|
||||
}
|
||||
}
|
||||
}
|
||||
err.note(fluent::passes::note).emit();
|
||||
});
|
||||
err.note(fluent::passes::note);
|
||||
err
|
||||
},
|
||||
);
|
||||
return false;
|
||||
}
|
||||
true
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use itertools::Itertools;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::{pluralize, Applicability, MultiSpan};
|
||||
use rustc_errors::{pluralize, Applicability, DelayDm, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
|
@ -184,13 +184,14 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
|||
lint::builtin::DEAD_CODE,
|
||||
assign.hir_id,
|
||||
assign.span,
|
||||
|lint| {
|
||||
lint.build(&format!(
|
||||
DelayDm(|| format!(
|
||||
"useless assignment of {} of type `{}` to itself",
|
||||
if is_field_assign { "field" } else { "variable" },
|
||||
self.typeck_results().expr_ty(lhs),
|
||||
))
|
||||
.emit();
|
||||
)),
|
||||
|lint| {
|
||||
lint
|
||||
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -717,6 +718,26 @@ impl<'tcx> DeadVisitor<'tcx> {
|
|||
})
|
||||
.collect();
|
||||
|
||||
let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
|
||||
let span_len = dead_codes.len();
|
||||
let names = match &names[..] {
|
||||
_ if span_len > 6 => String::new(),
|
||||
[name] => format!("`{name}` "),
|
||||
[names @ .., last] => {
|
||||
format!(
|
||||
"{} and `{last}` ",
|
||||
names.iter().map(|name| format!("`{name}`")).join(", ")
|
||||
)
|
||||
}
|
||||
[] => unreachable!(),
|
||||
};
|
||||
let msg = format!(
|
||||
"{these}{descr}{s} {names}{are} never {participle}",
|
||||
these = if span_len > 6 { "multiple " } else { "" },
|
||||
s = pluralize!(span_len),
|
||||
are = pluralize!("is", span_len),
|
||||
);
|
||||
|
||||
tcx.struct_span_lint_hir(
|
||||
if is_positional {
|
||||
lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
|
||||
|
@ -725,27 +746,8 @@ impl<'tcx> DeadVisitor<'tcx> {
|
|||
},
|
||||
tcx.hir().local_def_id_to_hir_id(first_id),
|
||||
MultiSpan::from_spans(spans.clone()),
|
||||
|lint| {
|
||||
let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
|
||||
let span_len = dead_codes.len();
|
||||
let names = match &names[..] {
|
||||
_ if span_len > 6 => String::new(),
|
||||
[name] => format!("`{name}` "),
|
||||
[names @ .., last] => {
|
||||
format!(
|
||||
"{} and `{last}` ",
|
||||
names.iter().map(|name| format!("`{name}`")).join(", ")
|
||||
)
|
||||
}
|
||||
[] => unreachable!(),
|
||||
};
|
||||
let mut err = lint.build(&format!(
|
||||
"{these}{descr}{s} {names}{are} never {participle}",
|
||||
these = if span_len > 6 { "multiple " } else { "" },
|
||||
s = pluralize!(span_len),
|
||||
are = pluralize!("is", span_len),
|
||||
));
|
||||
|
||||
msg,
|
||||
|err| {
|
||||
if is_positional {
|
||||
err.multipart_suggestion(
|
||||
&format!(
|
||||
|
@ -791,7 +793,7 @@ impl<'tcx> DeadVisitor<'tcx> {
|
|||
);
|
||||
err.note(&msg);
|
||||
}
|
||||
err.emit();
|
||||
err
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1319,14 +1319,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
// that we do not emit the same warning twice if the uninhabited type
|
||||
// is indeed `!`.
|
||||
|
||||
let msg = format!("unreachable {}", descr);
|
||||
self.ir.tcx.struct_span_lint_hir(
|
||||
lint::builtin::UNREACHABLE_CODE,
|
||||
expr_id,
|
||||
expr_span,
|
||||
|lint| {
|
||||
let msg = format!("unreachable {}", descr);
|
||||
lint.build(&msg)
|
||||
.span_label(expr_span, &msg)
|
||||
&msg,
|
||||
|diag| {
|
||||
diag.span_label(expr_span, &msg)
|
||||
.span_label(orig_span, "any code following this expression is unreachable")
|
||||
.span_note(
|
||||
orig_span,
|
||||
|
@ -1335,7 +1335,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
orig_ty
|
||||
),
|
||||
)
|
||||
.emit();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -1491,14 +1490,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
lint::builtin::UNUSED_ASSIGNMENTS,
|
||||
var_hir_id,
|
||||
vec![span],
|
||||
|lint| {
|
||||
lint.build(&format!(
|
||||
"value captured by `{}` is never read",
|
||||
name
|
||||
))
|
||||
.help("did you mean to capture by reference instead?")
|
||||
.emit();
|
||||
},
|
||||
format!("value captured by `{}` is never read", name),
|
||||
|lint| lint.help("did you mean to capture by reference instead?"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1508,11 +1501,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
lint::builtin::UNUSED_VARIABLES,
|
||||
var_hir_id,
|
||||
vec![span],
|
||||
|lint| {
|
||||
lint.build(&format!("unused variable: `{}`", name))
|
||||
.help("did you mean to capture by reference instead?")
|
||||
.emit();
|
||||
},
|
||||
format!("unused variable: `{}`", name),
|
||||
|lint| lint.help("did you mean to capture by reference instead?"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1601,20 +1591,17 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
.into_iter()
|
||||
.map(|(_, _, ident_span)| ident_span)
|
||||
.collect::<Vec<_>>(),
|
||||
|lint| {
|
||||
lint.build(&format!("variable `{}` is assigned to, but never used", name))
|
||||
.note(&format!("consider using `_{}` instead", name))
|
||||
.emit();
|
||||
},
|
||||
format!("variable `{}` is assigned to, but never used", name),
|
||||
|lint| lint.note(&format!("consider using `_{}` instead", name)),
|
||||
)
|
||||
} else if can_remove {
|
||||
self.ir.tcx.struct_span_lint_hir(
|
||||
lint::builtin::UNUSED_VARIABLES,
|
||||
first_hir_id,
|
||||
hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::<Vec<_>>(),
|
||||
format!("unused variable: `{}`", name),
|
||||
|lint| {
|
||||
let mut err = lint.build(&format!("unused variable: `{}`", name));
|
||||
err.multipart_suggestion(
|
||||
lint.multipart_suggestion(
|
||||
"try removing the field",
|
||||
hir_ids_and_spans
|
||||
.iter()
|
||||
|
@ -1629,8 +1616,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
})
|
||||
.collect(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
@ -1661,14 +1647,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
.iter()
|
||||
.map(|(_, pat_span, _)| *pat_span)
|
||||
.collect::<Vec<_>>(),
|
||||
format!("unused variable: `{}`", name),
|
||||
|lint| {
|
||||
let mut err = lint.build(&format!("unused variable: `{}`", name));
|
||||
err.multipart_suggestion(
|
||||
lint.multipart_suggestion(
|
||||
"try ignoring the field",
|
||||
shorthands,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
@ -1684,17 +1669,16 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
.iter()
|
||||
.map(|(_, _, ident_span)| *ident_span)
|
||||
.collect::<Vec<_>>(),
|
||||
format!("unused variable: `{}`", name),
|
||||
|lint| {
|
||||
let mut err = lint.build(&format!("unused variable: `{}`", name));
|
||||
if self.has_added_lit_match_name_span(&name, opt_body, &mut err) {
|
||||
err.span_label(pat.span, "unused variable");
|
||||
if self.has_added_lit_match_name_span(&name, opt_body, lint) {
|
||||
lint.span_label(pat.span, "unused variable");
|
||||
}
|
||||
err.multipart_suggestion(
|
||||
lint.multipart_suggestion(
|
||||
"if this is intentional, prefix it with an underscore",
|
||||
non_shorthands,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -1758,11 +1742,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||
lint::builtin::UNUSED_ASSIGNMENTS,
|
||||
hir_id,
|
||||
spans,
|
||||
|lint| {
|
||||
lint.build(&message(&name))
|
||||
.help("maybe it is overwritten before being read?")
|
||||
.emit();
|
||||
},
|
||||
message(&name),
|
||||
|lint| lint.help("maybe it is overwritten before being read?"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,9 +65,13 @@ fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
|
|||
if abi == Abi::Rust {
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let span = tcx.def_span(def_id);
|
||||
tcx.struct_span_lint_hir(UNDEFINED_NAKED_FUNCTION_ABI, hir_id, span, |lint| {
|
||||
lint.build("Rust ABI is unsupported in naked functions").emit();
|
||||
});
|
||||
tcx.struct_span_lint_hir(
|
||||
UNDEFINED_NAKED_FUNCTION_ABI,
|
||||
hir_id,
|
||||
span,
|
||||
"Rust ABI is unsupported in naked functions",
|
||||
|lint| lint,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -752,10 +752,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
|
||||
item.hir_id(),
|
||||
span,
|
||||
|lint| {lint
|
||||
.build("an `#[unstable]` annotation here has no effect")
|
||||
.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
|
||||
.emit();}
|
||||
"an `#[unstable]` annotation here has no effect",
|
||||
|lint| lint.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1081,11 +1079,16 @@ fn unnecessary_partially_stable_feature_lint(
|
|||
implies: Symbol,
|
||||
since: Symbol,
|
||||
) {
|
||||
tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
|
||||
lint.build(&format!(
|
||||
tcx.struct_span_lint_hir(
|
||||
lint::builtin::STABLE_FEATURES,
|
||||
hir::CRATE_HIR_ID,
|
||||
span,
|
||||
format!(
|
||||
"the feature `{feature}` has been partially stabilized since {since} and is succeeded \
|
||||
by the feature `{implies}`"
|
||||
))
|
||||
),
|
||||
|lint| {
|
||||
lint
|
||||
.span_suggestion(
|
||||
span,
|
||||
&format!(
|
||||
|
@ -1100,8 +1103,8 @@ fn unnecessary_partially_stable_feature_lint(
|
|||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn unnecessary_stable_feature_lint(
|
||||
|
@ -1113,12 +1116,8 @@ fn unnecessary_stable_feature_lint(
|
|||
if since.as_str() == VERSION_PLACEHOLDER {
|
||||
since = rust_version_symbol();
|
||||
}
|
||||
tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
|
||||
lint.build(&format!(
|
||||
"the feature `{feature}` has been stable since {since} and no longer requires an \
|
||||
attribute to enable",
|
||||
))
|
||||
.emit();
|
||||
tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, format!("the feature `{feature}` has been stable since {since} and no longer requires an attribute to enable"), |lint| {
|
||||
lint
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue