Skip to content

Commit 0cd9eda

Browse files
committed
Emit warning when there is no space between -o and arg
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
1 parent 0d11be5 commit 0cd9eda

File tree

6 files changed

+132
-1
lines changed

6 files changed

+132
-1
lines changed

compiler/rustc_driver_impl/src/args.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{env, error, fmt, fs, io};
22

3-
use rustc_session::EarlyDiagCtxt;
3+
use rustc_session::{EarlyDiagCtxt, config};
44

55
/// Expands argfiles in command line arguments.
66
#[derive(Default)]
@@ -153,3 +153,40 @@ impl fmt::Display for Error {
153153
}
154154

155155
impl error::Error for Error {}
156+
157+
/// check if suspect is a confusables of any option or arg in rustc or fake_args
158+
pub(crate) fn check_confusables(suspect: &str, fake_args: &[&str]) -> Option<String> {
159+
let suspect = suspect.strip_prefix("-").unwrap_or(suspect);
160+
// Check if s1 starts with s2, ignoring hyphens vs underscores
161+
fn starts_with_ignoring_separators(s1: &str, s2: &str) -> bool {
162+
let normalized_s1 = s1.replace('-', "_");
163+
let normalized_s2 = s2.replace('-', "_");
164+
normalized_s1.starts_with(&normalized_s2)
165+
}
166+
167+
let optgroups = config::rustc_optgroups();
168+
for option in optgroups {
169+
let prefix = String::from("--");
170+
if starts_with_ignoring_separators(option.long_name(), suspect) {
171+
return Some(prefix + option.long_name());
172+
}
173+
}
174+
for option in config::CG_OPTIONS {
175+
let prefix = String::from("-C ");
176+
if starts_with_ignoring_separators(option.name(), suspect) {
177+
return Some(prefix + option.name());
178+
}
179+
}
180+
for option in config::Z_OPTIONS {
181+
let prefix = String::from("-Z ");
182+
if starts_with_ignoring_separators(option.name(), suspect) {
183+
return Some(prefix + option.name());
184+
}
185+
}
186+
for arg in fake_args {
187+
if starts_with_ignoring_separators(arg, suspect) {
188+
return Some("".to_string());
189+
}
190+
}
191+
None
192+
}

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ mod signal_handler {
103103
pub(super) fn install() {}
104104
}
105105

106+
use crate::args::check_confusables;
106107
use crate::session_diagnostics::{
107108
CantEmitMIR, RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
108109
RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage,
@@ -1237,6 +1238,25 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
12371238
return None;
12381239
}
12391240

1241+
// To avoid confusion, emit warning if no space
1242+
// between `-o` and arg, e.g.`-optimize`, `-out-dir`, is applied, see issue #142812
1243+
if let Some(name) = matches.opt_str("o")
1244+
&& let Some(suspect) = args.iter().find(|arg| arg.starts_with("-o") && *arg != "-o")
1245+
{
1246+
if let Some(confusable) = check_confusables(&suspect, &["optimize"]) {
1247+
early_dcx.early_warn(
1248+
"option `-o` has no space between flag name and value, which can be confusing",
1249+
);
1250+
early_dcx.early_note(format!(
1251+
"option `-o {}` is applied instead of a flag named `o{}`",
1252+
name, name
1253+
));
1254+
if !confusable.is_empty() {
1255+
early_dcx.early_note(format!("Do you mean `{}`?", confusable));
1256+
}
1257+
}
1258+
}
1259+
12401260
Some(matches)
12411261
}
12421262

compiler/rustc_session/src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,6 +1653,10 @@ impl RustcOptGroup {
16531653
OptionKind::FlagMulti => options.optflagmulti(short_name, long_name, desc),
16541654
};
16551655
}
1656+
1657+
pub fn long_name(&self) -> &str {
1658+
self.long_name
1659+
}
16561660
}
16571661

16581662
pub fn make_opt(
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// This test is to check if the warning is emitted when no space
2+
// between `-o` and arg is applied, see issue #142812
3+
use run_make_support::rustc;
4+
5+
fn main() {
6+
// test fake args
7+
rustc()
8+
.input("main.rs")
9+
.arg("-optimize")
10+
.run()
11+
.assert_stderr_contains(
12+
"warning: option `-o` has no space between flag name and value, which can be confusing",
13+
)
14+
.assert_stderr_contains(
15+
"note: option `-o ptimize` is applied instead of a flag named `optimize`",
16+
);
17+
// test real args by iter optgroups
18+
rustc()
19+
.input("main.rs")
20+
.arg("-out-dir")
21+
.run()
22+
.assert_stderr_contains(
23+
"warning: option `-o` has no space between flag name and value, which can be confusing",
24+
)
25+
.assert_stderr_contains(
26+
"note: option `-o ut-dir` is applied instead of a flag named `out-dir`",
27+
)
28+
.assert_stderr_contains("Do you mean `--out-dir`?");
29+
// test real args by iter CG_OPTIONS
30+
rustc()
31+
.input("main.rs")
32+
.arg("-opt-level")
33+
.run()
34+
.assert_stderr_contains(
35+
"warning: option `-o` has no space between flag name and value, which can be confusing",
36+
)
37+
.assert_stderr_contains(
38+
"note: option `-o pt-level` is applied instead of a flag named `opt-level`",
39+
)
40+
.assert_stderr_contains("Do you mean `-C opt_level`?");
41+
rustc()
42+
.input("main.rs")
43+
.arg("-overflow-checks")
44+
.run()
45+
.assert_stderr_contains(
46+
"warning: option `-o` has no space between flag name and value, which can be confusing",
47+
)
48+
.assert_stderr_contains(
49+
"note: option `-o verflow-checks` is applied instead of a flag named `overflow-checks`",
50+
)
51+
.assert_stderr_contains("Do you mean `-C overflow_checks`?");
52+
// test real args by iter Z_OPTIONS
53+
rustc()
54+
.input("main.rs")
55+
.arg("-oom")
56+
.run()
57+
.assert_stderr_contains(
58+
"warning: option `-o` has no space between flag name and value, which can be confusing",
59+
)
60+
.assert_stderr_contains("note: option `-o om` is applied instead of a flag named `oom`")
61+
.assert_stderr_contains("note: Do you mean `-Z oom`?");
62+
63+
// test no warning when there is space between `-o` and arg
64+
rustc().input("main.rs").arg("-o").arg("ptimize").run().assert_stderr_equals("");
65+
rustc().input("main.rs").arg("--out-dir").arg("xxx").run().assert_stderr_equals("");
66+
rustc().input("main.rs").arg("-o").arg("out-dir").run().assert_stderr_equals("");
67+
}

tests/ui/unpretty/avoid-crash.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
warning: option `-o .` is applied
2+
13
error: failed to write `.` due to $ERROR_MESSAGE
24

35
error: aborting due to 1 previous error

0 commit comments

Comments
 (0)