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;
|
||||
}
|
||||
|
||||
let matches =
|
||||
match getopts::getopts(&args[..], &config::optgroups()) {
|
||||
Ok(m) => m,
|
||||
Err(f_stable_attempt) => {
|
||||
// redo option parsing, including unstable options this time,
|
||||
// in anticipation that the mishandled option was one of the
|
||||
// unstable ones.
|
||||
let all_groups : Vec<getopts::OptGroup>
|
||||
= config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect();
|
||||
match getopts::getopts(&args, &all_groups) {
|
||||
Ok(m_unstable) => {
|
||||
let r = m_unstable.opt_strs("Z");
|
||||
let include_unstable_options = r.iter().any(|x| *x == "unstable-options");
|
||||
if include_unstable_options {
|
||||
m_unstable
|
||||
fn allows_unstable_options(matches: &getopts::Matches) -> bool {
|
||||
let r = matches.opt_strs("Z");
|
||||
r.iter().any(|x| *x == "unstable-options")
|
||||
}
|
||||
|
||||
fn parse_all_options(args: &Vec<String>) -> getopts::Matches {
|
||||
let all_groups : Vec<getopts::OptGroup>
|
||||
= config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect();
|
||||
match getopts::getopts(&args[..], &all_groups) {
|
||||
Ok(m) => {
|
||||
if !allows_unstable_options(&m) {
|
||||
// If -Z unstable-options was not specified, verify that
|
||||
// no unstable options were present.
|
||||
for opt in config::rustc_optgroups().into_iter().filter(|x| !x.is_stable()) {
|
||||
let opt_name = if !opt.opt_group.long_name.is_empty() {
|
||||
&opt.opt_group.long_name
|
||||
} 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");
|
||||
let include_unstable_options = r.iter().any(|x| *x == "unstable-options");
|
||||
// As a speed optimization, first try to parse the command-line using just
|
||||
// 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") {
|
||||
usage(matches.opt_present("verbose"), include_unstable_options);
|
||||
usage(matches.opt_present("verbose"), allows_unstable_options(&matches));
|
||||
return None;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user