diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 716b1116a20..4ff3c1f0075 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -686,39 +686,57 @@ pub fn handle_options(mut args: Vec) -> Option { 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 - = 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) -> getopts::Matches { + let all_groups : Vec + = 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; }