use dep_graph::DepNode;
use middle::privacy::AccessLevels;
-use middle::ty;
+use ty::TyCtxt;
use session::{config, early_error, Session};
use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass};
use lint::{EarlyLintPass, EarlyLintPassObject, LateLintPass, LateLintPassObject};
use std::cmp;
use std::default::Default as StdDefault;
use std::mem;
-use syntax::ast_util::{self, IdVisitingOperation};
use syntax::attr::{self, AttrMetaMethods};
use syntax::codemap::Span;
use syntax::errors::DiagnosticBuilder;
use syntax::parse::token::InternedString;
use syntax::ast;
use syntax::attr::ThinAttributesExt;
-use rustc_front::hir;
-use rustc_front::util;
-use rustc_front::intravisit as hir_visit;
+use hir;
+use hir::intravisit as hir_visit;
+use hir::intravisit::{IdVisitor, IdVisitingOperation};
use syntax::visit as ast_visit;
/// Information about the registered lints.
// We load builtin lints first, so a duplicate is a compiler bug.
// Use early_error when handling -W help with no crate.
(None, _) => early_error(config::ErrorOutputType::default(), &msg[..]),
- (Some(sess), false) => sess.bug(&msg[..]),
+ (Some(_), false) => bug!("{}", msg),
// A duplicate name from a plugin is a user error.
(Some(sess), true) => sess.err(&msg[..]),
// We load builtin lints first, so a duplicate is a compiler bug.
// Use early_error when handling -W help with no crate.
(None, _) => early_error(config::ErrorOutputType::default(), &msg[..]),
- (Some(sess), false) => sess.bug(&msg[..]),
+ (Some(_), false) => bug!("{}", msg),
// A duplicate name from a plugin is a user error.
(Some(sess), true) => sess.err(&msg[..]),
pub fn register_renamed(&mut self, old_name: &str, new_name: &str) {
let target = match self.by_name.get(new_name) {
Some(&Id(lint_id)) => lint_id.clone(),
- _ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
+ _ => bug!("invalid lint renaming of {} to {}", old_name, new_name)
};
self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target));
}
/// Context for lint checking after type checking.
pub struct LateContext<'a, 'tcx: 'a> {
/// Type context we're checking in.
- pub tcx: &'a ty::ctxt<'tcx>,
+ pub tcx: &'a TyCtxt<'tcx>,
/// The crate being checked.
pub krate: &'a hir::Crate,
format!("{} [-{} {}]", msg,
match level {
Warn => 'W', Deny => 'D', Forbid => 'F',
- Allow => panic!()
+ Allow => bug!()
}, name.replace("_", "-"))
},
Node(src) => {
(Warn, None) => sess.struct_warn(&msg[..]),
(Deny, Some(sp)) => sess.struct_span_err(sp, &msg[..]),
(Deny, None) => sess.struct_err(&msg[..]),
- _ => sess.bug("impossible level in raw_emit_lint"),
+ _ => bug!("impossible level in raw_emit_lint"),
};
// Check for future incompatibility lints and issue a stronger warning.
fn level_src(&self, lint: &'static Lint) -> Option<LevelSource> {
self.lints().levels.get(&LintId::of(lint)).map(|ls| match ls {
- &(Warn, src) => {
+ &(Warn, _) => {
let lint_id = LintId::of(builtin::WARNINGS);
- (self.lints().get_level_source(lint_id).0, src)
+ let warn_src = self.lints().get_level_source(lint_id);
+ if warn_src.0 != Warn {
+ warn_src
+ } else {
+ *ls
+ }
}
_ => *ls
})
level_stack: vec![],
}
}
-
- fn visit_ids<F>(&mut self, f: F)
- where F: FnOnce(&mut ast_util::IdVisitor<EarlyContext>)
- {
- let mut v = ast_util::IdVisitor {
- operation: self,
- visited_outermost: false,
- };
- f(&mut v);
- }
}
impl<'a, 'tcx> LateContext<'a, 'tcx> {
- fn new(tcx: &'a ty::ctxt<'tcx>,
+ fn new(tcx: &'a TyCtxt<'tcx>,
krate: &'a hir::Crate,
access_levels: &'a AccessLevels) -> LateContext<'a, 'tcx> {
// We want to own the lint store, so move it out of the session.
}
fn visit_ids<F>(&mut self, f: F)
- where F: FnOnce(&mut util::IdVisitor<LateContext>)
+ where F: FnOnce(&mut IdVisitor<LateContext>)
{
- let mut v = util::IdVisitor::new(self);
+ let mut v = IdVisitor::new(self);
f(&mut v);
}
}
}
fn visit_struct_field(&mut self, s: &hir::StructField) {
- self.with_lint_attrs(&s.node.attrs, |cx| {
+ self.with_lint_attrs(&s.attrs, |cx| {
run_lints!(cx, check_struct_field, late_passes, s);
hir_visit::walk_struct_field(cx, s);
})
fn visit_item(&mut self, it: &ast::Item) {
self.with_lint_attrs(&it.attrs, |cx| {
run_lints!(cx, check_item, early_passes, it);
- cx.visit_ids(|v| v.visit_item(it));
ast_visit::walk_item(cx, it);
run_lints!(cx, check_item_post, early_passes, it);
})
}
fn visit_struct_field(&mut self, s: &ast::StructField) {
- self.with_lint_attrs(&s.node.attrs, |cx| {
+ self.with_lint_attrs(&s.attrs, |cx| {
run_lints!(cx, check_struct_field, early_passes, s);
ast_visit::walk_struct_field(cx, s);
})
fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
self.with_lint_attrs(&trait_item.attrs, |cx| {
run_lints!(cx, check_trait_item, early_passes, trait_item);
- cx.visit_ids(|v| v.visit_trait_item(trait_item));
ast_visit::walk_trait_item(cx, trait_item);
run_lints!(cx, check_trait_item_post, early_passes, trait_item);
});
fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
self.with_lint_attrs(&impl_item.attrs, |cx| {
run_lints!(cx, check_impl_item, early_passes, impl_item);
- cx.visit_ids(|v| v.visit_impl_item(impl_item));
ast_visit::walk_impl_item(cx, impl_item);
run_lints!(cx, check_impl_item_post, early_passes, impl_item);
});
}
}
}
-impl<'a> IdVisitingOperation for EarlyContext<'a> {
- fn visit_id(&mut self, id: ast::NodeId) {
- match self.sess.lints.borrow_mut().remove(&id) {
- None => {}
- Some(lints) => {
- for (lint_id, span, msg) in lints {
- self.span_lint(lint_id.lint, span, &msg[..])
- }
- }
- }
- }
-}
// This lint pass is defined here because it touches parts of the `LateContext`
// that we don't want to expose. It records the lint level at certain AST
}
}
-enum CheckLintNameResult<'a> {
+enum CheckLintNameResult {
Ok,
// Lint doesn't exist
NoLint,
- // The lint is either renamed or removed and a warning was
- // generated in the DiagnosticBuilder
- Mentioned(DiagnosticBuilder<'a>)
+ // The lint is either renamed or removed. This is the warning
+ // message.
+ Warning(String)
}
/// Checks the name of a lint for its existence, and whether it was
/// it emits non-fatal warnings and there are *two* lint passes that
/// inspect attributes, this is only run from the late pass to avoid
/// printing duplicate warnings.
-fn check_lint_name<'a>(sess: &'a Session,
- lint_cx: &LintStore,
- lint_name: &str,
- span: Option<Span>) -> CheckLintNameResult<'a> {
+fn check_lint_name(lint_cx: &LintStore,
+ lint_name: &str) -> CheckLintNameResult {
match lint_cx.by_name.get(lint_name) {
Some(&Renamed(ref new_name, _)) => {
- let warning = format!("lint {} has been renamed to {}",
- lint_name, new_name);
- let db = match span {
- Some(span) => sess.struct_span_warn(span, &warning[..]),
- None => sess.struct_warn(&warning[..]),
- };
- CheckLintNameResult::Mentioned(db)
+ CheckLintNameResult::Warning(
+ format!("lint {} has been renamed to {}", lint_name, new_name)
+ )
},
Some(&Removed(ref reason)) => {
- let warning = format!("lint {} has been removed: {}", lint_name, reason);
- let db = match span {
- Some(span) => sess.struct_span_warn(span, &warning[..]),
- None => sess.struct_warn(&warning[..])
- };
- CheckLintNameResult::Mentioned(db)
+ CheckLintNameResult::Warning(
+ format!("lint {} has been removed: {}", lint_name, reason)
+ )
},
None => {
match lint_cx.lint_groups.get(lint_name) {
continue;
}
Ok((lint_name, _, span)) => {
- match check_lint_name(&cx.tcx.sess, &cx.lints, &lint_name[..], Some(span)) {
+ match check_lint_name(&cx.lints,
+ &lint_name[..]) {
CheckLintNameResult::Ok => (),
- CheckLintNameResult::Mentioned(mut db) => {
- db.emit();
+ CheckLintNameResult::Warning(ref msg) => {
+ cx.span_lint(builtin::RENAMED_AND_REMOVED_LINTS,
+ span, msg);
}
CheckLintNameResult::NoLint => {
cx.span_lint(builtin::UNKNOWN_LINTS, span,
// Checks the validity of lint names derived from the command line
fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore,
lint_name: &str, level: Level) {
- let db = match check_lint_name(sess, lint_cx, lint_name, None) {
+ let db = match check_lint_name(lint_cx, lint_name) {
CheckLintNameResult::Ok => None,
- CheckLintNameResult::Mentioned(db) => Some(db),
+ CheckLintNameResult::Warning(ref msg) => {
+ Some(sess.struct_warn(msg))
+ },
CheckLintNameResult::NoLint => {
Some(sess.struct_err(&format!("unknown lint: `{}`", lint_name)))
}
/// Perform lint checking on a crate.
///
/// Consumes the `lint_store` field of the `Session`.
-pub fn check_crate(tcx: &ty::ctxt, access_levels: &AccessLevels) {
+pub fn check_crate(tcx: &TyCtxt, access_levels: &AccessLevels) {
let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck);
let krate = tcx.map.krate();
// in the iteration code.
for (id, v) in tcx.sess.lints.borrow().iter() {
for &(lint, span, ref msg) in v {
- tcx.sess.span_bug(span,
- &format!("unprocessed lint {} at {}: {}",
- lint.as_str(), tcx.map.node_to_string(*id), *msg))
+ span_bug!(span,
+ "unprocessed lint {} at {}: {}",
+ lint.as_str(), tcx.map.node_to_string(*id), *msg)
}
}
*tcx.node_lint_levels.borrow_mut() = cx.node_levels.into_inner();
+
+ // Put the lint store back in the session.
+ mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), cx.lints);
}
pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
// Visit the whole crate.
cx.with_lint_attrs(&krate.attrs, |cx| {
- cx.visit_id(ast::CRATE_NODE_ID);
- cx.visit_ids(|v| {
- v.visited_outermost = true;
- ast_visit::walk_crate(v, krate);
- });
+ // Lints may be assigned to the whole crate.
+ if let Some(lints) = cx.sess.lints.borrow_mut().remove(&ast::CRATE_NODE_ID) {
+ for (lint_id, span, msg) in lints {
+ cx.span_lint(lint_id.lint, span, &msg[..])
+ }
+ }
// since the root module isn't visited as an item (because it isn't an
// item), warn for it here.
// in the iteration code.
for (_, v) in sess.lints.borrow().iter() {
for &(lint, span, ref msg) in v {
- sess.span_bug(span,
- &format!("unprocessed lint {}: {}",
- lint.as_str(), *msg))
+ span_bug!(span, "unprocessed lint {}: {}", lint.as_str(), *msg)
}
}
}