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
This commit is contained in:
parent
14ce607d9b
commit
61004f88d1
@ -688,39 +688,57 @@ pub fn handle_options(mut args: Vec<String>) -> Option<getopts::Matches> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let matches =
|
fn allows_unstable_options(matches: &getopts::Matches) -> bool {
|
||||||
match getopts::getopts(&args[..], &config::optgroups()) {
|
let r = matches.opt_strs("Z");
|
||||||
Ok(m) => m,
|
r.iter().any(|x| *x == "unstable-options")
|
||||||
Err(f_stable_attempt) => {
|
}
|
||||||
// redo option parsing, including unstable options this time,
|
|
||||||
// in anticipation that the mishandled option was one of the
|
fn parse_all_options(args: &Vec<String>) -> getopts::Matches {
|
||||||
// unstable ones.
|
let all_groups : Vec<getopts::OptGroup>
|
||||||
let all_groups : Vec<getopts::OptGroup>
|
= config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect();
|
||||||
= config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect();
|
match getopts::getopts(&args[..], &all_groups) {
|
||||||
match getopts::getopts(&args, &all_groups) {
|
Ok(m) => {
|
||||||
Ok(m_unstable) => {
|
if !allows_unstable_options(&m) {
|
||||||
let r = m_unstable.opt_strs("Z");
|
// If -Z unstable-options was not specified, verify that
|
||||||
let include_unstable_options = r.iter().any(|x| *x == "unstable-options");
|
// no unstable options were present.
|
||||||
if include_unstable_options {
|
for opt in config::rustc_optgroups().into_iter().filter(|x| !x.is_stable()) {
|
||||||
m_unstable
|
let opt_name = if !opt.opt_group.long_name.is_empty() {
|
||||||
|
&opt.opt_group.long_name
|
||||||
} else {
|
} else {
|
||||||
early_error(&f_stable_attempt.to_string());
|
&opt.opt_group.short_name
|
||||||
|
};
|
||||||
|
if m.opt_present(opt_name) {
|
||||||
|
early_error(&format!("use of unstable option '{}' requires \
|
||||||
|
-Z unstable-options", opt_name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
|
||||||
// ignore the error from the unstable attempt; just
|
|
||||||
// pass the error we got from the first try.
|
|
||||||
early_error(&f_stable_attempt.to_string());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
m
|
||||||
}
|
}
|
||||||
};
|
Err(f) => early_error(&f.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let r = matches.opt_strs("Z");
|
// As a speed optimization, first try to parse the command-line using just
|
||||||
let include_unstable_options = r.iter().any(|x| *x == "unstable-options");
|
// the stable options.
|
||||||
|
let matches = match getopts::getopts(&args[..], &config::optgroups()) {
|
||||||
|
Ok(ref m) if allows_unstable_options(m) => {
|
||||||
|
// If -Z unstable-options was specified, redo parsing with the
|
||||||
|
// unstable options to ensure that unstable options are defined
|
||||||
|
// in the returned getopts::Matches.
|
||||||
|
parse_all_options(&args)
|
||||||
|
}
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(_) => {
|
||||||
|
// redo option parsing, including unstable options this time,
|
||||||
|
// in anticipation that the mishandled option was one of the
|
||||||
|
// unstable ones.
|
||||||
|
parse_all_options(&args)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if matches.opt_present("h") || matches.opt_present("help") {
|
if matches.opt_present("h") || matches.opt_present("help") {
|
||||||
usage(matches.opt_present("verbose"), include_unstable_options);
|
usage(matches.opt_present("verbose"), allows_unstable_options(&matches));
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user