diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 64056ece98770..4c5ee4230c790 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -68,6 +68,12 @@ declare_lint! { "detect assignments that will never be read" } +declare_lint! { + pub UNUSED_ATTRIBUTES, + Warn, + "detects attributes that were not used by the compiler" +} + declare_lint! { pub DEAD_CODE, Warn, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 0633286e39838..5fcc316243f5b 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -707,6 +707,7 @@ impl<'a> LintContext<'a> for EarlyContext<'a> { f: F) where F: FnOnce(&mut Self) { + info!("ZMD A with_lint_attrs {:?} ", attrs.iter().map(|a| (a.id, a.path.clone())).collect::>()); let push = self.builder.push(attrs); self.check_id(id); self.enter_attrs(attrs); diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 8765fd855ebf2..93951ea4ce8ac 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -24,6 +24,7 @@ use syntax::attr; use syntax::feature_gate; use syntax::source_map::MultiSpan; use syntax::symbol::Symbol; +use syntax_pos::Span; use util::nodemap::FxHashMap; pub struct LintLevelSets { @@ -196,12 +197,22 @@ impl<'a> LintLevelsBuilder<'a> { /// /// Don't forget to call `pop`! pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { + info!("ZMD B push called with {:?}", attrs); let mut specs = FxHashMap(); let store = self.sess.lint_store.borrow(); let sess = self.sess; let bad_attr = |span| { struct_span_err!(sess, span, E0452, "malformed lint attribute") }; + let empty_attr = |span: Span, specs| { + let lint = builtin::UNUSED_ATTRIBUTES; + let (level, src) = self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess); + let sp = Some(span.into()); + let msg = "empty lint attribute is unused"; + info!("ZMD C empty-attr being called on {:?} {:?} {:?}", level, src, sp); + lint::struct_lint_level(sess, lint, level, src, sp, msg) + }; + for attr in attrs { let level = match Level::from_str(&attr.name().as_str()) { None => continue, @@ -216,9 +227,15 @@ impl<'a> LintLevelsBuilder<'a> { } else { let mut err = bad_attr(meta.span); err.emit(); - continue + continue; }; + if metas.is_empty() { + let mut err = empty_attr(attr.span, specs.clone()); + err.emit(); + continue; + } + // Before processing the lint names, look for a reason (RFC 2383) // at the end. let mut reason = None; @@ -231,6 +248,13 @@ impl<'a> LintLevelsBuilder<'a> { if item.ident == "reason" { // found reason, reslice meta list to exclude it metas = &metas[0..metas.len()-1]; + // ... but also notice if we thereby don't have any lint names + // left (attribute was `#[level(reason = "foo")]`) + if metas.is_empty() { + let mut err = empty_attr(attr.span, specs.clone()); + err.emit(); + continue; + } if let ast::LitKind::Str(rationale, _) = name_value.node { if gate_reasons { feature_gate::emit_feature_err( diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 0a6ffc98d2fe5..644fee5375c6f 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -463,7 +463,7 @@ impl Level { } /// How a lint level was set. -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum LintSource { /// Lint is at the default level as declared /// in rustc or a plugin. diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 7d178d2096720..7aebf3953c398 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -10,10 +10,13 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; + use rustc::ty; use rustc::ty::adjustment; -use lint::{LateContext, EarlyContext, LintContext, LintArray}; -use lint::{LintPass, EarlyLintPass, LateLintPass}; +use lint::{ + LateContext, EarlyContext, LintContext, LintArray, LintPass, EarlyLintPass, LateLintPass, + builtin::UNUSED_ATTRIBUTES +}; use syntax::ast; use syntax::attr; @@ -195,12 +198,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements { } } -declare_lint! { - pub UNUSED_ATTRIBUTES, - Warn, - "detects attributes that were not used by the compiler" -} - #[derive(Copy, Clone)] pub struct UnusedAttributes;