diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 2b1ff8a0e78..cc7c5dc0666 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -14,8 +14,11 @@ //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. +use errors::DiagnosticBuilder; use lint::{LintPass, LateLintPass, LintArray}; +use session::Session; use session::config::Epoch; +use syntax::codemap::Span; declare_lint! { pub CONST_ERR, @@ -312,4 +315,27 @@ impl LintPass for HardwiredLints { } } +// this could be a closure, but then implementing derive traits +// becomes hacky (and it gets allocated) +#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] +pub enum BuiltinLintDiagnostics { + Normal, + BareTraitObject(Span) +} + +impl BuiltinLintDiagnostics { + pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) { + match self { + BuiltinLintDiagnostics::Normal => (), + BuiltinLintDiagnostics::BareTraitObject(span) => { + let sugg = match sess.codemap().span_to_snippet(span) { + Ok(s) => format!("dyn {}", s), + Err(_) => format!("dyn ") + }; + db.span_suggestion(span, "use `dyn`", sugg); + } + } + } +} + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {} diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 870b52c221f..a9c023d1430 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -29,6 +29,7 @@ use self::TargetLint::*; use std::slice; use lint::{EarlyLintPassObject, LateLintPassObject}; use lint::{Level, Lint, LintId, LintPass, LintBuffer}; +use lint::builtin::BuiltinLintDiagnostics; use lint::levels::{LintLevelSets, LintLevelsBuilder}; use middle::privacy::AccessLevels; use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; @@ -92,6 +93,7 @@ pub struct BufferedEarlyLint { pub ast_id: ast::NodeId, pub span: MultiSpan, pub msg: String, + pub diagnostic: BuiltinLintDiagnostics, } /// Extra information for a future incompatibility lint. See the call @@ -446,6 +448,16 @@ pub trait LintContext<'tcx>: Sized { self.lookup(lint, span, msg).emit(); } + fn lookup_and_emit_with_diagnostics>(&self, + lint: &'static Lint, + span: Option, + msg: &str, + diagnostic: BuiltinLintDiagnostics) { + let mut db = self.lookup(lint, span, msg); + diagnostic.run(self.sess(), &mut db); + db.emit(); + } + fn lookup>(&self, lint: &'static Lint, span: Option, @@ -516,9 +528,10 @@ impl<'a> EarlyContext<'a> { fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.buffered.take(id) { - self.lookup_and_emit(early_lint.lint_id.lint, - Some(early_lint.span.clone()), - &early_lint.msg); + self.lookup_and_emit_with_diagnostics(early_lint.lint_id.lint, + Some(early_lint.span.clone()), + &early_lint.msg, + early_lint.diagnostic); } } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index e28cc9c201d..a51d06c06ed 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -37,6 +37,7 @@ use errors::{DiagnosticBuilder, DiagnosticId}; use hir::def_id::{CrateNum, LOCAL_CRATE}; use hir::intravisit::{self, FnKind}; use hir; +use lint::builtin::BuiltinLintDiagnostics; use session::{config, Session, DiagnosticMessageId}; use std::hash; use syntax::ast; @@ -399,12 +400,14 @@ impl LintBuffer { lint: &'static Lint, id: ast::NodeId, sp: MultiSpan, - msg: &str) { + msg: &str, + diagnostic: BuiltinLintDiagnostics) { let early_lint = BufferedEarlyLint { lint_id: LintId::of(lint), ast_id: id, span: sp, msg: msg.to_string(), + diagnostic }; let arr = self.map.entry(id).or_insert(Vec::new()); if !arr.contains(&early_lint) { diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 6901674a6cf..7041efbd5bc 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -16,6 +16,7 @@ use ich::Fingerprint; use ich; use lint; +use lint::builtin::BuiltinLintDiagnostics; use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; @@ -341,7 +342,18 @@ impl Session { sp: S, msg: &str) { match *self.buffered_lints.borrow_mut() { - Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), msg), + Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), + msg, BuiltinLintDiagnostics::Normal), + None => bug!("can't buffer lints after HIR lowering"), + } + } + + pub fn buffer_lint_with_diagnostic>(&self, + lint: &'static lint::Lint, id: ast::NodeId, sp: S, + msg: &str, diagnostic: BuiltinLintDiagnostics) { + match *self.buffered_lints.borrow_mut() { + Some(ref mut buffer) => buffer.add_lint(lint, id, sp.into(), + msg, diagnostic), None => bug!("can't buffer lints after HIR lowering"), } }