Skip to content

Commit cee9463

Browse files
committed
Auto merge of #30878 - brson:raw-pointer-derive, r=brson
This adds back the raw_pointer_derive lint as a 'removed' lint, so that its removal does not cause errors (#30346) but warnings. In the process I discovered regressions in the code for renamed and removed lints, which didn't appear to have any tests. The addition of a second lint pass (ast vs. hir) meant that attributes were being inspected twice, renamed and removed warnings printed twice. I restructured the code so these tests are only done once and added tests. Unfortunately it makes the patch more complicated for the needed beta backport. r? @nikomatsakis
2 parents 683af0d + ca81d3d commit cee9463

10 files changed

+272
-38
lines changed

src/librustc/lint/builtin.rs

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

139+
declare_lint! {
140+
pub RAW_POINTER_DERIVE,
141+
Warn,
142+
"uses of #[derive] with raw pointers are rarely correct"
143+
}
144+
139145
/// Does nothing as a lint pass, but registers some `Lint`s
140146
/// which are used by other parts of the compiler.
141147
#[derive(Copy, Clone)]
@@ -163,7 +169,8 @@ impl LintPass for HardwiredLints {
163169
PRIVATE_IN_PUBLIC,
164170
INVALID_TYPE_PARAM_DEFAULT,
165171
MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
166-
CONST_ERR
172+
CONST_ERR,
173+
RAW_POINTER_DERIVE
167174
)
168175
}
169176
}

src/librustc/lint/context.rs

+149-35
Original file line numberDiff line numberDiff line change
@@ -247,21 +247,10 @@ impl LintStore {
247247
{
248248
match self.by_name.get(lint_name) {
249249
Some(&Id(lint_id)) => Ok(lint_id),
250-
Some(&Renamed(ref new_name, lint_id)) => {
251-
let warning = format!("lint {} has been renamed to {}",
252-
lint_name, new_name);
253-
match span {
254-
Some(span) => sess.span_warn(span, &warning[..]),
255-
None => sess.warn(&warning[..]),
256-
};
250+
Some(&Renamed(_, lint_id)) => {
257251
Ok(lint_id)
258252
},
259253
Some(&Removed(ref reason)) => {
260-
let warning = format!("lint {} has been removed: {}", lint_name, reason);
261-
match span {
262-
Some(span) => sess.span_warn(span, &warning[..]),
263-
None => sess.warn(&warning[..])
264-
}
265254
Err(FindLintError::Removed)
266255
},
267256
None => Err(FindLintError::NotFound)
@@ -270,8 +259,12 @@ impl LintStore {
270259

271260
pub fn process_command_line(&mut self, sess: &Session) {
272261
for &(ref lint_name, level) in &sess.opts.lint_opts {
262+
check_lint_name_cmdline(sess, self,
263+
&lint_name[..], level);
264+
273265
match self.find_lint(&lint_name[..], sess, None) {
274266
Ok(lint_id) => self.set_level(lint_id, (level, CommandLine)),
267+
Err(FindLintError::Removed) => { }
275268
Err(_) => {
276269
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone()))
277270
.collect::<FnvHashMap<&'static str,
@@ -283,8 +276,11 @@ impl LintStore {
283276
self.set_level(*lint_id, (level, CommandLine)))
284277
.collect::<Vec<()>>();
285278
}
286-
None => sess.err(&format!("unknown {} flag: {}",
287-
level.as_str(), lint_name)),
279+
None => {
280+
// The lint or lint group doesn't exist.
281+
// This is an error, but it was handled
282+
// by check_lint_name_cmdline.
283+
}
288284
}
289285
}
290286
}
@@ -359,29 +355,39 @@ pub fn gather_attrs(attrs: &[ast::Attribute])
359355
-> Vec<Result<(InternedString, Level, Span), Span>> {
360356
let mut out = vec!();
361357
for attr in attrs {
362-
let level = match Level::from_str(&attr.name()) {
363-
None => continue,
364-
Some(lvl) => lvl,
365-
};
358+
let r = gather_attr(attr);
359+
out.extend(r.into_iter());
360+
}
361+
out
362+
}
366363

367-
attr::mark_used(attr);
364+
pub fn gather_attr(attr: &ast::Attribute)
365+
-> Vec<Result<(InternedString, Level, Span), Span>> {
366+
let mut out = vec!();
368367

369-
let meta = &attr.node.value;
370-
let metas = match meta.node {
371-
ast::MetaList(_, ref metas) => metas,
372-
_ => {
373-
out.push(Err(meta.span));
374-
continue;
375-
}
376-
};
368+
let level = match Level::from_str(&attr.name()) {
369+
None => return out,
370+
Some(lvl) => lvl,
371+
};
377372

378-
for meta in metas {
379-
out.push(match meta.node {
380-
ast::MetaWord(ref lint_name) => Ok((lint_name.clone(), level, meta.span)),
381-
_ => Err(meta.span),
382-
});
373+
attr::mark_used(attr);
374+
375+
let meta = &attr.node.value;
376+
let metas = match meta.node {
377+
ast::MetaList(_, ref metas) => metas,
378+
_ => {
379+
out.push(Err(meta.span));
380+
return out;
383381
}
382+
};
383+
384+
for meta in metas {
385+
out.push(match meta.node {
386+
ast::MetaWord(ref lint_name) => Ok((lint_name.clone(), level, meta.span)),
387+
_ => Err(meta.span),
388+
});
384389
}
390+
385391
out
386392
}
387393

@@ -587,9 +593,9 @@ pub trait LintContext: Sized {
587593
(*lint_id, level, span))
588594
.collect(),
589595
None => {
590-
self.span_lint(builtin::UNKNOWN_LINTS, span,
591-
&format!("unknown `{}` attribute: `{}`",
592-
level.as_str(), lint_name));
596+
// The lint or lint group doesn't exist.
597+
// This is an error, but it was handled
598+
// by check_lint_name_attribute.
593599
continue;
594600
}
595601
}
@@ -901,6 +907,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
901907
}
902908

903909
fn visit_attribute(&mut self, attr: &ast::Attribute) {
910+
check_lint_name_attribute(self, attr);
904911
run_lints!(self, check_attribute, late_passes, attr);
905912
}
906913
}
@@ -1114,6 +1121,113 @@ impl LateLintPass for GatherNodeLevels {
11141121
}
11151122
}
11161123

1124+
enum CheckLintNameResult<'a> {
1125+
Ok,
1126+
// Lint doesn't exist
1127+
NoLint,
1128+
// The lint is either renamed or removed and a warning was
1129+
// generated in the DiagnosticBuilder
1130+
Mentioned(DiagnosticBuilder<'a>)
1131+
}
1132+
1133+
/// Checks the name of a lint for its existence, and whether it was
1134+
/// renamed or removed. Generates a DiagnosticBuilder containing a
1135+
/// warning for renamed and removed lints. This is over both lint
1136+
/// names from attributes and those passed on the command line. Since
1137+
/// it emits non-fatal warnings and there are *two* lint passes that
1138+
/// inspect attributes, this is only run from the late pass to avoid
1139+
/// printing duplicate warnings.
1140+
fn check_lint_name<'a>(sess: &'a Session,
1141+
lint_cx: &LintStore,
1142+
lint_name: &str,
1143+
span: Option<Span>) -> CheckLintNameResult<'a> {
1144+
match lint_cx.by_name.get(lint_name) {
1145+
Some(&Renamed(ref new_name, _)) => {
1146+
let warning = format!("lint {} has been renamed to {}",
1147+
lint_name, new_name);
1148+
let db = match span {
1149+
Some(span) => sess.struct_span_warn(span, &warning[..]),
1150+
None => sess.struct_warn(&warning[..]),
1151+
};
1152+
CheckLintNameResult::Mentioned(db)
1153+
},
1154+
Some(&Removed(ref reason)) => {
1155+
let warning = format!("lint {} has been removed: {}", lint_name, reason);
1156+
let db = match span {
1157+
Some(span) => sess.struct_span_warn(span, &warning[..]),
1158+
None => sess.struct_warn(&warning[..])
1159+
};
1160+
CheckLintNameResult::Mentioned(db)
1161+
},
1162+
None => {
1163+
match lint_cx.lint_groups.get(lint_name) {
1164+
None => {
1165+
CheckLintNameResult::NoLint
1166+
}
1167+
Some(_) => {
1168+
/* lint group exists */
1169+
CheckLintNameResult::Ok
1170+
}
1171+
}
1172+
}
1173+
Some(_) => {
1174+
/* lint exists */
1175+
CheckLintNameResult::Ok
1176+
}
1177+
}
1178+
}
1179+
1180+
// Checks the validity of lint names derived from attributes
1181+
fn check_lint_name_attribute(cx: &LateContext, attr: &ast::Attribute) {
1182+
for result in gather_attr(attr) {
1183+
match result {
1184+
Err(_) => {
1185+
// Malformed lint attr. Reported by with_lint_attrs
1186+
continue;
1187+
}
1188+
Ok((lint_name, _, span)) => {
1189+
match check_lint_name(&cx.tcx.sess, &cx.lints, &lint_name[..], Some(span)) {
1190+
CheckLintNameResult::Ok => (),
1191+
CheckLintNameResult::Mentioned(mut db) => {
1192+
db.emit();
1193+
}
1194+
CheckLintNameResult::NoLint => {
1195+
cx.span_lint(builtin::UNKNOWN_LINTS, span,
1196+
&format!("unknown lint: `{}`",
1197+
lint_name));
1198+
}
1199+
}
1200+
}
1201+
}
1202+
}
1203+
}
1204+
1205+
// Checks the validity of lint names derived from the command line
1206+
fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore,
1207+
lint_name: &str, level: Level) {
1208+
let db = match check_lint_name(sess, lint_cx, lint_name, None) {
1209+
CheckLintNameResult::Ok => None,
1210+
CheckLintNameResult::Mentioned(db) => Some(db),
1211+
CheckLintNameResult::NoLint => {
1212+
Some(sess.struct_err(&format!("unknown lint: `{}`", lint_name)))
1213+
}
1214+
};
1215+
1216+
if let Some(mut db) = db {
1217+
let msg = format!("requested on the command line with `{} {}`",
1218+
match level {
1219+
Level::Allow => "-A",
1220+
Level::Warn => "-W",
1221+
Level::Deny => "-D",
1222+
Level::Forbid => "-F",
1223+
},
1224+
lint_name);
1225+
db.note(&msg);
1226+
db.emit();
1227+
}
1228+
}
1229+
1230+
11171231
/// Perform lint checking on a crate.
11181232
///
11191233
/// Consumes the `lint_store` field of the `Session`.

src/librustc_lint/lib.rs

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

175-
// Insert temporary renamings for a one-time deprecation
175+
// Register renamed and removed lints
176176
store.register_renamed("unknown_features", "unused_features");
177-
178177
store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
179178
store.register_removed("negate_unsigned", "cast a signed value instead");
179+
store.register_removed("raw_pointer_derive", "using derive with raw pointers is ok");
180+
// This was renamed to raw_pointer_derive, which was then removed,
181+
// so it is also considered removed
182+
store.register_removed("raw_pointer_deriving", "using derive with raw pointers is ok");
180183
}
+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)