Skip to content

Improve -Z unstable-options diagnostics and avoid an ICE #23274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 12, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 43 additions & 25 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down