From d1d3129ad1c6f6d600ecadeb7a363ba06e1afb50 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Sep 2026 16:18:34 +1000 Subject: [PATCH 1/3] Improve the "no space between flag name and value" warning A command like `rustc -optimize a.rs` currently gives this: ``` warning: option `-o` has no space between flag name and value, which can be confusing note: output filename `-o ptimize` is applied instead of a flag named `optimize` help: insert a space between `-o` and `ptimize` if this is intentional: `-o ptimize` ``` A top-level warning, then a top-level note, then a top-level help. Weird! This commit converts the note and the help into children of the warning, which looks better and matches how things are normally done, giving this: ``` warning: option `-o` has no space between flag name and value, which can be confusing | = note: output filename `-o ptimize` is applied instead of a flag named `optimize` = help: insert a space between `-o` and `ptimize` if this is intentional: `-o ptimize` ``` Much better. --- compiler/rustc_driver_impl/src/lib.rs | 20 +++++++++-------- .../run-make/option-output-no-space/rmake.rs | 22 ++++++++++--------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c935efe71edc1..5af05fa6fe0fd 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1344,15 +1344,17 @@ fn warn_on_confusing_output_filename_flag( || config::CG_OPTIONS.iter().any(|option| eq_ignore_separators(option.name(), filename)) || fake_args.iter().any(|arg| eq_ignore_separators(arg, filename)) { - early_dcx.early_warn( - "option `-o` has no space between flag name and value, which can be confusing", - ); - early_dcx.early_note(format!( - "output filename `-o {name}` is applied instead of a flag named `o{name}`" - )); - early_dcx.early_help(format!( - "insert a space between `-o` and `{name}` if this is intentional: `-o {name}`" - )); + early_dcx + .early_struct_warn( + "option `-o` has no space between flag name and value, which can be confusing", + ) + .with_note(format!( + "output filename `-o {name}` is applied instead of a flag named `o{name}`" + )) + .with_help(format!( + "insert a space between `-o` and `{name}` if this is intentional: `-o {name}`" + )) + .emit(); } } } diff --git a/tests/run-make/option-output-no-space/rmake.rs b/tests/run-make/option-output-no-space/rmake.rs index 2c42f15aa89a6..63d2389890155 100644 --- a/tests/run-make/option-output-no-space/rmake.rs +++ b/tests/run-make/option-output-no-space/rmake.rs @@ -14,7 +14,7 @@ fn main() { "warning: option `-o` has no space between flag name and value, which can be confusing", ) .assert_stderr_contains( - "note: output filename `-o ptimize` is applied instead of a flag named `optimize`", + "= note: output filename `-o ptimize` is applied instead of a flag named `optimize`", ); rustc() .input("main.rs") @@ -24,7 +24,7 @@ fn main() { "warning: option `-o` has no space between flag name and value, which can be confusing", ) .assert_stderr_contains( - "note: output filename `-o 0` is applied instead of a flag named `o0`", + "= note: output filename `-o 0` is applied instead of a flag named `o0`", ); rustc().input("main.rs").arg("-o1").run(); // test real args by iter optgroups @@ -36,10 +36,10 @@ fn main() { "warning: option `-o` has no space between flag name and value, which can be confusing", ) .assert_stderr_contains( - "note: output filename `-o ut-dir` is applied instead of a flag named `out-dir`", + "= note: output filename `-o ut-dir` is applied instead of a flag named `out-dir`", ) .assert_stderr_contains( - "help: insert a space between `-o` and `ut-dir` if this is intentional: `-o ut-dir`", + "= help: insert a space between `-o` and `ut-dir` if this is intentional: `-o ut-dir`", ); // test real args by iter CG_OPTIONS rustc() @@ -50,10 +50,11 @@ fn main() { "warning: option `-o` has no space between flag name and value, which can be confusing", ) .assert_stderr_contains( - "note: output filename `-o pt_level` is applied instead of a flag named `opt_level`", + "= note: output filename `-o pt_level` is applied instead of a flag named `opt_level`", ) .assert_stderr_contains( - "help: insert a space between `-o` and `pt_level` if this is intentional: `-o pt_level`" + "= help: insert a space between `-o` and `pt_level` if this is intentional: \ + `-o pt_level`", ); // separater in-sensitive rustc() @@ -64,10 +65,11 @@ fn main() { "warning: option `-o` has no space between flag name and value, which can be confusing", ) .assert_stderr_contains( - "note: output filename `-o pt-level` is applied instead of a flag named `opt-level`", + "= note: output filename `-o pt-level` is applied instead of a flag named `opt-level`", ) .assert_stderr_contains( - "help: insert a space between `-o` and `pt-level` if this is intentional: `-o pt-level`" + "= help: insert a space between `-o` and `pt-level` if this is intentional: \ + `-o pt-level`", ); rustc() .input("main.rs") @@ -77,11 +79,11 @@ fn main() { "warning: option `-o` has no space between flag name and value, which can be confusing", ) .assert_stderr_contains( - "note: output filename `-o verflow-checks` \ + "= note: output filename `-o verflow-checks` \ is applied instead of a flag named `overflow-checks`", ) .assert_stderr_contains( - "help: insert a space between `-o` and `verflow-checks` \ + "= help: insert a space between `-o` and `verflow-checks` \ if this is intentional: `-o verflow-checks`", ); From de902bb264c2250856dc54a8c41f1c369d0769b0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Sep 2026 17:02:17 +1000 Subject: [PATCH 2/3] Improve nightly option parse errors Currently the command `rustc -Zunstable-options -j3 --jobs-backend=1 a.rs`, when run on stable rustc, gives this: ``` error: the option `Z` is only accepted on the nightly compiler error: the option `jobs` is only accepted on the nightly compiler error: the option `jobs-backend` is only accepted on the nightly compiler help: consider switching to a nightly toolchain: `rustup default nightly` note: selecting a toolchain with `+toolchain` arguments require a rustup proxy; see note: for more information about Rust's stability policy, see error: 3 nightly options were parsed ``` The errors are fine, but top-level help and notes are weird. This commit changes it to this, which is more normal: ``` error: the option `Z` is only accepted on the nightly compiler error: the option `jobs` is only accepted on the nightly compiler error: the option `jobs-backend` is only accepted on the nightly compiler error: 3 nightly options were parsed | = help: consider switching to a nightly toolchain: `rustup default nightly` = note: selecting a toolchain with `+toolchain` arguments require a rustup proxy; see = note: for more information about Rust's stability policy, see ``` It's a slightly different order but that seems fine. The commit also makes two other small improvements: - An unnecessary `match opt.stability` is removed. (There's another `opt.stability` check a few lines above.) - It fixes "1 nightly option were parsed" to "1 nightly option was parsed". --- compiler/rustc_session/src/config.rs | 39 +++++++++---------- .../rustc_bootstrap.force_stable.stderr | 12 +++--- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 2ae9dfdc9c2ad..d19566f8f632e 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3194,29 +3194,28 @@ pub mod nightly_options { if really_allows_unstable_options { continue; } - match opt.stability { - OptionStability::Unstable => { - nightly_options_on_stable += 1; - let msg = format!( - "the option `{}` is only accepted on the nightly compiler", - opt.name - ); - // The non-zero nightly_options_on_stable will force an early_fatal eventually. - let _ = early_dcx.early_err(msg); - } - OptionStability::Stable => {} - } + + nightly_options_on_stable += 1; + let msg = format!("the option `{}` is only accepted on the nightly compiler", opt.name); + // The non-zero nightly_options_on_stable will force an early_fatal eventually. + let _ = early_dcx.early_err(msg); } + if nightly_options_on_stable > 0 { - early_dcx - .early_help("consider switching to a nightly toolchain: `rustup default nightly`"); - early_dcx.early_note("selecting a toolchain with `+toolchain` arguments require a rustup proxy; see "); - early_dcx.early_note("for more information about Rust's stability policy, see "); - early_dcx.early_fatal(format!( - "{} nightly option{} were parsed", - nightly_options_on_stable, - if nightly_options_on_stable > 1 { "s" } else { "" } + let (s, were) = if nightly_options_on_stable > 1 { ("s", "were") } else { ("", "was") }; + let mut err = early_dcx.early_struct_fatal(format!( + "{nightly_options_on_stable} nightly option{s} {were} parsed", )); + err.help("consider switching to a nightly toolchain: `rustup default nightly`"); + err.note( + "selecting a toolchain with `+toolchain` arguments require a rustup proxy; \ + see ", + ); + err.note( + "for more information about Rust's stability policy, see \ + ", + ); + err.emit(); } } } diff --git a/tests/ui/bootstrap/rustc_bootstrap.force_stable.stderr b/tests/ui/bootstrap/rustc_bootstrap.force_stable.stderr index f378f3c70dd03..32f177e752ad0 100644 --- a/tests/ui/bootstrap/rustc_bootstrap.force_stable.stderr +++ b/tests/ui/bootstrap/rustc_bootstrap.force_stable.stderr @@ -1,10 +1,8 @@ error: the option `Z` is only accepted on the nightly compiler -help: consider switching to a nightly toolchain: `rustup default nightly` - -note: selecting a toolchain with `+toolchain` arguments require a rustup proxy; see - -note: for more information about Rust's stability policy, see - -error: 1 nightly option were parsed +error: 1 nightly option was parsed + | + = help: consider switching to a nightly toolchain: `rustup default nightly` + = note: selecting a toolchain with `+toolchain` arguments require a rustup proxy; see + = note: for more information about Rust's stability policy, see From 396d60358fd2ed02791b8f1115c6fe52ffd15b1a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Sep 2026 17:12:42 +1000 Subject: [PATCH 3/3] Remove `EarlyDiagCtxt::early_{note,help}` They're now unused. --- compiler/rustc_session/src/session.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 6b851250eae6e..17aa00d8339d0 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1767,14 +1767,6 @@ impl EarlyDiagCtxt { self.dcx = DiagCtxt::new(emitter); } - pub fn early_note(&self, msg: impl Into) { - self.dcx.handle().note(msg) - } - - pub fn early_help(&self, msg: impl Into) { - self.dcx.handle().struct_help(msg).emit() - } - #[must_use = "raise_fatal must be called on the returned ErrorGuaranteed in order to exit with a non-zero status code"] pub fn early_err(&self, msg: impl Into) -> ErrorGuaranteed { self.dcx.handle().err(msg)