Skip to content

Commit 8852752

Browse files
author
David Koloski
committed
Treat unstable lints as unknown
This change causes unstable lints to be ignored if the `unknown_lints` lint is allowed. To achieve this, it also changes lints to apply as soon as they are processed. Previously, lints in the same set were processed as a batch and then all simultaneously applied. Implementation of rust-lang/compiler-team#469
1 parent b97dc20 commit 8852752

File tree

10 files changed

+119
-35
lines changed

10 files changed

+119
-35
lines changed

compiler/rustc_feature/src/active.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ declare_features! (
169169
(active, staged_api, "1.0.0", None, None),
170170
/// Added for testing E0705; perma-unstable.
171171
(active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)),
172+
/// Added for testing unstable lints; perma-unstable.
173+
(active, test_unstable_lint, "1.60.0", None, None),
172174
/// Allows non-`unsafe` —and thus, unsound— access to `Pin` constructions.
173175
/// Marked `incomplete` since perma-unstable and unsound.
174176
(incomplete, unsafe_pin_internals, "1.60.0", None, None),

compiler/rustc_lint/src/levels.rs

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,21 @@ impl<'s> LintLevelsBuilder<'s> {
9393
self.store
9494
}
9595

96+
fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
97+
&self.sets.list[self.cur].specs
98+
}
99+
100+
fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource> {
101+
&mut self.sets.list[self.cur].specs
102+
}
103+
96104
fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
97-
let mut specs = FxHashMap::default();
98105
self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
99106

107+
self.cur = self.sets.list.push(LintSet {
108+
specs: FxHashMap::default(),
109+
parent: COMMAND_LINE,
110+
});
100111
for &(ref lint_name, level) in &sess.opts.lint_opts {
101112
store.check_lint_name_cmdline(sess, &lint_name, level, self.registered_tools);
102113
let orig_level = level;
@@ -108,30 +119,28 @@ impl<'s> LintLevelsBuilder<'s> {
108119
};
109120
for id in ids {
110121
// ForceWarn and Forbid cannot be overriden
111-
if let Some((Level::ForceWarn | Level::Forbid, _)) = specs.get(&id) {
122+
if let Some((Level::ForceWarn | Level::Forbid, _)) = self.current_specs().get(&id) {
112123
continue;
113124
}
114125

115-
self.check_gated_lint(id, DUMMY_SP);
116-
let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
117-
specs.insert(id, (level, src));
126+
if self.check_gated_lint(id, DUMMY_SP) {
127+
let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
128+
self.current_specs_mut().insert(id, (level, src));
129+
}
118130
}
119131
}
120-
121-
self.cur = self.sets.list.push(LintSet { specs, parent: COMMAND_LINE });
122132
}
123133

124134
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
125135
/// (e.g. if a forbid was already inserted on the same scope), then emits a
126136
/// diagnostic with no change to `specs`.
127137
fn insert_spec(
128138
&mut self,
129-
specs: &mut FxHashMap<LintId, LevelAndSource>,
130139
id: LintId,
131140
(level, src): LevelAndSource,
132141
) {
133142
let (old_level, old_src) =
134-
self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess);
143+
self.sets.get_lint_level(id.lint, self.cur, Some(self.current_specs()), &self.sess);
135144
// Setting to a non-forbid level is an error if the lint previously had
136145
// a forbid level. Note that this is not necessarily true even with a
137146
// `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`.
@@ -154,7 +163,7 @@ impl<'s> LintLevelsBuilder<'s> {
154163
};
155164
debug!(
156165
"fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}",
157-
fcw_warning, specs, old_src, id_name
166+
fcw_warning, self.current_specs(), old_src, id_name
158167
);
159168

160169
let decorate_diag = |diag: &mut Diagnostic| {
@@ -213,9 +222,9 @@ impl<'s> LintLevelsBuilder<'s> {
213222
}
214223
}
215224
if let Level::ForceWarn = old_level {
216-
specs.insert(id, (old_level, old_src));
225+
self.current_specs_mut().insert(id, (old_level, old_src));
217226
} else {
218-
specs.insert(id, (level, src));
227+
self.current_specs_mut().insert(id, (level, src));
219228
}
220229
}
221230

@@ -239,7 +248,11 @@ impl<'s> LintLevelsBuilder<'s> {
239248
is_crate_node: bool,
240249
source_hir_id: Option<HirId>,
241250
) -> BuilderPush {
242-
let mut specs = FxHashMap::default();
251+
let prev = self.cur;
252+
self.cur = self.sets.list.push(LintSet {
253+
specs: FxHashMap::default(),
254+
parent: prev,
255+
});
243256
let sess = self.sess;
244257
let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
245258
for (attr_index, attr) in attrs.iter().enumerate() {
@@ -348,8 +361,9 @@ impl<'s> LintLevelsBuilder<'s> {
348361
reason,
349362
);
350363
for &id in *ids {
351-
self.check_gated_lint(id, attr.span);
352-
self.insert_spec(&mut specs, id, (level, src));
364+
if self.check_gated_lint(id, attr.span) {
365+
self.insert_spec(id, (level, src));
366+
}
353367
}
354368
if let Level::Expect(expect_id) = level {
355369
self.lint_expectations
@@ -368,7 +382,7 @@ impl<'s> LintLevelsBuilder<'s> {
368382
reason,
369383
);
370384
for id in ids {
371-
self.insert_spec(&mut specs, *id, (level, src));
385+
self.insert_spec(*id, (level, src));
372386
}
373387
if let Level::Expect(expect_id) = level {
374388
self.lint_expectations
@@ -378,7 +392,7 @@ impl<'s> LintLevelsBuilder<'s> {
378392
Err((Some(ids), ref new_lint_name)) => {
379393
let lint = builtin::RENAMED_AND_REMOVED_LINTS;
380394
let (lvl, src) =
381-
self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
395+
self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), &sess);
382396
struct_lint_level(
383397
self.sess,
384398
lint,
@@ -408,7 +422,7 @@ impl<'s> LintLevelsBuilder<'s> {
408422
reason,
409423
);
410424
for id in ids {
411-
self.insert_spec(&mut specs, *id, (level, src));
425+
self.insert_spec(*id, (level, src));
412426
}
413427
if let Level::Expect(expect_id) = level {
414428
self.lint_expectations
@@ -449,7 +463,7 @@ impl<'s> LintLevelsBuilder<'s> {
449463
CheckLintNameResult::Warning(msg, renamed) => {
450464
let lint = builtin::RENAMED_AND_REMOVED_LINTS;
451465
let (renamed_lint_level, src) =
452-
self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
466+
self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), &sess);
453467
struct_lint_level(
454468
self.sess,
455469
lint,
@@ -473,7 +487,7 @@ impl<'s> LintLevelsBuilder<'s> {
473487
CheckLintNameResult::NoLint(suggestion) => {
474488
let lint = builtin::UNKNOWN_LINTS;
475489
let (level, src) =
476-
self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
490+
self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), self.sess);
477491
struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| {
478492
let name = if let Some(tool_ident) = tool_ident {
479493
format!("{}::{}", tool_ident.name, name)
@@ -504,8 +518,9 @@ impl<'s> LintLevelsBuilder<'s> {
504518
{
505519
let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason);
506520
for &id in ids {
507-
self.check_gated_lint(id, attr.span);
508-
self.insert_spec(&mut specs, id, (level, src));
521+
if self.check_gated_lint(id, attr.span) {
522+
self.insert_spec(id, (level, src));
523+
}
509524
}
510525
if let Level::Expect(expect_id) = level {
511526
self.lint_expectations
@@ -519,7 +534,7 @@ impl<'s> LintLevelsBuilder<'s> {
519534
}
520535

521536
if !is_crate_node {
522-
for (id, &(level, ref src)) in specs.iter() {
537+
for (id, &(level, ref src)) in self.current_specs().iter() {
523538
if !id.lint.crate_level_only {
524539
continue;
525540
}
@@ -530,7 +545,7 @@ impl<'s> LintLevelsBuilder<'s> {
530545

531546
let lint = builtin::UNUSED_ATTRIBUTES;
532547
let (lint_level, lint_src) =
533-
self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
548+
self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), self.sess);
534549
struct_lint_level(
535550
self.sess,
536551
lint,
@@ -551,9 +566,9 @@ impl<'s> LintLevelsBuilder<'s> {
551566
}
552567
}
553568

554-
let prev = self.cur;
555-
if !specs.is_empty() {
556-
self.cur = self.sets.list.push(LintSet { specs, parent: prev });
569+
if self.current_specs().is_empty() {
570+
self.sets.list.pop();
571+
self.cur = prev;
557572
}
558573

559574
BuilderPush { prev, changed: prev != self.cur }
@@ -574,18 +589,25 @@ impl<'s> LintLevelsBuilder<'s> {
574589
}
575590

576591
/// Checks if the lint is gated on a feature that is not enabled.
577-
fn check_gated_lint(&self, lint_id: LintId, span: Span) {
592+
///
593+
/// Returns `true` if the lint's feature is enabled.
594+
fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool {
578595
if let Some(feature) = lint_id.lint.feature_gate {
579596
if !self.sess.features_untracked().enabled(feature) {
580-
feature_err(
581-
&self.sess.parse_sess,
582-
feature,
583-
span,
584-
&format!("the `{}` lint is unstable", lint_id.lint.name_lower()),
585-
)
586-
.emit();
597+
let (unknown_lints_level, _) = self.lint_level(builtin::UNKNOWN_LINTS);
598+
if unknown_lints_level != Level::Allow {
599+
feature_err(
600+
&self.sess.parse_sess,
601+
feature,
602+
span,
603+
&format!("the `{}` lint is unstable", lint_id.lint.name_lower()),
604+
)
605+
.emit();
606+
}
607+
return false;
587608
}
588609
}
610+
true
589611
}
590612

591613
/// Called after `push` when the scope of a set of attributes are exited.

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3128,6 +3128,7 @@ declare_lint_pass! {
31283128
SUSPICIOUS_AUTO_TRAIT_IMPLS,
31293129
UNEXPECTED_CFGS,
31303130
DEPRECATED_WHERE_CLAUSE_LOCATION,
3131+
TEST_UNSTABLE_LINT,
31313132
]
31323133
}
31333134

@@ -3771,3 +3772,11 @@ declare_lint! {
37713772
Warn,
37723773
"deprecated where clause location"
37733774
}
3775+
3776+
declare_lint! {
3777+
#[doc(hidden)]
3778+
pub TEST_UNSTABLE_LINT,
3779+
Deny,
3780+
"this unstable lint is only for testing",
3781+
@feature_gate = sym::test_unstable_lint;
3782+
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,7 @@ symbols! {
13831383
test_case,
13841384
test_removed_feature,
13851385
test_runner,
1386+
test_unstable_lint,
13861387
then_with,
13871388
thread,
13881389
thread_local,
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// check-pass
2+
// compile-flags: -Aunknown_lints -Atest_unstable_lint
3+
4+
fn main() {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// check-pass
2+
3+
#![allow(unknown_lints, test_unstable_lint)]
4+
5+
fn main() {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// check-fail
2+
// compile-flags: -Atest_unstable_lint
3+
// error-pattern: the `test_unstable_lint` lint is unstable
4+
5+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0658]: the `test_unstable_lint` lint is unstable
2+
|
3+
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
4+
5+
error[E0658]: the `test_unstable_lint` lint is unstable
6+
|
7+
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
8+
9+
error: aborting due to 2 previous errors
10+
11+
For more information about this error, try `rustc --explain E0658`.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// check-fail
2+
// error-pattern: the `test_unstable_lint` lint is unstable
3+
4+
#![allow(test_unstable_lint)]
5+
6+
fn main() {}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0658]: the `test_unstable_lint` lint is unstable
2+
--> $DIR/unstable-lint-inline.rs:4:1
3+
|
4+
LL | #![allow(test_unstable_lint)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
8+
9+
error[E0658]: the `test_unstable_lint` lint is unstable
10+
--> $DIR/unstable-lint-inline.rs:4:1
11+
|
12+
LL | #![allow(test_unstable_lint)]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
|
15+
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)