1
Fork 0

Add ability for hardwired lints to operate on the diagnostic builder

This commit is contained in:
Manish Goregaokar 2018-02-22 22:34:06 -08:00
parent 3eeabe7b7d
commit bd29696218
4 changed files with 59 additions and 5 deletions

View file

@ -14,8 +14,11 @@
//! compiler code, rather than using their own custom pass. Those //! compiler code, rather than using their own custom pass. Those
//! lints are all available in `rustc_lint::builtin`. //! lints are all available in `rustc_lint::builtin`.
use errors::DiagnosticBuilder;
use lint::{LintPass, LateLintPass, LintArray}; use lint::{LintPass, LateLintPass, LintArray};
use session::Session;
use session::config::Epoch; use session::config::Epoch;
use syntax::codemap::Span;
declare_lint! { declare_lint! {
pub CONST_ERR, 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 <type>")
};
db.span_suggestion(span, "use `dyn`", sugg);
}
}
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {} impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {}

View file

@ -29,6 +29,7 @@ use self::TargetLint::*;
use std::slice; use std::slice;
use lint::{EarlyLintPassObject, LateLintPassObject}; use lint::{EarlyLintPassObject, LateLintPassObject};
use lint::{Level, Lint, LintId, LintPass, LintBuffer}; use lint::{Level, Lint, LintId, LintPass, LintBuffer};
use lint::builtin::BuiltinLintDiagnostics;
use lint::levels::{LintLevelSets, LintLevelsBuilder}; use lint::levels::{LintLevelSets, LintLevelsBuilder};
use middle::privacy::AccessLevels; use middle::privacy::AccessLevels;
use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
@ -92,6 +93,7 @@ pub struct BufferedEarlyLint {
pub ast_id: ast::NodeId, pub ast_id: ast::NodeId,
pub span: MultiSpan, pub span: MultiSpan,
pub msg: String, pub msg: String,
pub diagnostic: BuiltinLintDiagnostics,
} }
/// Extra information for a future incompatibility lint. See the call /// 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(); self.lookup(lint, span, msg).emit();
} }
fn lookup_and_emit_with_diagnostics<S: Into<MultiSpan>>(&self,
lint: &'static Lint,
span: Option<S>,
msg: &str,
diagnostic: BuiltinLintDiagnostics) {
let mut db = self.lookup(lint, span, msg);
diagnostic.run(self.sess(), &mut db);
db.emit();
}
fn lookup<S: Into<MultiSpan>>(&self, fn lookup<S: Into<MultiSpan>>(&self,
lint: &'static Lint, lint: &'static Lint,
span: Option<S>, span: Option<S>,
@ -516,9 +528,10 @@ impl<'a> EarlyContext<'a> {
fn check_id(&mut self, id: ast::NodeId) { fn check_id(&mut self, id: ast::NodeId) {
for early_lint in self.buffered.take(id) { for early_lint in self.buffered.take(id) {
self.lookup_and_emit(early_lint.lint_id.lint, self.lookup_and_emit_with_diagnostics(early_lint.lint_id.lint,
Some(early_lint.span.clone()), Some(early_lint.span.clone()),
&early_lint.msg); &early_lint.msg,
early_lint.diagnostic);
} }
} }
} }

View file

@ -37,6 +37,7 @@ use errors::{DiagnosticBuilder, DiagnosticId};
use hir::def_id::{CrateNum, LOCAL_CRATE}; use hir::def_id::{CrateNum, LOCAL_CRATE};
use hir::intravisit::{self, FnKind}; use hir::intravisit::{self, FnKind};
use hir; use hir;
use lint::builtin::BuiltinLintDiagnostics;
use session::{config, Session, DiagnosticMessageId}; use session::{config, Session, DiagnosticMessageId};
use std::hash; use std::hash;
use syntax::ast; use syntax::ast;
@ -399,12 +400,14 @@ impl LintBuffer {
lint: &'static Lint, lint: &'static Lint,
id: ast::NodeId, id: ast::NodeId,
sp: MultiSpan, sp: MultiSpan,
msg: &str) { msg: &str,
diagnostic: BuiltinLintDiagnostics) {
let early_lint = BufferedEarlyLint { let early_lint = BufferedEarlyLint {
lint_id: LintId::of(lint), lint_id: LintId::of(lint),
ast_id: id, ast_id: id,
span: sp, span: sp,
msg: msg.to_string(), msg: msg.to_string(),
diagnostic
}; };
let arr = self.map.entry(id).or_insert(Vec::new()); let arr = self.map.entry(id).or_insert(Vec::new());
if !arr.contains(&early_lint) { if !arr.contains(&early_lint) {

View file

@ -16,6 +16,7 @@ use ich::Fingerprint;
use ich; use ich;
use lint; use lint;
use lint::builtin::BuiltinLintDiagnostics;
use middle::allocator::AllocatorKind; use middle::allocator::AllocatorKind;
use middle::dependency_format; use middle::dependency_format;
use session::search_paths::PathKind; use session::search_paths::PathKind;
@ -341,7 +342,18 @@ impl Session {
sp: S, sp: S,
msg: &str) { msg: &str) {
match *self.buffered_lints.borrow_mut() { 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<S: Into<MultiSpan>>(&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"), None => bug!("can't buffer lints after HIR lowering"),
} }
} }