diff options
| author | bors <bors@rust-lang.org> | 2022-10-01 10:44:25 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-10-01 10:44:25 +0000 |
| commit | 744e397d8855f7da87d70aa8d0bd9e0f5f0b51a1 (patch) | |
| tree | 1721987352b5f0a8548fc46984821d974b661934 /compiler/rustc_lint/src/levels.rs | |
| parent | 277bb6653b55475b5fbce6309e9852fa2100dabe (diff) | |
| parent | b5b3ffe3fc9cfb524a6432ec60a0fc95c514d2e1 (diff) | |
| download | rust-744e397d8855f7da87d70aa8d0bd9e0f5f0b51a1.tar.gz rust-744e397d8855f7da87d70aa8d0bd9e0f5f0b51a1.zip | |
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 😢
Diffstat (limited to 'compiler/rustc_lint/src/levels.rs')
| -rw-r--r-- | compiler/rustc_lint/src/levels.rs | 132 |
1 files changed, 73 insertions, 59 deletions
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 1e16ac51e9e..82382350823 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -3,7 +3,7 @@ use crate::late::unerased_lint_store; use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan}; +use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan}; use rustc_hir as hir; use rustc_hir::{intravisit, HirId}; use rustc_middle::hir::nested_filter; @@ -214,14 +214,14 @@ impl<'s> LintLevelsBuilder<'s> { self.struct_lint( FORBIDDEN_LINT_GROUPS, Some(src.span().into()), - |diag_builder| { - let mut diag_builder = diag_builder.build(&format!( - "{}({}) incompatible with previous forbid", - level.as_str(), - src.name(), - )); - decorate_diag(&mut diag_builder); - diag_builder.emit(); + format!( + "{}({}) incompatible with previous forbid", + level.as_str(), + src.name(), + ), + |lint| { + decorate_diag(lint); + lint }, ); } @@ -466,20 +466,18 @@ impl<'s> LintLevelsBuilder<'s> { lvl, src, Some(sp.into()), + format!( + "lint name `{}` is deprecated \ + and may not have an effect in the future.", + name + ), |lint| { - let msg = format!( - "lint name `{}` is deprecated \ - and may not have an effect in the future.", - name - ); - lint.build(&msg) - .span_suggestion( - sp, - "change it to", - new_lint_name, - Applicability::MachineApplicable, - ) - .emit(); + lint.span_suggestion( + sp, + "change it to", + new_lint_name, + Applicability::MachineApplicable, + ) }, ); @@ -533,17 +531,17 @@ impl<'s> LintLevelsBuilder<'s> { renamed_lint_level, src, Some(sp.into()), + msg, |lint| { - let mut err = lint.build(msg); if let Some(new_name) = &renamed { - err.span_suggestion( + lint.span_suggestion( sp, "use the new name", new_name, Applicability::MachineApplicable, ); } - err.emit(); + lint }, ); } @@ -555,23 +553,30 @@ impl<'s> LintLevelsBuilder<'s> { Some(self.current_specs()), self.sess, ); - struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| { - let name = if let Some(tool_ident) = tool_ident { - format!("{}::{}", tool_ident.name, name) - } else { - name.to_string() - }; - let mut db = lint.build(format!("unknown lint: `{}`", name)); - if let Some(suggestion) = suggestion { - db.span_suggestion( - sp, - "did you mean", - suggestion, - Applicability::MachineApplicable, - ); - } - db.emit(); - }); + let name = if let Some(tool_ident) = tool_ident { + format!("{}::{}", tool_ident.name, name) + } else { + name.to_string() + }; + struct_lint_level( + self.sess, + lint, + level, + src, + Some(sp.into()), + format!("unknown lint: `{}`", name), + |lint| { + if let Some(suggestion) = suggestion { + lint.span_suggestion( + sp, + "did you mean", + suggestion, + Applicability::MachineApplicable, + ); + } + lint + }, + ); } } // If this lint was renamed, apply the new lint instead of ignoring the attribute. @@ -621,14 +626,12 @@ impl<'s> LintLevelsBuilder<'s> { lint_level, lint_src, Some(lint_attr_span.into()), - |lint| { - let mut db = lint.build(&format!( - "{}({}) is ignored unless specified at crate level", - level.as_str(), - lint_attr_name - )); - db.emit(); - }, + format!( + "{}({}) is ignored unless specified at crate level", + level.as_str(), + lint_attr_name + ), + |lint| lint, ); // don't set a separate error for every lint in the group break; @@ -665,13 +668,21 @@ impl<'s> LintLevelsBuilder<'s> { if !self.sess.features_untracked().enabled(feature) { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS); - struct_lint_level(self.sess, lint, level, src, Some(span.into()), |lint_db| { - let mut db = - lint_db.build(&format!("unknown lint: `{}`", lint_id.lint.name_lower())); - db.note(&format!("the `{}` lint is unstable", lint_id.lint.name_lower(),)); - add_feature_diagnostics(&mut db, &self.sess.parse_sess, feature); - db.emit(); - }); + struct_lint_level( + self.sess, + lint, + level, + src, + Some(span.into()), + format!("unknown lint: `{}`", lint_id.lint.name_lower()), + |lint| { + lint.note( + &format!("the `{}` lint is unstable", lint_id.lint.name_lower(),), + ); + add_feature_diagnostics(lint, &self.sess.parse_sess, feature); + lint + }, + ); return false; } } @@ -694,10 +705,13 @@ impl<'s> LintLevelsBuilder<'s> { &self, lint: &'static Lint, span: Option<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(lint); - struct_lint_level(self.sess, lint, level, src, span, decorate) + struct_lint_level(self.sess, lint, level, src, span, msg, decorate) } /// Registers the ID provided with the current set of lints stored in |
