From f05f6cff963d6871d9de294e423e066326ee8aa1 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Fri, 30 Aug 2013 15:26:16 -0400 Subject: [PATCH 1/3] Allow a reason="foo" in lint attributes Also add a lint that asserts that all lint attributes have a reason (allow by default). Closes #3358 --- src/librustc/middle/lint.rs | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 6f4d94e2a647a..93266bb09dcc3 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -81,6 +81,7 @@ pub enum lint { while_true, path_statement, unrecognized_lint, + no_lint_reason, non_camel_case_types, non_uppercase_statics, type_limits, @@ -123,7 +124,7 @@ pub enum level { pub struct LintSpec { lint: lint, desc: &'static str, - default: level + default: level, } impl Ord for LintSpec { @@ -195,6 +196,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[ default: warn }), + ("no_lint_reason", + LintSpec { + lint: no_lint_reason, + desc: "lint setting without a reason", + default: allow, + }), + ("non_camel_case_types", LintSpec { lint: non_camel_case_types, @@ -479,7 +487,7 @@ impl Context { // of what we changed so we can roll everything back after invoking the // specified closure let mut pushed = 0u; - do each_lint(self.tcx.sess, attrs) |meta, level, lintname| { + do each_lint(self.tcx.sess, attrs, self) |meta, level, lintname| { match self.dict.find_equiv(&lintname) { None => { self.span_lint( @@ -489,6 +497,8 @@ impl Context { level_to_str(level), lintname)); } Some(lint) => { + error!(meta); + error!(attrs); let lint = lint.lint; let now = self.get_level(lint); if now == forbid && level != forbid { @@ -605,16 +615,18 @@ impl Context { pub fn each_lint(sess: session::Session, attrs: &[ast::Attribute], + cx: @mut Context, f: &fn(@ast::MetaItem, level, @str) -> bool) -> bool { let xs = [allow, warn, deny, forbid]; for &level in xs.iter() { let level_name = level_to_str(level); for attr in attrs.iter().filter(|m| level_name == m.name()) { + let mut found_reason = false; let meta = attr.node.value; let metas = match meta.node { ast::MetaList(_, ref metas) => metas, _ => { - sess.span_err(meta.span, "malformed lint attribute"); + sess.span_err(meta.span, "malformed lint attribute: not a list"); loop; } }; @@ -624,14 +636,26 @@ pub fn each_lint(sess: session::Session, if !f(*meta, level, lintname) { return false; } - } + }, + ast::MetaNameValue(n, _v) => { + if "reason" != n { + sess.span_err(meta.span, + "malformed lint attribute: unrecognized name/value pair"); + } else { + found_reason = true; + } + }, _ => { - sess.span_err(meta.span, "malformed lint attribute"); + sess.span_err(meta.span, "malformed lint attribute: not a word"); } } } + if !found_reason { + cx.span_lint(no_lint_reason, meta.span, "lint attribute without reason"); + } } } + true } From bfe5285bd4c272c39ebea126f8e46d23f4c01150 Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Fri, 6 Sep 2013 13:25:01 -0400 Subject: [PATCH 2/3] Add a no_lint_reason test --- src/test/compile-fail/lint-reason.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/compile-fail/lint-reason.rs diff --git a/src/test/compile-fail/lint-reason.rs b/src/test/compile-fail/lint-reason.rs new file mode 100644 index 0000000000000..5cecfa3cb571f --- /dev/null +++ b/src/test/compile-fail/lint-reason.rs @@ -0,0 +1,14 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[deny(no_lint_reason, reason="why not?")]; +#[deny(heap_memory)]; //~ ERROR lint attribute without reason + +fn main() { } From 6c0d0d2fbac3315b4ec0c6dc08d3ef730507235b Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Sat, 7 Sep 2013 18:27:23 -0400 Subject: [PATCH 3/3] Add a scoping test for the lint-reason lint --- src/test/run-pass/lint-reason.rs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/test/run-pass/lint-reason.rs diff --git a/src/test/run-pass/lint-reason.rs b/src/test/run-pass/lint-reason.rs new file mode 100644 index 0000000000000..1ab1e761c75a8 --- /dev/null +++ b/src/test/run-pass/lint-reason.rs @@ -0,0 +1,8 @@ +#[deny(no_lint_reason, reason="")]; + +#[allow(no_lint_reason, reason="")] +mod foo { + #[warn(unused_unsafe)]; +} + +fn main() { }