Skip to content

Commit 7808fdd

Browse files
authored
Rollup merge of #42874 - zackmdavis:overzealous_by_outer_forbid, r=nikomatsakis
only set "overruled by outer forbid" once for lint groups, by group name Previously, conflicting forbid/allow attributes for a lint group would result in a separate "allow(L) overruled by outer forbid(L)" error for every lint L in the group. This was needlessly and annoyingly verbose; we prefer to just have one error pointing out the conflicting attributes. (Also, while we're touching context.rs, clean up some unused arguments.) Resolves #42873.
2 parents b1afcb6 + 890a76f commit 7808fdd

File tree

3 files changed

+73
-17
lines changed

3 files changed

+73
-17
lines changed

src/librustc/lint/context.rs

+22-17
Original file line numberDiff line numberDiff line change
@@ -291,16 +291,13 @@ impl LintStore {
291291
self.by_name.insert(name.into(), Removed(reason.into()));
292292
}
293293

294-
#[allow(unused_variables)]
295-
fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
296-
-> Result<LintId, FindLintError>
297-
{
294+
fn find_lint(&self, lint_name: &str) -> Result<LintId, FindLintError> {
298295
match self.by_name.get(lint_name) {
299296
Some(&Id(lint_id)) => Ok(lint_id),
300297
Some(&Renamed(_, lint_id)) => {
301298
Ok(lint_id)
302299
},
303-
Some(&Removed(ref reason)) => {
300+
Some(&Removed(_)) => {
304301
Err(FindLintError::Removed)
305302
},
306303
None => Err(FindLintError::NotFound)
@@ -313,7 +310,7 @@ impl LintStore {
313310
&lint_name[..], level);
314311

315312
let lint_flag_val = Symbol::intern(&lint_name);
316-
match self.find_lint(&lint_name[..], sess, None) {
313+
match self.find_lint(&lint_name[..]) {
317314
Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))),
318315
Err(FindLintError::Removed) => { }
319316
Err(_) => {
@@ -724,21 +721,22 @@ pub trait LintContext<'tcx>: Sized {
724721
let mut pushed = 0;
725722

726723
for result in gather_attrs(attrs) {
727-
let v = match result {
724+
let (is_group, lint_level_spans) = match result {
728725
Err(span) => {
729726
span_err!(self.sess(), span, E0452,
730727
"malformed lint attribute");
731728
continue;
732729
}
733730
Ok((lint_name, level, span)) => {
734-
match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) {
735-
Ok(lint_id) => vec![(lint_id, level, span)],
731+
match self.lints().find_lint(&lint_name.as_str()) {
732+
Ok(lint_id) => (false, vec![(lint_id, level, span)]),
736733
Err(FindLintError::NotFound) => {
737734
match self.lints().lint_groups.get(&*lint_name.as_str()) {
738-
Some(&(ref v, _)) => v.iter()
735+
Some(&(ref v, _)) => (true,
736+
v.iter()
739737
.map(|lint_id: &LintId|
740738
(*lint_id, level, span))
741-
.collect(),
739+
.collect()),
742740
None => {
743741
// The lint or lint group doesn't exist.
744742
// This is an error, but it was handled
@@ -754,14 +752,18 @@ pub trait LintContext<'tcx>: Sized {
754752

755753
let lint_attr_name = result.expect("lint attribute should be well-formed").0;
756754

757-
for (lint_id, level, span) in v {
755+
for (lint_id, level, span) in lint_level_spans {
758756
let (now, now_source) = self.lint_sess().get_source(lint_id);
759757
if now == Forbid && level != Forbid {
760-
let lint_name = lint_id.to_string();
758+
let forbidden_lint_name = match now_source {
759+
LintSource::Default => lint_id.to_string(),
760+
LintSource::Node(name, _) => name.to_string(),
761+
LintSource::CommandLine(name) => name.to_string(),
762+
};
761763
let mut diag_builder = struct_span_err!(self.sess(), span, E0453,
762764
"{}({}) overruled by outer forbid({})",
763-
level.as_str(), lint_name,
764-
lint_name);
765+
level.as_str(), lint_attr_name,
766+
forbidden_lint_name);
765767
diag_builder.span_label(span, "overruled by previous forbid");
766768
match now_source {
767769
LintSource::Default => &mut diag_builder,
@@ -772,7 +774,10 @@ pub trait LintContext<'tcx>: Sized {
772774
LintSource::CommandLine(_) => {
773775
diag_builder.note("`forbid` lint level was set on command line")
774776
}
775-
}.emit()
777+
}.emit();
778+
if is_group { // don't set a separate error for every lint in the group
779+
break;
780+
}
776781
} else if now != level {
777782
let cx = self.lint_sess_mut();
778783
cx.stack.push((lint_id, (now, now_source)));
@@ -1420,7 +1425,7 @@ impl Decodable for LintId {
14201425
fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
14211426
let s = d.read_str()?;
14221427
ty::tls::with(|tcx| {
1423-
match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) {
1428+
match tcx.sess.lint_store.borrow().find_lint(&s) {
14241429
Ok(id) => Ok(id),
14251430
Err(_) => panic!("invalid lint-id `{}`", s),
14261431
}

src/test/ui/lint/outer-forbid.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Forbidding a group (here, `unused`) overrules subsequent allowance of both
12+
// the group, and an individual lint in the group (here, `unused_variables`);
13+
// and, forbidding an individual lint (here, `non_snake_case`) overrules
14+
// subsequent allowance of a lint group containing it (here, `bad_style`). See
15+
// Issue #42873.
16+
17+
#![forbid(unused, non_snake_case)]
18+
19+
#[allow(unused, unused_variables, bad_style)]
20+
fn main() {
21+
println!("hello forbidden world")
22+
}

src/test/ui/lint/outer-forbid.stderr

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0453]: allow(unused) overruled by outer forbid(unused)
2+
--> $DIR/outer-forbid.rs:19:9
3+
|
4+
17 | #![forbid(unused, non_snake_case)]
5+
| ------ `forbid` level set here
6+
18 |
7+
19 | #[allow(unused, unused_variables, bad_style)]
8+
| ^^^^^^ overruled by previous forbid
9+
10+
error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
11+
--> $DIR/outer-forbid.rs:19:17
12+
|
13+
17 | #![forbid(unused, non_snake_case)]
14+
| ------ `forbid` level set here
15+
18 |
16+
19 | #[allow(unused, unused_variables, bad_style)]
17+
| ^^^^^^^^^^^^^^^^ overruled by previous forbid
18+
19+
error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case)
20+
--> $DIR/outer-forbid.rs:19:35
21+
|
22+
17 | #![forbid(unused, non_snake_case)]
23+
| -------------- `forbid` level set here
24+
18 |
25+
19 | #[allow(unused, unused_variables, bad_style)]
26+
| ^^^^^^^^^ overruled by previous forbid
27+
28+
error: aborting due to previous error(s)
29+

0 commit comments

Comments
 (0)