about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2020-11-02 01:37:26 -0500
committerAaron Hill <aa1ronham@gmail.com>2020-11-02 01:43:25 -0500
commit6c1f15fa81be5f89cd7af7f7e73012967b4e673a (patch)
tree255f70d53542ab18d9f63633b8c9f7b8f57a21a4
parentd8ef0d7757742862116c455345120dcbfb7e74e0 (diff)
downloadrust-6c1f15fa81be5f89cd7af7f7e73012967b4e673a.tar.gz
rust-6c1f15fa81be5f89cd7af7f7e73012967b4e673a.zip
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).
-rw-r--r--compiler/rustc_lint/src/levels.rs9
-rw-r--r--compiler/rustc_middle/src/lint.rs14
-rw-r--r--src/test/ui/lint/issue-78660-cap-lints-future-compat.rs10
-rw-r--r--src/test/ui/lint/issue-78660-cap-lints-future-compat.stderr11
4 files changed, 34 insertions, 10 deletions
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index f36f598ade2..aca28988364 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 6e67f0d828c..781c1744ac6 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<Symbol> /* 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 00000000000..4d98f0ad62d
--- /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 00000000000..79958ba90d4
--- /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 <https://github.com/rust-lang/rust/issues/66145>
+