From 6c1f15fa81be5f89cd7af7f7e73012967b4e673a Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 2 Nov 2020 01:37:26 -0500 Subject: [PATCH] Fix ICE when a future-incompat-report has its command-line level capped Fixes #78660 With PR https://github.com/rust-lang/rust/pull/75534 merged, we now run more lint-related code for future-incompat-report, even when their final level is Allow. Some lint-related code was not expecting `Level::Allow`, and had an explicit panic. This PR explicitly tracks the lint level set on the command line before `--cap-lints` is applied. This is used to emit a more precise error note (e.g. we don't say that `-W lint-name` was specified on the command line just because a lint was capped to Warn). As a result, we can now correctly emit a note that `-A` was used if we got `Level::Allow` from the command line (before the cap is applied). --- compiler/rustc_lint/src/levels.rs | 9 +++++---- compiler/rustc_middle/src/lint.rs | 14 ++++++++------ .../ui/lint/issue-78660-cap-lints-future-compat.rs | 10 ++++++++++ .../issue-78660-cap-lints-future-compat.stderr | 11 +++++++++++ 4 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/lint/issue-78660-cap-lints-future-compat.rs create mode 100644 src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index f36f598ade2de..aca28988364e6 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -74,6 +74,7 @@ impl<'s> LintLevelsBuilder<'s> { for &(ref lint_name, level) in &sess.opts.lint_opts { store.check_lint_name_cmdline(sess, &lint_name, level); + let orig_level = level; // If the cap is less than this specified level, e.g., if we've got // `--cap-lints allow` but we've also got `-D foo` then we ignore @@ -88,7 +89,7 @@ impl<'s> LintLevelsBuilder<'s> { }; for id in ids { self.check_gated_lint(id, DUMMY_SP); - let src = LintSource::CommandLine(lint_flag_val); + let src = LintSource::CommandLine(lint_flag_val, orig_level); specs.insert(id, (level, src)); } } @@ -123,7 +124,7 @@ impl<'s> LintLevelsBuilder<'s> { diag_builder.note(&rationale.as_str()); } } - LintSource::CommandLine(_) => { + LintSource::CommandLine(_, _) => { diag_builder.note("`forbid` lint level was set on command line"); } } @@ -422,7 +423,7 @@ impl<'s> LintLevelsBuilder<'s> { let forbidden_lint_name = match forbid_src { LintSource::Default => id.to_string(), LintSource::Node(name, _, _) => name.to_string(), - LintSource::CommandLine(name) => name.to_string(), + LintSource::CommandLine(name, _) => name.to_string(), }; let (lint_attr_name, lint_attr_span) = match *src { LintSource::Node(name, span, _) => (name, span), @@ -446,7 +447,7 @@ impl<'s> LintLevelsBuilder<'s> { diag_builder.note(&rationale.as_str()); } } - LintSource::CommandLine(_) => { + LintSource::CommandLine(_, _) => { diag_builder.note("`forbid` lint level was set on command line"); } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 6e67f0d828c05..781c1744ac62d 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -22,7 +22,9 @@ pub enum LintSource { Node(Symbol, Span, Option /* RFC 2383 reason */), /// Lint level was set by a command-line flag. - CommandLine(Symbol), + /// The provided `Level` is the level specified on the command line - + /// the actual level may be lower due to `--cap-lints` + CommandLine(Symbol, Level), } impl LintSource { @@ -30,7 +32,7 @@ impl LintSource { match *self { LintSource::Default => symbol::kw::Default, LintSource::Node(name, _, _) => name, - LintSource::CommandLine(name) => name, + LintSource::CommandLine(name, _) => name, } } @@ -38,7 +40,7 @@ impl LintSource { match *self { LintSource::Default => DUMMY_SP, LintSource::Node(_, span, _) => span, - LintSource::CommandLine(_) => DUMMY_SP, + LintSource::CommandLine(_, _) => DUMMY_SP, } } } @@ -279,12 +281,12 @@ pub fn struct_lint_level<'s, 'd>( &format!("`#[{}({})]` on by default", level.as_str(), name), ); } - LintSource::CommandLine(lint_flag_val) => { - let flag = match level { + LintSource::CommandLine(lint_flag_val, orig_level) => { + let flag = match orig_level { Level::Warn => "-W", Level::Deny => "-D", Level::Forbid => "-F", - Level::Allow => panic!(), + Level::Allow => "-A", }; let hyphen_case_lint_name = name.replace("_", "-"); if lint_flag_val.as_str() == name { diff --git a/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs b/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs new file mode 100644 index 0000000000000..4d98f0ad62d4d --- /dev/null +++ b/src/test/ui/lint/issue-78660-cap-lints-future-compat.rs @@ -0,0 +1,10 @@ +// compile-flags: -D warnings --cap-lints allow +// check-pass + +// Regression test for issue #78660 +// Tests that we don't ICE when a future-incompat-report lint has +// has a command-line source, but is capped to allow + +fn main() { + ["hi"].into_iter(); +} diff --git a/src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr b/src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr new file mode 100644 index 0000000000000..79958ba90d409 --- /dev/null +++ b/src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr @@ -0,0 +1,11 @@ +Future incompatibility report: Future breakage date: None, diagnostic: +warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added. + --> $DIR/issue-78660-cap-lints-future-compat.rs:9:12 + | +LL | ["hi"].into_iter(); + | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` + | + = note: `-D array-into-iter` implied by `-D warnings` + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #66145 +