Skip to content

Commit 61004f8

Browse files
committed
Improve -Z unstable-options diagnostics and avoid an ICE
* Consumers of handle_options assume the unstable options are defined in the getopts::Matches value if -Z unstable-options is set, but that's not the case if there weren't any actual unstable options. Fix this by always reparsing options when -Z unstable-options is set. * If both argument parsing attempts fail, print the error from the second attempt rather than the first. The error from the first is very poor whenever unstable options are present. e.g.: $ rustc hello.rs -Z unstable-options --show-span error: Unrecognized option: 'show-span'. $ rustc hello.rs -Z unstable-options --pretty --pretty error: Unrecognized option: 'pretty'. $ rustc hello.rs -Z unstable-options --pretty --bad-option error: Unrecognized option: 'pretty'. * On the second parse, add a separate pass to reject unstable options if -Z unstable-options wasn't specified. Fixes #21715. r? @pnkfelix
1 parent 14ce607 commit 61004f8

File tree

1 file changed

+43
-25
lines changed

1 file changed

+43
-25
lines changed

src/librustc_driver/lib.rs

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -688,39 +688,57 @@ pub fn handle_options(mut args: Vec<String>) -> Option<getopts::Matches> {
688688
return None;
689689
}
690690

691-
let matches =
692-
match getopts::getopts(&args[..], &config::optgroups()) {
693-
Ok(m) => m,
694-
Err(f_stable_attempt) => {
695-
// redo option parsing, including unstable options this time,
696-
// in anticipation that the mishandled option was one of the
697-
// unstable ones.
698-
let all_groups : Vec<getopts::OptGroup>
699-
= config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect();
700-
match getopts::getopts(&args, &all_groups) {
701-
Ok(m_unstable) => {
702-
let r = m_unstable.opt_strs("Z");
703-
let include_unstable_options = r.iter().any(|x| *x == "unstable-options");
704-
if include_unstable_options {
705-
m_unstable
691+
fn allows_unstable_options(matches: &getopts::Matches) -> bool {
692+
let r = matches.opt_strs("Z");
693+
r.iter().any(|x| *x == "unstable-options")
694+
}
695+
696+
fn parse_all_options(args: &Vec<String>) -> getopts::Matches {
697+
let all_groups : Vec<getopts::OptGroup>
698+
= config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect();
699+
match getopts::getopts(&args[..], &all_groups) {
700+
Ok(m) => {
701+
if !allows_unstable_options(&m) {
702+
// If -Z unstable-options was not specified, verify that
703+
// no unstable options were present.
704+
for opt in config::rustc_optgroups().into_iter().filter(|x| !x.is_stable()) {
705+
let opt_name = if !opt.opt_group.long_name.is_empty() {
706+
&opt.opt_group.long_name
706707
} else {
707-
early_error(&f_stable_attempt.to_string());
708+
&opt.opt_group.short_name
709+
};
710+
if m.opt_present(opt_name) {
711+
early_error(&format!("use of unstable option '{}' requires \
712+
-Z unstable-options", opt_name));
708713
}
709714
}
710-
Err(_) => {
711-
// ignore the error from the unstable attempt; just
712-
// pass the error we got from the first try.
713-
early_error(&f_stable_attempt.to_string());
714-
}
715715
}
716+
m
716717
}
717-
};
718+
Err(f) => early_error(&f.to_string())
719+
}
720+
}
718721

719-
let r = matches.opt_strs("Z");
720-
let include_unstable_options = r.iter().any(|x| *x == "unstable-options");
722+
// As a speed optimization, first try to parse the command-line using just
723+
// the stable options.
724+
let matches = match getopts::getopts(&args[..], &config::optgroups()) {
725+
Ok(ref m) if allows_unstable_options(m) => {
726+
// If -Z unstable-options was specified, redo parsing with the
727+
// unstable options to ensure that unstable options are defined
728+
// in the returned getopts::Matches.
729+
parse_all_options(&args)
730+
}
731+
Ok(m) => m,
732+
Err(_) => {
733+
// redo option parsing, including unstable options this time,
734+
// in anticipation that the mishandled option was one of the
735+
// unstable ones.
736+
parse_all_options(&args)
737+
}
738+
};
721739

722740
if matches.opt_present("h") || matches.opt_present("help") {
723-
usage(matches.opt_present("verbose"), include_unstable_options);
741+
usage(matches.opt_present("verbose"), allows_unstable_options(&matches));
724742
return None;
725743
}
726744

0 commit comments

Comments
 (0)