From 2b5bc487c5e7a028f56820db49c8f2b1c6aec99a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 13 Oct 2016 12:08:50 -0400 Subject: [PATCH] improve early lint to use multispan from diagnostic --- src/librustc/lint/context.rs | 49 ++++++++++--------------------- src/librustc/lint/mod.rs | 2 +- src/librustc/session/mod.rs | 23 ++++++++++----- src/librustc_errors/diagnostic.rs | 4 +-- src/librustc_errors/lib.rs | 4 +-- 5 files changed, 36 insertions(+), 46 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 95e1ba6e0567..f08aa2eb49f7 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -83,15 +83,11 @@ pub struct LintStore { /// When you call `add_lint` on the session, you wind up storing one /// of these, which records a "potential lint" at a particular point. +#[derive(PartialEq)] pub struct EarlyLint { /// what lint is this? (e.g., `dead_code`) pub id: LintId, - /// what span was it attached to (this is used for Eq comparisons; - /// it duplicates to some extent the information in - /// `diagnostic.span`) - pub span: MultiSpan, - /// the main message pub diagnostic: Diagnostic, } @@ -106,38 +102,22 @@ impl fmt::Debug for EarlyLint { } } -impl EarlyLint { - pub fn new(id: LintId, span: Span, msg: M) -> Self { - let diagnostic = msg.into_diagnostic(span); - EarlyLint { id: id, span: MultiSpan::from(span), diagnostic: diagnostic } - } - - pub fn with_diagnostic(id: LintId, span: Span, diagnostic: Diagnostic) -> Self { - EarlyLint { id: id, span: MultiSpan::from(span), diagnostic: diagnostic } - } - - pub fn matches(&self, other: &EarlyLint) -> bool { - self.id == other.id && - self.span == other.span && - self.diagnostic.message == other.diagnostic.message - } +pub trait IntoEarlyLint { + fn into_early_lint(self, id: LintId) -> EarlyLint; } -pub trait EarlyLintMessage { - fn into_diagnostic(self, span: Span) -> Diagnostic; -} - -impl EarlyLintMessage for String { - fn into_diagnostic(self, span: Span) -> Diagnostic { - let mut diagnostic = Diagnostic::new(errors::Level::Warning, &self); +impl<'a> IntoEarlyLint for (Span, &'a str) { + fn into_early_lint(self, id: LintId) -> EarlyLint { + let (span, msg) = self; + let mut diagnostic = Diagnostic::new(errors::Level::Warning, msg); diagnostic.set_span(span); - diagnostic + EarlyLint { id: id, diagnostic: diagnostic } } } -impl EarlyLintMessage for Diagnostic { - fn into_diagnostic(self, _span: Span) -> Diagnostic { - self +impl IntoEarlyLint for Diagnostic { + fn into_early_lint(self, id: LintId) -> EarlyLint { + EarlyLint { id: id, diagnostic: self } } } @@ -578,8 +558,9 @@ pub trait LintContext: Sized { } fn early_lint(&self, early_lint: EarlyLint) { + let span = early_lint.diagnostic.span.primary_span().expect("early lint w/o primary span"); let mut err = self.struct_span_lint(early_lint.id.lint, - early_lint.span, + span, &early_lint.diagnostic.message); err.copy_details_not_message(&early_lint.diagnostic); err.emit(); @@ -1283,7 +1264,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // in the iteration code. for (id, v) in tcx.sess.lints.borrow().iter() { for early_lint in v { - span_bug!(early_lint.span.clone(), + span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?} at {}", early_lint, tcx.map.node_to_string(*id)); } @@ -1321,7 +1302,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { // in the iteration code. for (_, v) in sess.lints.borrow().iter() { for early_lint in v { - span_bug!(early_lint.span.clone(), "unprocessed lint {:?}", early_lint); + span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?}", early_lint); } } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index abbab299ca0c..34e0ce7da146 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -41,7 +41,7 @@ use hir; pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, raw_emit_lint, check_crate, check_ast_crate, gather_attrs, - raw_struct_lint, FutureIncompatibleInfo, EarlyLint, EarlyLintMessage}; + raw_struct_lint, FutureIncompatibleInfo, EarlyLint, IntoEarlyLint}; /// Specification of a single lint. #[derive(Copy, Clone, Debug)] diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 3af0b7f27dd7..b4dadbf7961f 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -258,16 +258,25 @@ impl Session { pub fn unimpl(&self, msg: &str) -> ! { self.diagnostic().unimpl(msg) } - pub fn add_lint(&self, - lint: &'static lint::Lint, - id: ast::NodeId, - sp: Span, - msg: M) { + pub fn add_lint(&self, + lint: &'static lint::Lint, + id: ast::NodeId, + sp: Span, + msg: String) + { + self.add_lint_diagnostic(lint, id, (sp, &msg[..])) + } + pub fn add_lint_diagnostic(&self, + lint: &'static lint::Lint, + id: ast::NodeId, + msg: M) + where M: lint::IntoEarlyLint, + { let lint_id = lint::LintId::of(lint); let mut lints = self.lints.borrow_mut(); - let early_lint = lint::EarlyLint::new(lint_id, sp, msg); + let early_lint = msg.into_early_lint(lint_id); if let Some(arr) = lints.get_mut(&id) { - if !arr.iter().any(|l| l.matches(&early_lint)) { + if !arr.contains(&early_lint) { arr.push(early_lint); } return; diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index c378d5f8d5b3..0f37daa51964 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -6,7 +6,7 @@ use std::fmt; use syntax_pos::{MultiSpan, Span}; #[must_use] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct Diagnostic { pub level: Level, pub message: String, @@ -16,7 +16,7 @@ pub struct Diagnostic { } /// For example a note attached to an error. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct SubDiagnostic { pub level: Level, pub message: String, diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index d9ab0dd075be..badee66b83de 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -57,7 +57,7 @@ mod lock; use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION}; use syntax_pos::MacroBacktrace; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum RenderSpan { /// A FullSpan renders with both with an initial line for the /// message, prefixed by file:linenum, followed by a summary of @@ -71,7 +71,7 @@ pub enum RenderSpan { Suggestion(CodeSuggestion), } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct CodeSuggestion { pub msp: MultiSpan, pub substitutes: Vec,