diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2021-03-18 00:28:14 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-18 00:28:14 +0100 |
| commit | bcb9226efb86f5e082476f4b6910735bd8522825 (patch) | |
| tree | 603ed37ae7d05ac3340a5a99356c7d21a98685fe /compiler/rustc_lint/src | |
| parent | 201893f5aca0e98d66b01ce59e0889c8c4266079 (diff) | |
| parent | e3031fe22ae19965967f4fdf8bf46b017902a06a (diff) | |
Rollup merge of #83216 - jyn514:register-tool, r=petrochenkov
Allow registering tool lints with `register_tool` Previously, there was no way to add a custom tool prefix, even if the tool itself had registered a lint: ```rust #![feature(register_tool)] #![register_tool(xyz)] #![warn(xyz::my_lint)] ``` ``` $ rustc unknown-lint.rs --crate-type lib error[E0710]: an unknown tool name found in scoped lint: `xyz::my_lint` --> unknown-lint.rs:3:9 | 3 | #![warn(xyz::my_lint)] | ^^^ ``` This allows opting-in to lints from other tools using `register_tool`. cc https://github.com/rust-lang/rust/issues/66079#issuecomment-788589193, ``@chorman0773`` r? ``@petrochenkov``
Diffstat (limited to 'compiler/rustc_lint/src')
| -rw-r--r-- | compiler/rustc_lint/src/context.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/levels.rs | 46 |
2 files changed, 38 insertions, 10 deletions
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 3ba687124ae..c9de85a2f18 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -748,7 +748,7 @@ impl<'a> EarlyContext<'a> { sess, krate, lint_store, - builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store), + builder: LintLevelsBuilder::new(sess, warn_about_weird_lints, lint_store, &krate.attrs), buffered, } } diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 5e6b090027c..a332c300787 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1,13 +1,12 @@ use crate::context::{CheckLintNameResult, LintStore}; use crate::late::unerased_lint_store; use rustc_ast as ast; -use rustc_ast::attr; use rustc_ast::unwrap_or; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::{intravisit, HirId}; use rustc_middle::hir::map::Map; use rustc_middle::lint::LevelAndSource; @@ -32,7 +31,8 @@ use std::cmp; fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap { assert_eq!(cnum, LOCAL_CRATE); let store = unerased_lint_store(tcx); - let levels = LintLevelsBuilder::new(tcx.sess, false, &store); + let crate_attrs = tcx.get_attrs(DefId { krate: cnum, index: CRATE_DEF_INDEX }); + let levels = LintLevelsBuilder::new(tcx.sess, false, &store, crate_attrs); let mut builder = LintLevelMapBuilder { levels, tcx, store }; let krate = tcx.hir().krate(); @@ -56,6 +56,7 @@ pub struct LintLevelsBuilder<'s> { cur: u32, warn_about_weird_lints: bool, store: &'s LintStore, + crate_attrs: &'s [ast::Attribute], } pub struct BuilderPush { @@ -64,7 +65,12 @@ pub struct BuilderPush { } impl<'s> LintLevelsBuilder<'s> { - pub fn new(sess: &'s Session, warn_about_weird_lints: bool, store: &'s LintStore) -> Self { + pub fn new( + sess: &'s Session, + warn_about_weird_lints: bool, + store: &'s LintStore, + crate_attrs: &'s [ast::Attribute], + ) -> Self { let mut builder = LintLevelsBuilder { sess, sets: LintLevelSets::new(), @@ -72,6 +78,7 @@ impl<'s> LintLevelsBuilder<'s> { id_to_set: Default::default(), warn_about_weird_lints, store, + crate_attrs, }; builder.process_command_line(sess, store); assert_eq!(builder.sets.list.len(), 1); @@ -304,15 +311,22 @@ impl<'s> LintLevelsBuilder<'s> { }; let tool_name = if meta_item.path.segments.len() > 1 { let tool_ident = meta_item.path.segments[0].ident; - if !attr::is_known_lint_tool(tool_ident) { - struct_span_err!( + if !is_known_lint_tool(tool_ident.name, sess, &self.crate_attrs) { + let mut err = struct_span_err!( sess, tool_ident.span, E0710, - "an unknown tool name found in scoped lint: `{}`", + "unknown tool name `{}` found in scoped lint: `{}`", + tool_ident.name, pprust::path_to_string(&meta_item.path), - ) - .emit(); + ); + if sess.is_nightly_build() { + err.help(&format!( + "add `#![register_tool({})]` to the crate root", + tool_ident.name + )); + } + err.emit(); continue; } @@ -559,6 +573,20 @@ impl<'s> LintLevelsBuilder<'s> { } } +fn is_known_lint_tool(m_item: Symbol, sess: &Session, attrs: &[ast::Attribute]) -> bool { + if [sym::clippy, sym::rustc, sym::rustdoc].contains(&m_item) { + return true; + } + // Look for registered tools + // NOTE: does no error handling; error handling is done by rustc_resolve. + sess.filter_by_name(attrs, sym::register_tool) + .filter_map(|attr| attr.meta_item_list()) + .flat_map(std::convert::identity) + .filter_map(|nested_meta| nested_meta.ident()) + .map(|ident| ident.name) + .any(|name| name == m_item) +} + struct LintLevelMapBuilder<'a, 'tcx> { levels: LintLevelsBuilder<'tcx>, tcx: TyCtxt<'tcx>, |
