diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index bc6956f579783..069fa41fa886a 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -26,8 +26,6 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::{source_map::MultiSpan, Span, DUMMY_SP}; use tracing::debug; -use std::cmp; - fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap { let store = unerased_lint_store(tcx); let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID); @@ -91,12 +89,6 @@ impl<'s> LintLevelsBuilder<'s> { for &(ref lint_name, level) in &sess.opts.lint_opts { store.check_lint_name_cmdline(sess, &lint_name, level, self.crate_attrs); 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 - // this specification as the lint cap will set it to allow anyway. - let level = cmp::min(level, self.sets.lint_cap); - let lint_flag_val = Symbol::intern(lint_name); let ids = match store.find_lints(&lint_name) { @@ -104,23 +96,17 @@ impl<'s> LintLevelsBuilder<'s> { Err(_) => continue, // errors handled in check_lint_name_cmdline above }; for id in ids { + // ForceWarn and Forbid cannot be overriden + if let Some((Level::ForceWarn | Level::Forbid, _)) = 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)); } } - for lint_name in &sess.opts.force_warns { - store.check_lint_name_cmdline(sess, lint_name, Level::ForceWarn, self.crate_attrs); - let lints = store - .find_lints(lint_name) - .unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids")); - for id in lints { - let src = LintLevelSource::CommandLine(Symbol::intern(lint_name), Level::ForceWarn); - specs.insert(id, (Level::ForceWarn, src)); - } - } - self.cur = self.sets.list.push(LintSet { specs, parent: COMMAND_LINE }); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index b444f66258a8e..9e5a38b8dc0b1 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -677,7 +677,6 @@ impl Default for Options { optimize: OptLevel::No, debuginfo: DebugInfo::None, lint_opts: Vec::new(), - force_warns: Vec::new(), lint_cap: None, describe_lints: false, output_types: OutputTypes(BTreeMap::new()), @@ -1172,20 +1171,20 @@ pub fn get_cmd_lint_options( matches: &getopts::Matches, error_format: ErrorOutputType, debugging_opts: &DebuggingOptions, -) -> (Vec<(String, lint::Level)>, bool, Option, Vec) { +) -> (Vec<(String, lint::Level)>, bool, Option) { let mut lint_opts_with_position = vec![]; let mut describe_lints = false; - for level in [lint::Allow, lint::Warn, lint::Deny, lint::Forbid] { - for (passed_arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { - let arg_pos = if let lint::Forbid = level { - // HACK: forbid is always specified last, so it can't be overridden. - // FIXME: remove this once is - // fixed and `forbid` works as expected. - usize::MAX - } else { - passed_arg_pos - }; + if !debugging_opts.unstable_options && matches.opt_present("force-warns") { + early_error( + error_format, + "the `-Z unstable-options` flag must also be passed to enable \ + the flag `--force-warns=lints`", + ); + } + + for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] { + for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { if lint_name == "help" { describe_lints = true; } else { @@ -1206,18 +1205,7 @@ pub fn get_cmd_lint_options( .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap))) }); - if !debugging_opts.unstable_options && matches.opt_present("force-warns") { - early_error( - error_format, - "the `-Z unstable-options` flag must also be passed to enable \ - the flag `--force-warns=lints`", - ); - } - - let force_warns = - matches.opt_strs("force-warns").into_iter().map(|name| name.replace('-', "_")).collect(); - - (lint_opts, describe_lints, lint_cap, force_warns) + (lint_opts, describe_lints, lint_cap) } /// Parses the `--color` flag. @@ -1955,7 +1943,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { .unwrap_or_else(|e| early_error(error_format, &e[..])); let mut debugging_opts = DebuggingOptions::build(matches, error_format); - let (lint_opts, describe_lints, lint_cap, force_warns) = + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format, &debugging_opts); check_debug_option_stability(&debugging_opts, error_format, json_rendered); @@ -2129,7 +2117,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { optimize: opt_level, debuginfo, lint_opts, - force_warns, lint_cap, describe_lints, output_types, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 474cd86f43bea..9c66890292ad1 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -135,7 +135,6 @@ top_level_options!( debuginfo: DebugInfo [TRACKED], lint_opts: Vec<(String, lint::Level)> [TRACKED], lint_cap: Option [TRACKED], - force_warns: Vec [TRACKED], describe_lints: bool [UNTRACKED], output_types: OutputTypes [TRACKED], search_paths: Vec [UNTRACKED], diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 4cf647a81ae4b..d601d948555fb 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -628,7 +628,7 @@ impl Options { let generate_redirect_map = matches.opt_present("generate-redirect-map"); let show_type_layout = matches.opt_present("show-type-layout"); - let (lint_opts, describe_lints, lint_cap, _) = + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format, &debugging_opts); Ok(Options { diff --git a/src/test/ui/lint/cli-lint-override.forbid_warn.stderr b/src/test/ui/lint/cli-lint-override.forbid_warn.stderr new file mode 100644 index 0000000000000..ff4dc4abc74a1 --- /dev/null +++ b/src/test/ui/lint/cli-lint-override.forbid_warn.stderr @@ -0,0 +1,11 @@ +error: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +LL | extern fn foo() {} + | ^^^^^^^^^^^^^^^ ABI should be specified here + | + = note: requested on the command line with `-F missing-abi` + = help: the default ABI is C + +error: aborting due to previous error + diff --git a/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr b/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr new file mode 100644 index 0000000000000..50c58ea6e151a --- /dev/null +++ b/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr @@ -0,0 +1,11 @@ +warning: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +LL | extern fn foo() {} + | ^^^^^^^^^^^^^^^ ABI should be specified here + | + = note: requested on the command line with `--force-warns missing-abi` + = help: the default ABI is C + +warning: 1 warning emitted + diff --git a/src/test/ui/lint/cli-lint-override.rs b/src/test/ui/lint/cli-lint-override.rs new file mode 100644 index 0000000000000..6814c15e65686 --- /dev/null +++ b/src/test/ui/lint/cli-lint-override.rs @@ -0,0 +1,17 @@ +// Tests that subsequent lints specified via the command line override +// each other, except for ForceWarn and Forbid, which cannot be overriden. +// +// revisions: warn_deny forbid_warn force_warn_deny +// +//[warn_deny] compile-flags: --warn missing_abi --deny missing_abi +//[forbid_warn] compile-flags: --warn missing_abi --forbid missing_abi +//[force_warn_deny] compile-flags: -Z unstable-options --force-warns missing_abi --allow missing_abi +//[force_warn_deny] check-pass + + +extern fn foo() {} +//[warn_deny]~^ ERROR extern declarations without an explicit ABI are deprecated +//[forbid_warn]~^^ ERROR extern declarations without an explicit ABI are deprecated +//[force_warn_deny]~^^^ WARN extern declarations without an explicit ABI are deprecated + +fn main() {} diff --git a/src/test/ui/lint/cli-lint-override.warn_deny.stderr b/src/test/ui/lint/cli-lint-override.warn_deny.stderr new file mode 100644 index 0000000000000..2d869adfd37e3 --- /dev/null +++ b/src/test/ui/lint/cli-lint-override.warn_deny.stderr @@ -0,0 +1,11 @@ +error: extern declarations without an explicit ABI are deprecated + --> $DIR/cli-lint-override.rs:12:1 + | +LL | extern fn foo() {} + | ^^^^^^^^^^^^^^^ ABI should be specified here + | + = note: requested on the command line with `-D missing-abi` + = help: the default ABI is C + +error: aborting due to previous error + diff --git a/src/test/ui/lint/cli-unknown-force-warn.rs b/src/test/ui/lint/cli-unknown-force-warn.rs new file mode 100644 index 0000000000000..201161296baf4 --- /dev/null +++ b/src/test/ui/lint/cli-unknown-force-warn.rs @@ -0,0 +1,7 @@ +// Checks that rustc correctly errors when passed an invalid lint with +// `--force-warns`. This is a regression test for issue #86958. +// +// compile-flags: -Z unstable-options --force-warns foo-qux +// error-pattern: unknown lint: `foo_qux` + +fn main() {} diff --git a/src/test/ui/lint/cli-unknown-force-warn.stderr b/src/test/ui/lint/cli-unknown-force-warn.stderr new file mode 100644 index 0000000000000..3a9aebb996c93 --- /dev/null +++ b/src/test/ui/lint/cli-unknown-force-warn.stderr @@ -0,0 +1,15 @@ +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warns foo_qux` + +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warns foo_qux` + +error[E0602]: unknown lint: `foo_qux` + | + = note: requested on the command line with `--force-warns foo_qux` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0602`.