mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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 https://github.com/rust-lang/compiler-team/issues/469
This commit is contained in:
parent
b97dc20784
commit
8852752078
@ -169,6 +169,8 @@ declare_features! (
|
||||
(active, staged_api, "1.0.0", None, None),
|
||||
/// Added for testing E0705; perma-unstable.
|
||||
(active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)),
|
||||
/// Added for testing unstable lints; perma-unstable.
|
||||
(active, test_unstable_lint, "1.60.0", None, None),
|
||||
/// Allows non-`unsafe` —and thus, unsound— access to `Pin` constructions.
|
||||
/// Marked `incomplete` since perma-unstable and unsound.
|
||||
(incomplete, unsafe_pin_internals, "1.60.0", None, None),
|
||||
|
@ -93,10 +93,21 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
self.store
|
||||
}
|
||||
|
||||
fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
|
||||
&self.sets.list[self.cur].specs
|
||||
}
|
||||
|
||||
fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource> {
|
||||
&mut self.sets.list[self.cur].specs
|
||||
}
|
||||
|
||||
fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
|
||||
let mut specs = FxHashMap::default();
|
||||
self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
|
||||
|
||||
self.cur = self.sets.list.push(LintSet {
|
||||
specs: FxHashMap::default(),
|
||||
parent: COMMAND_LINE,
|
||||
});
|
||||
for &(ref lint_name, level) in &sess.opts.lint_opts {
|
||||
store.check_lint_name_cmdline(sess, &lint_name, level, self.registered_tools);
|
||||
let orig_level = level;
|
||||
@ -108,17 +119,16 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
};
|
||||
for id in ids {
|
||||
// ForceWarn and Forbid cannot be overriden
|
||||
if let Some((Level::ForceWarn | Level::Forbid, _)) = specs.get(&id) {
|
||||
if let Some((Level::ForceWarn | Level::Forbid, _)) = self.current_specs().get(&id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
self.check_gated_lint(id, DUMMY_SP);
|
||||
let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
|
||||
specs.insert(id, (level, src));
|
||||
if self.check_gated_lint(id, DUMMY_SP) {
|
||||
let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
|
||||
self.current_specs_mut().insert(id, (level, src));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.cur = self.sets.list.push(LintSet { specs, parent: COMMAND_LINE });
|
||||
}
|
||||
|
||||
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
|
||||
@ -126,12 +136,11 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
/// diagnostic with no change to `specs`.
|
||||
fn insert_spec(
|
||||
&mut self,
|
||||
specs: &mut FxHashMap<LintId, LevelAndSource>,
|
||||
id: LintId,
|
||||
(level, src): LevelAndSource,
|
||||
) {
|
||||
let (old_level, old_src) =
|
||||
self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess);
|
||||
self.sets.get_lint_level(id.lint, self.cur, Some(self.current_specs()), &self.sess);
|
||||
// Setting to a non-forbid level is an error if the lint previously had
|
||||
// a forbid level. Note that this is not necessarily true even with a
|
||||
// `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`.
|
||||
@ -154,7 +163,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
};
|
||||
debug!(
|
||||
"fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}",
|
||||
fcw_warning, specs, old_src, id_name
|
||||
fcw_warning, self.current_specs(), old_src, id_name
|
||||
);
|
||||
|
||||
let decorate_diag = |diag: &mut Diagnostic| {
|
||||
@ -213,9 +222,9 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
}
|
||||
}
|
||||
if let Level::ForceWarn = old_level {
|
||||
specs.insert(id, (old_level, old_src));
|
||||
self.current_specs_mut().insert(id, (old_level, old_src));
|
||||
} else {
|
||||
specs.insert(id, (level, src));
|
||||
self.current_specs_mut().insert(id, (level, src));
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +248,11 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
is_crate_node: bool,
|
||||
source_hir_id: Option<HirId>,
|
||||
) -> BuilderPush {
|
||||
let mut specs = FxHashMap::default();
|
||||
let prev = self.cur;
|
||||
self.cur = self.sets.list.push(LintSet {
|
||||
specs: FxHashMap::default(),
|
||||
parent: prev,
|
||||
});
|
||||
let sess = self.sess;
|
||||
let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
|
||||
for (attr_index, attr) in attrs.iter().enumerate() {
|
||||
@ -348,8 +361,9 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
reason,
|
||||
);
|
||||
for &id in *ids {
|
||||
self.check_gated_lint(id, attr.span);
|
||||
self.insert_spec(&mut specs, id, (level, src));
|
||||
if self.check_gated_lint(id, attr.span) {
|
||||
self.insert_spec(id, (level, src));
|
||||
}
|
||||
}
|
||||
if let Level::Expect(expect_id) = level {
|
||||
self.lint_expectations
|
||||
@ -368,7 +382,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
reason,
|
||||
);
|
||||
for id in ids {
|
||||
self.insert_spec(&mut specs, *id, (level, src));
|
||||
self.insert_spec(*id, (level, src));
|
||||
}
|
||||
if let Level::Expect(expect_id) = level {
|
||||
self.lint_expectations
|
||||
@ -378,7 +392,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
Err((Some(ids), ref new_lint_name)) => {
|
||||
let lint = builtin::RENAMED_AND_REMOVED_LINTS;
|
||||
let (lvl, src) =
|
||||
self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
|
||||
self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), &sess);
|
||||
struct_lint_level(
|
||||
self.sess,
|
||||
lint,
|
||||
@ -408,7 +422,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
reason,
|
||||
);
|
||||
for id in ids {
|
||||
self.insert_spec(&mut specs, *id, (level, src));
|
||||
self.insert_spec(*id, (level, src));
|
||||
}
|
||||
if let Level::Expect(expect_id) = level {
|
||||
self.lint_expectations
|
||||
@ -449,7 +463,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
CheckLintNameResult::Warning(msg, renamed) => {
|
||||
let lint = builtin::RENAMED_AND_REMOVED_LINTS;
|
||||
let (renamed_lint_level, src) =
|
||||
self.sets.get_lint_level(lint, self.cur, Some(&specs), &sess);
|
||||
self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), &sess);
|
||||
struct_lint_level(
|
||||
self.sess,
|
||||
lint,
|
||||
@ -473,7 +487,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
CheckLintNameResult::NoLint(suggestion) => {
|
||||
let lint = builtin::UNKNOWN_LINTS;
|
||||
let (level, src) =
|
||||
self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
|
||||
self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), self.sess);
|
||||
struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| {
|
||||
let name = if let Some(tool_ident) = tool_ident {
|
||||
format!("{}::{}", tool_ident.name, name)
|
||||
@ -504,8 +518,9 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
{
|
||||
let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason);
|
||||
for &id in ids {
|
||||
self.check_gated_lint(id, attr.span);
|
||||
self.insert_spec(&mut specs, id, (level, src));
|
||||
if self.check_gated_lint(id, attr.span) {
|
||||
self.insert_spec(id, (level, src));
|
||||
}
|
||||
}
|
||||
if let Level::Expect(expect_id) = level {
|
||||
self.lint_expectations
|
||||
@ -519,7 +534,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
}
|
||||
|
||||
if !is_crate_node {
|
||||
for (id, &(level, ref src)) in specs.iter() {
|
||||
for (id, &(level, ref src)) in self.current_specs().iter() {
|
||||
if !id.lint.crate_level_only {
|
||||
continue;
|
||||
}
|
||||
@ -530,7 +545,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
|
||||
let lint = builtin::UNUSED_ATTRIBUTES;
|
||||
let (lint_level, lint_src) =
|
||||
self.sets.get_lint_level(lint, self.cur, Some(&specs), self.sess);
|
||||
self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), self.sess);
|
||||
struct_lint_level(
|
||||
self.sess,
|
||||
lint,
|
||||
@ -551,9 +566,9 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
}
|
||||
}
|
||||
|
||||
let prev = self.cur;
|
||||
if !specs.is_empty() {
|
||||
self.cur = self.sets.list.push(LintSet { specs, parent: prev });
|
||||
if self.current_specs().is_empty() {
|
||||
self.sets.list.pop();
|
||||
self.cur = prev;
|
||||
}
|
||||
|
||||
BuilderPush { prev, changed: prev != self.cur }
|
||||
@ -574,18 +589,25 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
}
|
||||
|
||||
/// Checks if the lint is gated on a feature that is not enabled.
|
||||
fn check_gated_lint(&self, lint_id: LintId, span: Span) {
|
||||
///
|
||||
/// Returns `true` if the lint's feature is enabled.
|
||||
fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool {
|
||||
if let Some(feature) = lint_id.lint.feature_gate {
|
||||
if !self.sess.features_untracked().enabled(feature) {
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
feature,
|
||||
span,
|
||||
&format!("the `{}` lint is unstable", lint_id.lint.name_lower()),
|
||||
)
|
||||
.emit();
|
||||
let (unknown_lints_level, _) = self.lint_level(builtin::UNKNOWN_LINTS);
|
||||
if unknown_lints_level != Level::Allow {
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
feature,
|
||||
span,
|
||||
&format!("the `{}` lint is unstable", lint_id.lint.name_lower()),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Called after `push` when the scope of a set of attributes are exited.
|
||||
|
@ -3128,6 +3128,7 @@ declare_lint_pass! {
|
||||
SUSPICIOUS_AUTO_TRAIT_IMPLS,
|
||||
UNEXPECTED_CFGS,
|
||||
DEPRECATED_WHERE_CLAUSE_LOCATION,
|
||||
TEST_UNSTABLE_LINT,
|
||||
]
|
||||
}
|
||||
|
||||
@ -3771,3 +3772,11 @@ declare_lint! {
|
||||
Warn,
|
||||
"deprecated where clause location"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
#[doc(hidden)]
|
||||
pub TEST_UNSTABLE_LINT,
|
||||
Deny,
|
||||
"this unstable lint is only for testing",
|
||||
@feature_gate = sym::test_unstable_lint;
|
||||
}
|
||||
|
@ -1383,6 +1383,7 @@ symbols! {
|
||||
test_case,
|
||||
test_removed_feature,
|
||||
test_runner,
|
||||
test_unstable_lint,
|
||||
then_with,
|
||||
thread,
|
||||
thread_local,
|
||||
|
@ -0,0 +1,4 @@
|
||||
// check-pass
|
||||
// compile-flags: -Aunknown_lints -Atest_unstable_lint
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,5 @@
|
||||
// check-pass
|
||||
|
||||
#![allow(unknown_lints, test_unstable_lint)]
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,5 @@
|
||||
// check-fail
|
||||
// compile-flags: -Atest_unstable_lint
|
||||
// error-pattern: the `test_unstable_lint` lint is unstable
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,11 @@
|
||||
error[E0658]: the `test_unstable_lint` lint is unstable
|
||||
|
|
||||
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: the `test_unstable_lint` lint is unstable
|
||||
|
|
||||
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,6 @@
|
||||
// check-fail
|
||||
// error-pattern: the `test_unstable_lint` lint is unstable
|
||||
|
||||
#![allow(test_unstable_lint)]
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,19 @@
|
||||
error[E0658]: the `test_unstable_lint` lint is unstable
|
||||
--> $DIR/unstable-lint-inline.rs:4:1
|
||||
|
|
||||
LL | #![allow(test_unstable_lint)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: the `test_unstable_lint` lint is unstable
|
||||
--> $DIR/unstable-lint-inline.rs:4:1
|
||||
|
|
||||
LL | #![allow(test_unstable_lint)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
Loading…
Reference in New Issue
Block a user