Skip to content

Commit ca81d3d

Browse files
committed
rustc: Fix bugs in renamed and removed lints and re-add raw_pointer_derive
cc #30346
1 parent b0eec55 commit ca81d3d

10 files changed

+272
-38
lines changed

src/librustc/lint/builtin.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ declare_lint! {
139139
"unit struct or enum variant erroneously allowed to match via path::ident(..)"
140140
}
141141

142+
declare_lint! {
143+
pub RAW_POINTER_DERIVE,
144+
Warn,
145+
"uses of #[derive] with raw pointers are rarely correct"
146+
}
147+
142148
/// Does nothing as a lint pass, but registers some `Lint`s
143149
/// which are used by other parts of the compiler.
144150
#[derive(Copy, Clone)]
@@ -166,7 +172,8 @@ impl LintPass for HardwiredLints {
166172
PRIVATE_IN_PUBLIC,
167173
INVALID_TYPE_PARAM_DEFAULT,
168174
MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
169-
CONST_ERR
175+
CONST_ERR,
176+
RAW_POINTER_DERIVE
170177
)
171178
}
172179
}

src/librustc/lint/context.rs

+149-35
Original file line numberDiff line numberDiff line change
@@ -219,21 +219,10 @@ impl LintStore {
219219
{
220220
match self.by_name.get(lint_name) {
221221
Some(&Id(lint_id)) => Ok(lint_id),
222-
Some(&Renamed(ref new_name, lint_id)) => {
223-
let warning = format!("lint {} has been renamed to {}",
224-
lint_name, new_name);
225-
match span {
226-
Some(span) => sess.span_warn(span, &warning[..]),
227-
None => sess.warn(&warning[..]),
228-
};
222+
Some(&Renamed(_, lint_id)) => {
229223
Ok(lint_id)
230224
},
231225
Some(&Removed(ref reason)) => {
232-
let warning = format!("lint {} has been removed: {}", lint_name, reason);
233-
match span {
234-
Some(span) => sess.span_warn(span, &warning[..]),
235-
None => sess.warn(&warning[..])
236-
}
237226
Err(FindLintError::Removed)
238227
},
239228
None => Err(FindLintError::NotFound)
@@ -242,8 +231,12 @@ impl LintStore {
242231

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

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

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

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

@@ -555,9 +561,9 @@ pub trait LintContext: Sized {
555561
(*lint_id, level, span))
556562
.collect(),
557563
None => {
558-
self.span_lint(builtin::UNKNOWN_LINTS, span,
559-
&format!("unknown `{}` attribute: `{}`",
560-
level.as_str(), lint_name));
564+
// The lint or lint group doesn't exist.
565+
// This is an error, but it was handled
566+
// by check_lint_name_attribute.
561567
continue;
562568
}
563569
}
@@ -869,6 +875,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
869875
}
870876

871877
fn visit_attribute(&mut self, attr: &ast::Attribute) {
878+
check_lint_name_attribute(self, attr);
872879
run_lints!(self, check_attribute, late_passes, attr);
873880
}
874881
}
@@ -1082,6 +1089,113 @@ impl LateLintPass for GatherNodeLevels {
10821089
}
10831090
}
10841091

1092+
enum CheckLintNameResult<'a> {
1093+
Ok,
1094+
// Lint doesn't exist
1095+
NoLint,
1096+
// The lint is either renamed or removed and a warning was
1097+
// generated in the DiagnosticBuilder
1098+
Mentioned(DiagnosticBuilder<'a>)
1099+
}
1100+
1101+
/// Checks the name of a lint for its existence, and whether it was
1102+
/// renamed or removed. Generates a DiagnosticBuilder containing a
1103+
/// warning for renamed and removed lints. This is over both lint
1104+
/// names from attributes and those passed on the command line. Since
1105+
/// it emits non-fatal warnings and there are *two* lint passes that
1106+
/// inspect attributes, this is only run from the late pass to avoid
1107+
/// printing duplicate warnings.
1108+
fn check_lint_name<'a>(sess: &'a Session,
1109+
lint_cx: &LintStore,
1110+
lint_name: &str,
1111+
span: Option<Span>) -> CheckLintNameResult<'a> {
1112+
match lint_cx.by_name.get(lint_name) {
1113+
Some(&Renamed(ref new_name, _)) => {
1114+
let warning = format!("lint {} has been renamed to {}",
1115+
lint_name, new_name);
1116+
let db = match span {
1117+
Some(span) => sess.struct_span_warn(span, &warning[..]),
1118+
None => sess.struct_warn(&warning[..]),
1119+
};
1120+
CheckLintNameResult::Mentioned(db)
1121+
},
1122+
Some(&Removed(ref reason)) => {
1123+
let warning = format!("lint {} has been removed: {}", lint_name, reason);
1124+
let db = match span {
1125+
Some(span) => sess.struct_span_warn(span, &warning[..]),
1126+
None => sess.struct_warn(&warning[..])
1127+
};
1128+
CheckLintNameResult::Mentioned(db)
1129+
},
1130+
None => {
1131+
match lint_cx.lint_groups.get(lint_name) {
1132+
None => {
1133+
CheckLintNameResult::NoLint
1134+
}
1135+
Some(_) => {
1136+
/* lint group exists */
1137+
CheckLintNameResult::Ok
1138+
}
1139+
}
1140+
}
1141+
Some(_) => {
1142+
/* lint exists */
1143+
CheckLintNameResult::Ok
1144+
}
1145+
}
1146+
}
1147+
1148+
// Checks the validity of lint names derived from attributes
1149+
fn check_lint_name_attribute(cx: &LateContext, attr: &ast::Attribute) {
1150+
for result in gather_attr(attr) {
1151+
match result {
1152+
Err(_) => {
1153+
// Malformed lint attr. Reported by with_lint_attrs
1154+
continue;
1155+
}
1156+
Ok((lint_name, _, span)) => {
1157+
match check_lint_name(&cx.tcx.sess, &cx.lints, &lint_name[..], Some(span)) {
1158+
CheckLintNameResult::Ok => (),
1159+
CheckLintNameResult::Mentioned(mut db) => {
1160+
db.emit();
1161+
}
1162+
CheckLintNameResult::NoLint => {
1163+
cx.span_lint(builtin::UNKNOWN_LINTS, span,
1164+
&format!("unknown lint: `{}`",
1165+
lint_name));
1166+
}
1167+
}
1168+
}
1169+
}
1170+
}
1171+
}
1172+
1173+
// Checks the validity of lint names derived from the command line
1174+
fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore,
1175+
lint_name: &str, level: Level) {
1176+
let db = match check_lint_name(sess, lint_cx, lint_name, None) {
1177+
CheckLintNameResult::Ok => None,
1178+
CheckLintNameResult::Mentioned(db) => Some(db),
1179+
CheckLintNameResult::NoLint => {
1180+
Some(sess.struct_err(&format!("unknown lint: `{}`", lint_name)))
1181+
}
1182+
};
1183+
1184+
if let Some(mut db) = db {
1185+
let msg = format!("requested on the command line with `{} {}`",
1186+
match level {
1187+
Level::Allow => "-A",
1188+
Level::Warn => "-W",
1189+
Level::Deny => "-D",
1190+
Level::Forbid => "-F",
1191+
},
1192+
lint_name);
1193+
db.note(&msg);
1194+
db.emit();
1195+
}
1196+
}
1197+
1198+
10851199
/// Perform lint checking on a crate.
10861200
///
10871201
/// Consumes the `lint_store` field of the `Session`.

src/librustc_lint/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,12 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
151151
// We have one lint pass defined specially
152152
store.register_late_pass(sess, false, box lint::GatherNodeLevels);
153153

154-
// Insert temporary renamings for a one-time deprecation
154+
// Register renamed and removed lints
155155
store.register_renamed("unknown_features", "unused_features");
156-
157156
store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
158157
store.register_removed("negate_unsigned", "cast a signed value instead");
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
}
+14
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() { }
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

+16
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
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

+13
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
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() { }
+13
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)