diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-01-09 05:57:07 +0100 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-01-11 07:42:26 +0100 |
| commit | eee84fe3960f0bb79f8bf02577bf00aa44302e00 (patch) | |
| tree | 8526d9f87fb2fe8207a9253c4724c0c9dd0a2726 /src | |
| parent | f577b44712f0cba0404482b3e44d24ceb5b54a9e (diff) | |
| download | rust-eee84fe3960f0bb79f8bf02577bf00aa44302e00.tar.gz rust-eee84fe3960f0bb79f8bf02577bf00aa44302e00.zip | |
move struct_lint_level to levels.rs
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/lint/levels.rs | 168 | ||||
| -rw-r--r-- | src/librustc/lint/mod.rs | 158 |
2 files changed, 161 insertions, 165 deletions
diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index d43bc57ea7a..7e966a74910 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -1,15 +1,15 @@ use std::cmp; use crate::ich::StableHashingContext; -use crate::lint; use crate::lint::context::{CheckLintNameResult, LintStore}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_hir::HirId; use rustc_session::lint::{builtin, Level, Lint, LintId}; -use rustc_session::Session; -use rustc_span::source_map::MultiSpan; +use rustc_session::{DiagnosticMessageId, Session}; +use rustc_span::hygiene::MacroKind; +use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use syntax::ast; @@ -326,7 +326,7 @@ impl<'a> LintLevelsBuilder<'a> { Also `cfg_attr(cargo-clippy)` won't be necessary anymore", name ); - lint::struct_lint_level( + struct_lint_level( self.sess, lint, lvl, @@ -366,7 +366,7 @@ impl<'a> LintLevelsBuilder<'a> { let lint = builtin::RENAMED_AND_REMOVED_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess); - let mut err = lint::struct_lint_level( + let mut err = struct_lint_level( self.sess, lint, level, @@ -389,7 +389,7 @@ impl<'a> LintLevelsBuilder<'a> { let (level, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess); let msg = format!("unknown lint: `{}`", name); - let mut db = lint::struct_lint_level( + let mut db = struct_lint_level( self.sess, lint, level, @@ -480,7 +480,7 @@ impl<'a> LintLevelsBuilder<'a> { msg: &str, ) -> DiagnosticBuilder<'a> { let (level, src) = self.sets.get_lint_level(lint, self.cur, None, self.sess); - lint::struct_lint_level(self.sess, lint, level, src, span, msg) + struct_lint_level(self.sess, lint, level, src, span, msg) } /// Registers the ID provided with the current set of lints stored in @@ -553,3 +553,155 @@ impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap { }) } } + +pub fn struct_lint_level<'a>( + sess: &'a Session, + lint: &'static Lint, + level: Level, + src: LintSource, + span: Option<MultiSpan>, + msg: &str, +) -> DiagnosticBuilder<'a> { + let mut err = match (level, span) { + (Level::Allow, _) => return sess.diagnostic().struct_dummy(), + (Level::Warn, Some(span)) => sess.struct_span_warn(span, msg), + (Level::Warn, None) => sess.struct_warn(msg), + (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg), + (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(msg), + }; + + // Check for future incompatibility lints and issue a stronger warning. + let lint_id = LintId::of(lint); + let future_incompatible = lint.future_incompatible; + + // 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. + if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { + // Any suggestions made here are likely to be incorrect, so anything we + // emit shouldn't be automatically fixed by rustfix. + err.allow_suggestions(false); + + // If this is a future incompatible lint it'll become a hard error, so + // we have to emit *something*. Also allow lints to whitelist themselves + // on a case-by-case basis for emission in a foreign macro. + if future_incompatible.is_none() && !lint.report_in_external_macro { + err.cancel(); + // Don't continue further, since we don't want to have + // `diag_span_note_once` called for a diagnostic that isn't emitted. + return err; + } + } + + let name = lint.name_lower(); + match src { + LintSource::Default => { + sess.diag_note_once( + &mut err, + DiagnosticMessageId::from(lint), + &format!("`#[{}({})]` on by default", level.as_str(), name), + ); + } + LintSource::CommandLine(lint_flag_val) => { + let flag = match level { + Level::Warn => "-W", + Level::Deny => "-D", + Level::Forbid => "-F", + Level::Allow => panic!(), + }; + let hyphen_case_lint_name = name.replace("_", "-"); + if lint_flag_val.as_str() == name { + sess.diag_note_once( + &mut err, + DiagnosticMessageId::from(lint), + &format!( + "requested on the command line with `{} {}`", + flag, hyphen_case_lint_name + ), + ); + } else { + let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); + sess.diag_note_once( + &mut err, + DiagnosticMessageId::from(lint), + &format!( + "`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, hyphen_case_flag_val + ), + ); + } + } + LintSource::Node(lint_attr_name, src, reason) => { + if let Some(rationale) = reason { + err.note(&rationale.as_str()); + } + sess.diag_span_note_once( + &mut err, + DiagnosticMessageId::from(lint), + src, + "lint level defined here", + ); + if lint_attr_name.as_str() != name { + let level_str = level.as_str(); + sess.diag_note_once( + &mut err, + DiagnosticMessageId::from(lint), + &format!( + "`#[{}({})]` implied by `#[{}({})]`", + level_str, name, level_str, lint_attr_name + ), + ); + } + } + } + + err.code(DiagnosticId::Lint(name)); + + if let Some(future_incompatible) = future_incompatible { + const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ + it will become a hard error"; + + let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) { + "once this method is added to the standard library, \ + the ambiguity may cause an error or change in behavior!" + .to_owned() + } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) { + "this borrowing pattern was not meant to be accepted, \ + and may become a hard error in the future" + .to_owned() + } else if let Some(edition) = future_incompatible.edition { + format!("{} in the {} edition!", STANDARD_MESSAGE, edition) + } else { + format!("{} in a future release!", STANDARD_MESSAGE) + }; + let citation = format!("for more information, see {}", future_incompatible.reference); + err.warn(&explanation); + err.note(&citation); + } + + return err; +} + +/// Returns whether `span` originates in a foreign crate's external macro. +/// +/// This is used to test whether a lint should not even begin to figure out whether it should +/// be reported on the current node. +pub fn in_external_macro(sess: &Session, span: Span) -> bool { + let expn_data = span.ctxt().outer_expn_data(); + match expn_data.kind { + ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false, + ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" + ExpnKind::Macro(MacroKind::Bang, _) => { + if expn_data.def_site.is_dummy() { + // Dummy span for the `def_site` means it's an external macro. + return true; + } + match sess.source_map().span_to_snippet(expn_data.def_site) { + Ok(code) => !code.starts_with("macro_rules"), + // No snippet means external macro or compiler-builtin expansion. + Err(_) => true, + } + } + ExpnKind::Macro(..) => true, // definitely a plugin + } +} diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index eefcb670d0e..371fa27cb24 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -23,12 +23,8 @@ pub use self::Level::*; use crate::ty::TyCtxt; use rustc_data_structures::sync; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use rustc_hir as hir; use rustc_session::lint::builtin::HardwiredLints; -use rustc_session::{DiagnosticMessageId, Session}; -use rustc_span::hygiene::MacroKind; -use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; use rustc_span::Span; use syntax::ast; @@ -318,161 +314,9 @@ mod context; pub mod internal; mod levels; -pub use self::levels::{LintLevelMap, LintLevelSets, LintLevelsBuilder}; - -pub fn struct_lint_level<'a>( - sess: &'a Session, - lint: &'static Lint, - level: Level, - src: LintSource, - span: Option<MultiSpan>, - msg: &str, -) -> DiagnosticBuilder<'a> { - let mut err = match (level, span) { - (Level::Allow, _) => return sess.diagnostic().struct_dummy(), - (Level::Warn, Some(span)) => sess.struct_span_warn(span, msg), - (Level::Warn, None) => sess.struct_warn(msg), - (Level::Deny, Some(span)) | (Level::Forbid, Some(span)) => sess.struct_span_err(span, msg), - (Level::Deny, None) | (Level::Forbid, None) => sess.struct_err(msg), - }; - - // Check for future incompatibility lints and issue a stronger warning. - let lint_id = LintId::of(lint); - let future_incompatible = lint.future_incompatible; - - // 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. - if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) { - // Any suggestions made here are likely to be incorrect, so anything we - // emit shouldn't be automatically fixed by rustfix. - err.allow_suggestions(false); - - // If this is a future incompatible lint it'll become a hard error, so - // we have to emit *something*. Also allow lints to whitelist themselves - // on a case-by-case basis for emission in a foreign macro. - if future_incompatible.is_none() && !lint.report_in_external_macro { - err.cancel(); - // Don't continue further, since we don't want to have - // `diag_span_note_once` called for a diagnostic that isn't emitted. - return err; - } - } - - let name = lint.name_lower(); - match src { - LintSource::Default => { - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!("`#[{}({})]` on by default", level.as_str(), name), - ); - } - LintSource::CommandLine(lint_flag_val) => { - let flag = match level { - Level::Warn => "-W", - Level::Deny => "-D", - Level::Forbid => "-F", - Level::Allow => panic!(), - }; - let hyphen_case_lint_name = name.replace("_", "-"); - if lint_flag_val.as_str() == name { - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!( - "requested on the command line with `{} {}`", - flag, hyphen_case_lint_name - ), - ); - } else { - let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!( - "`{} {}` implied by `{} {}`", - flag, hyphen_case_lint_name, flag, hyphen_case_flag_val - ), - ); - } - } - LintSource::Node(lint_attr_name, src, reason) => { - if let Some(rationale) = reason { - err.note(&rationale.as_str()); - } - sess.diag_span_note_once( - &mut err, - DiagnosticMessageId::from(lint), - src, - "lint level defined here", - ); - if lint_attr_name.as_str() != name { - let level_str = level.as_str(); - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!( - "`#[{}({})]` implied by `#[{}({})]`", - level_str, name, level_str, lint_attr_name - ), - ); - } - } - } - - err.code(DiagnosticId::Lint(name)); - - if let Some(future_incompatible) = future_incompatible { - const STANDARD_MESSAGE: &str = "this was previously accepted by the compiler but is being phased out; \ - it will become a hard error"; - - let explanation = if lint_id == LintId::of(builtin::UNSTABLE_NAME_COLLISIONS) { - "once this method is added to the standard library, \ - the ambiguity may cause an error or change in behavior!" - .to_owned() - } else if lint_id == LintId::of(builtin::MUTABLE_BORROW_RESERVATION_CONFLICT) { - "this borrowing pattern was not meant to be accepted, \ - and may become a hard error in the future" - .to_owned() - } else if let Some(edition) = future_incompatible.edition { - format!("{} in the {} edition!", STANDARD_MESSAGE, edition) - } else { - format!("{} in a future release!", STANDARD_MESSAGE) - }; - let citation = format!("for more information, see {}", future_incompatible.reference); - err.warn(&explanation); - err.note(&citation); - } - - return err; -} +pub use self::levels::{struct_lint_level, LintLevelMap, LintLevelSets, LintLevelsBuilder}; pub fn maybe_lint_level_root(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { let attrs = tcx.hir().attrs(id); attrs.iter().any(|attr| Level::from_symbol(attr.name_or_empty()).is_some()) } - -/// Returns whether `span` originates in a foreign crate's external macro. -/// -/// This is used to test whether a lint should not even begin to figure out whether it should -/// be reported on the current node. -pub fn in_external_macro(sess: &Session, span: Span) -> bool { - let expn_data = span.ctxt().outer_expn_data(); - match expn_data.kind { - ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false, - ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" - ExpnKind::Macro(MacroKind::Bang, _) => { - if expn_data.def_site.is_dummy() { - // Dummy span for the `def_site` means it's an external macro. - return true; - } - match sess.source_map().span_to_snippet(expn_data.def_site) { - Ok(code) => !code.starts_with("macro_rules"), - // No snippet means external macro or compiler-builtin expansion. - Err(_) => true, - } - } - ExpnKind::Macro(..) => true, // definitely a plugin - } -} |
