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
|
@ -2,7 +2,7 @@ use std::cmp;
|
|||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_errors::{Diagnostic, DiagnosticId, LintDiagnosticBuilder, MultiSpan};
|
||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan};
|
||||
use rustc_hir::HirId;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
|
@ -283,7 +283,11 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
level: Level,
|
||||
src: LintLevelSource,
|
||||
span: Option<MultiSpan>,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) + 'd,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl 'd
|
||||
+ for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
) {
|
||||
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
|
||||
// the "real" work.
|
||||
|
@ -293,7 +297,13 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
level: Level,
|
||||
src: LintLevelSource,
|
||||
span: Option<MultiSpan>,
|
||||
decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) + 'd>,
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: Box<
|
||||
dyn 'd
|
||||
+ for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
>,
|
||||
) {
|
||||
// Check for future incompatibility lints and issue a stronger warning.
|
||||
let future_incompatible = lint.future_incompatible;
|
||||
|
@ -344,6 +354,9 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
(Level::Deny | Level::Forbid, None) => sess.diagnostic().struct_err_lint(""),
|
||||
};
|
||||
|
||||
err.set_primary_message(msg);
|
||||
err.set_is_lint();
|
||||
|
||||
// If this code originates in a foreign macro, aka something that this crate
|
||||
// did not itself author, then it's likely that there's nothing this crate
|
||||
// can do about it. We probably want to skip the lint entirely.
|
||||
|
@ -373,12 +386,12 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
if let Level::Expect(_) = level {
|
||||
let name = lint.name_lower();
|
||||
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn: false });
|
||||
decorate(LintDiagnosticBuilder::new(err));
|
||||
|
||||
decorate(&mut err);
|
||||
err.emit();
|
||||
return;
|
||||
}
|
||||
|
||||
explain_lint_level_source(lint, level, src, &mut err);
|
||||
|
||||
let name = lint.name_lower();
|
||||
let is_force_warn = matches!(level, Level::ForceWarn(_));
|
||||
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn });
|
||||
|
@ -417,10 +430,12 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
}
|
||||
}
|
||||
|
||||
// Finally, run `decorate`. This function is also responsible for emitting the diagnostic.
|
||||
decorate(LintDiagnosticBuilder::new(err));
|
||||
// Finally, run `decorate`.
|
||||
decorate(&mut err);
|
||||
explain_lint_level_source(lint, level, src, &mut *err);
|
||||
err.emit()
|
||||
}
|
||||
struct_lint_level_impl(sess, lint, level, src, span, Box::new(decorate))
|
||||
struct_lint_level_impl(sess, lint, level, src, span, msg, Box::new(decorate))
|
||||
}
|
||||
|
||||
/// Returns whether `span` originates in a foreign crate's external macro.
|
||||
|
|
|
@ -253,13 +253,12 @@ fn late_report_deprecation(
|
|||
return;
|
||||
}
|
||||
let method_span = method_span.unwrap_or(span);
|
||||
tcx.struct_span_lint_hir(lint, hir_id, method_span, |lint| {
|
||||
let mut diag = lint.build(message);
|
||||
tcx.struct_span_lint_hir(lint, hir_id, method_span, message, |diag| {
|
||||
if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
|
||||
let kind = tcx.def_kind(def_id).descr(def_id);
|
||||
deprecation_suggestion(&mut diag, kind, suggestion, method_span);
|
||||
deprecation_suggestion(diag, kind, suggestion, method_span);
|
||||
}
|
||||
diag.emit();
|
||||
diag
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -621,9 +620,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
unmarked: impl FnOnce(Span, DefId),
|
||||
) -> bool {
|
||||
let soft_handler = |lint, span, msg: &_| {
|
||||
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
|
||||
lint.build(msg).emit();
|
||||
})
|
||||
self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |lint| lint)
|
||||
};
|
||||
let eval_result =
|
||||
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
|
||||
|
|
|
@ -35,7 +35,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
|||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal};
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_errors::{DecorateLint, ErrorGuaranteed, LintDiagnosticBuilder, MultiSpan};
|
||||
use rustc_errors::{
|
||||
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
|
||||
|
@ -2857,7 +2859,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
span: impl Into<MultiSpan>,
|
||||
decorator: impl for<'a> DecorateLint<'a, ()>,
|
||||
) {
|
||||
self.struct_span_lint_hir(lint, hir_id, span, |diag| decorator.decorate_lint(diag))
|
||||
self.struct_span_lint_hir(lint, hir_id, span, decorator.msg(), |diag| {
|
||||
decorator.decorate_lint(diag)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn struct_span_lint_hir(
|
||||
|
@ -2865,10 +2869,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
lint: &'static Lint,
|
||||
hir_id: HirId,
|
||||
span: impl Into<MultiSpan>,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
) {
|
||||
let (level, src) = self.lint_level_at_node(lint, hir_id);
|
||||
struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
|
||||
struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
|
||||
}
|
||||
|
||||
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
|
||||
|
@ -2879,17 +2886,20 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
id: HirId,
|
||||
decorator: impl for<'a> DecorateLint<'a, ()>,
|
||||
) {
|
||||
self.struct_lint_node(lint, id, |diag| decorator.decorate_lint(diag))
|
||||
self.struct_lint_node(lint, id, decorator.msg(), |diag| decorator.decorate_lint(diag))
|
||||
}
|
||||
|
||||
pub fn struct_lint_node(
|
||||
self,
|
||||
lint: &'static Lint,
|
||||
id: HirId,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
|
||||
msg: impl Into<DiagnosticMessage>,
|
||||
decorate: impl for<'a, 'b> FnOnce(
|
||||
&'b mut DiagnosticBuilder<'a, ()>,
|
||||
) -> &'b mut DiagnosticBuilder<'a, ()>,
|
||||
) {
|
||||
let (level, src) = self.lint_level_at_node(lint, id);
|
||||
struct_lint_level(self.sess, lint, level, src, None, decorate);
|
||||
struct_lint_level(self.sess, lint, level, src, None, msg, decorate);
|
||||
}
|
||||
|
||||
pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue