Skip to content

Commit a74d647

Browse files
committed
rustc: Fix bugs in renamed and removed lints and re-add raw_pointer_derive
cc #30346 Conflicts: src/librustc_lint/lib.rs
1 parent 3e81984 commit a74d647

10 files changed

+269
-38
lines changed

src/librustc/lint/builtin.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ declare_lint! {
127127
"unit struct or enum variant erroneously allowed to match via path::ident(..)"
128128
}
129129

130+
declare_lint! {
131+
pub RAW_POINTER_DERIVE,
132+
Warn,
133+
"uses of #[derive] with raw pointers are rarely correct"
134+
}
135+
130136
/// Does nothing as a lint pass, but registers some `Lint`s
131137
/// which are used by other parts of the compiler.
132138
#[derive(Copy, Clone)]
@@ -152,7 +158,8 @@ impl LintPass for HardwiredLints {
152158
TRIVIAL_CASTS,
153159
TRIVIAL_NUMERIC_CASTS,
154160
MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
155-
CONST_ERR
161+
CONST_ERR,
162+
RAW_POINTER_DERIVE
156163
)
157164
}
158165
}

src/librustc/lint/context.rs

Lines changed: 146 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -218,21 +218,10 @@ impl LintStore {
218218
{
219219
match self.by_name.get(lint_name) {
220220
Some(&Id(lint_id)) => Ok(lint_id),
221-
Some(&Renamed(ref new_name, lint_id)) => {
222-
let warning = format!("lint {} has been renamed to {}",
223-
lint_name, new_name);
224-
match span {
225-
Some(span) => sess.span_warn(span, &warning[..]),
226-
None => sess.warn(&warning[..]),
227-
};
221+
Some(&Renamed(_, lint_id)) => {
228222
Ok(lint_id)
229223
},
230224
Some(&Removed(ref reason)) => {
231-
let warning = format!("lint {} has been removed: {}", lint_name, reason);
232-
match span {
233-
Some(span) => sess.span_warn(span, &warning[..]),
234-
None => sess.warn(&warning[..])
235-
}
236225
Err(FindLintError::Removed)
237226
},
238227
None => Err(FindLintError::NotFound)
@@ -241,8 +230,12 @@ impl LintStore {
241230

242231
pub fn process_command_line(&mut self, sess: &Session) {
243232
for &(ref lint_name, level) in &sess.opts.lint_opts {
233+
check_lint_name_cmdline(sess, self,
234+
&lint_name[..], level);
235+
244236
match self.find_lint(&lint_name[..], sess, None) {
245237
Ok(lint_id) => self.set_level(lint_id, (level, CommandLine)),
238+
Err(FindLintError::Removed) => { }
246239
Err(_) => {
247240
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone()))
248241
.collect::<FnvHashMap<&'static str,
@@ -254,8 +247,11 @@ impl LintStore {
254247
self.set_level(*lint_id, (level, CommandLine)))
255248
.collect::<Vec<()>>();
256249
}
257-
None => sess.err(&format!("unknown {} flag: {}",
258-
level.as_str(), lint_name)),
250+
None => {
251+
// The lint or lint group doesn't exist.
252+
// This is an error, but it was handled
253+
// by check_lint_name_cmdline.
254+
}
259255
}
260256
}
261257
}
@@ -330,29 +326,39 @@ pub fn gather_attrs(attrs: &[ast::Attribute])
330326
-> Vec<Result<(InternedString, Level, Span), Span>> {
331327
let mut out = vec!();
332328
for attr in attrs {
333-
let level = match Level::from_str(&attr.name()) {
334-
None => continue,
335-
Some(lvl) => lvl,
336-
};
329+
let r = gather_attr(attr);
330+
out.extend(r.into_iter());
331+
}
332+
out
333+
}
337334

338-
attr::mark_used(attr);
335+
pub fn gather_attr(attr: &ast::Attribute)
336+
-> Vec<Result<(InternedString, Level, Span), Span>> {
337+
let mut out = vec!();
339338

340-
let meta = &attr.node.value;
341-
let metas = match meta.node {
342-
ast::MetaList(_, ref metas) => metas,
343-
_ => {
344-
out.push(Err(meta.span));
345-
continue;
346-
}
347-
};
339+
let level = match Level::from_str(&attr.name()) {
340+
None => return out,
341+
Some(lvl) => lvl,
342+
};
348343

349-
for meta in metas {
350-
out.push(match meta.node {
351-
ast::MetaWord(ref lint_name) => Ok((lint_name.clone(), level, meta.span)),
352-
_ => Err(meta.span),
353-
});
344+
attr::mark_used(attr);
345+
346+
let meta = &attr.node.value;
347+
let metas = match meta.node {
348+
ast::MetaList(_, ref metas) => metas,
349+
_ => {
350+
out.push(Err(meta.span));
351+
return out;
354352
}
353+
};
354+
355+
for meta in metas {
356+
out.push(match meta.node {
357+
ast::MetaWord(ref lint_name) => Ok((lint_name.clone(), level, meta.span)),
358+
_ => Err(meta.span),
359+
});
355360
}
361+
356362
out
357363
}
358364

@@ -510,9 +516,9 @@ pub trait LintContext: Sized {
510516
(*lint_id, level, span))
511517
.collect(),
512518
None => {
513-
self.span_lint(builtin::UNKNOWN_LINTS, span,
514-
&format!("unknown `{}` attribute: `{}`",
515-
level.as_str(), lint_name));
519+
// The lint or lint group doesn't exist.
520+
// This is an error, but it was handled
521+
// by check_lint_name_attribute.
516522
continue;
517523
}
518524
}
@@ -824,6 +830,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
824830
}
825831

826832
fn visit_attribute(&mut self, attr: &ast::Attribute) {
833+
check_lint_name_attribute(self, attr);
827834
run_lints!(self, check_attribute, late_passes, attr);
828835
}
829836
}
@@ -1037,6 +1044,110 @@ impl LateLintPass for GatherNodeLevels {
10371044
}
10381045
}
10391046

1047+
enum CheckLintNameResult {
1048+
Ok,
1049+
// Lint doesn't exist
1050+
NoLint,
1051+
// The lint is either renamed or removed and a warning was generated
1052+
Mentioned
1053+
}
1054+
1055+
/// Checks the name of a lint for its existence, and whether it was
1056+
/// renamed or removed. Generates a DiagnosticBuilder containing a
1057+
/// warning for renamed and removed lints. This is over both lint
1058+
/// names from attributes and those passed on the command line. Since
1059+
/// it emits non-fatal warnings and there are *two* lint passes that
1060+
/// inspect attributes, this is only run from the late pass to avoid
1061+
/// printing duplicate warnings.
1062+
fn check_lint_name(sess: &Session,
1063+
lint_cx: &LintStore,
1064+
lint_name: &str,
1065+
span: Option<Span>) -> CheckLintNameResult {
1066+
match lint_cx.by_name.get(lint_name) {
1067+
Some(&Renamed(ref new_name, _)) => {
1068+
let warning = format!("lint {} has been renamed to {}",
1069+
lint_name, new_name);
1070+
match span {
1071+
Some(span) => sess.span_warn(span, &warning[..]),
1072+
None => sess.warn(&warning[..]),
1073+
};
1074+
CheckLintNameResult::Mentioned
1075+
},
1076+
Some(&Removed(ref reason)) => {
1077+
let warning = format!("lint {} has been removed: {}", lint_name, reason);
1078+
match span {
1079+
Some(span) => sess.span_warn(span, &warning[..]),
1080+
None => sess.warn(&warning[..])
1081+
};
1082+
CheckLintNameResult::Mentioned
1083+
},
1084+
None => {
1085+
match lint_cx.lint_groups.get(lint_name) {
1086+
None => {
1087+
CheckLintNameResult::NoLint
1088+
}
1089+
Some(_) => {
1090+
/* lint group exists */
1091+
CheckLintNameResult::Ok
1092+
}
1093+
}
1094+
}
1095+
Some(_) => {
1096+
/* lint exists */
1097+
CheckLintNameResult::Ok
1098+
}
1099+
}
1100+
}
1101+
1102+
// Checks the validity of lint names derived from attributes
1103+
fn check_lint_name_attribute(cx: &LateContext, attr: &ast::Attribute) {
1104+
for result in gather_attr(attr) {
1105+
match result {
1106+
Err(_) => {
1107+
// Malformed lint attr. Reported by with_lint_attrs
1108+
continue;
1109+
}
1110+
Ok((lint_name, _, span)) => {
1111+
match check_lint_name(&cx.tcx.sess, &cx.lints, &lint_name[..], Some(span)) {
1112+
CheckLintNameResult::Ok => (),
1113+
CheckLintNameResult::Mentioned => (),
1114+
CheckLintNameResult::NoLint => {
1115+
cx.span_lint(builtin::UNKNOWN_LINTS, span,
1116+
&format!("unknown lint: `{}`",
1117+
lint_name));
1118+
}
1119+
}
1120+
}
1121+
}
1122+
}
1123+
}
1124+
1125+
// Checks the validity of lint names derived from the command line
1126+
fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore,
1127+
lint_name: &str, level: Level) {
1128+
let explain = match check_lint_name(sess, lint_cx, lint_name, None) {
1129+
CheckLintNameResult::Ok => false,
1130+
CheckLintNameResult::Mentioned => true,
1131+
CheckLintNameResult::NoLint => {
1132+
sess.err(&format!("unknown lint: `{}`", lint_name));
1133+
true
1134+
}
1135+
};
1136+
1137+
if explain {
1138+
let msg = format!("requested on the command line with `{} {}`",
1139+
match level {
1140+
Level::Allow => "-A",
1141+
Level::Warn => "-W",
1142+
Level::Deny => "-D",
1143+
Level::Forbid => "-F",
1144+
},
1145+
lint_name);
1146+
sess.note(&msg);
1147+
}
1148+
}
1149+
1150+
10401151
/// Perform lint checking on a crate.
10411152
///
10421153
/// Consumes the `lint_store` field of the `Session`.

src/librustc_lint/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
152152
// We have one lint pass defined specially
153153
store.register_late_pass(sess, false, box lint::GatherNodeLevels);
154154

155-
// Insert temporary renamings for a one-time deprecation
155+
// Register renamed and removed lints
156156
store.register_renamed("unknown_features", "unused_features");
157-
158157
store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
158+
store.register_removed("raw_pointer_derive", "using derive with raw pointers is ok");
159+
// This was renamed to raw_pointer_derive, which was then removed,
160+
// so it is also considered removed
161+
store.register_removed("raw_pointer_deriving", "using derive with raw pointers is ok");
159162
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2016 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+
#![deny = "foo"] //~ ERR malformed lint attribute
12+
#![allow(bar = "baz")] //~ ERR malformed lint attribute
13+
14+
fn main() { }
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2016 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+
// The raw_pointer_derived lint warns about its removal
12+
// cc #30346
13+
14+
// compile-flags:-D raw_pointer_derive
15+
16+
// error-pattern:lint raw_pointer_derive has been removed
17+
// error-pattern:requested on the command line with `-D raw_pointer_derive`
18+
19+
#[deny(warnings)]
20+
fn main() { let unused = (); }

src/test/compile-fail/lint-removed.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2016 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+
// The raw_pointer_derived lint only warns about its own removal
12+
// cc #30346
13+
14+
#[deny(raw_pointer_derive)] //~ WARN raw_pointer_derive has been removed
15+
#[deny(warnings)]
16+
fn main() { let unused = (); } //~ ERR unused
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2016 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+
// compile-flags:-D unknown_features
12+
13+
// error-pattern:lint unknown_features has been renamed to unused_features
14+
// error-pattern:requested on the command line with `-D unknown_features`
15+
// error-pattern:unused
16+
17+
#[deny(unused)]
18+
fn main() { let unused = (); }

src/test/compile-fail/lint-renamed.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2016 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+
#[deny(unknown_features)] //~ WARN lint unknown_features has been renamed to unused_features
12+
#[deny(unused)]
13+
fn main() { let unused = (); } //~ ERR unused
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2016 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+
// compile-flags:-D bogus
12+
13+
// error-pattern:unknown lint
14+
// error-pattern:requested on the command line with `-D bogus`
15+
16+
fn main() { }
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2016 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+
#![allow(not_a_real_lint)] //~ WARN unknown lint
12+
#![deny(unused)]
13+
fn main() { let unused = (); } //~ ERR unused variable

0 commit comments

Comments
 (0)