Skip to content

Commit 0a07db4

Browse files
committed
rollup merge of rust-lang#19964: pnkfelix/everybody-loops-pprint
Conflicts: src/librustc/session/config.rs src/librustc_driver/lib.rs src/librustc_driver/pretty.rs
2 parents de11710 + 34d4378 commit 0a07db4

File tree

4 files changed

+277
-69
lines changed

4 files changed

+277
-69
lines changed

src/librustc/session/config.rs

Lines changed: 131 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ use syntax::parse::token::InternedString;
3434

3535
use std::collections::HashMap;
3636
use std::collections::hash_map::Entry::{Occupied, Vacant};
37-
use getopts::{optopt, optmulti, optflag, optflagopt};
3837
use getopts;
3938
use std::cell::{RefCell};
4039
use std::fmt;
@@ -278,7 +277,8 @@ debugging_opts! {
278277
PRINT_REGION_GRAPH,
279278
PARSE_ONLY,
280279
NO_TRANS,
281-
NO_ANALYSIS
280+
NO_ANALYSIS,
281+
UNSTABLE_OPTIONS
282282
]
283283
0
284284
}
@@ -330,7 +330,8 @@ pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
330330
("no-trans", "Run all passes except translation; no output", NO_TRANS),
331331
("no-analysis", "Parse and expand the source, but run no analysis and",
332332
NO_TRANS),
333-
]
333+
("unstable-options", "Adds unstable command line options to rustc interface",
334+
UNSTABLE_OPTIONS)]
334335
}
335336

336337
#[deriving(Clone)]
@@ -653,95 +654,180 @@ pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config {
653654
}
654655
}
655656

657+
/// Returns the "short" subset of the stable rustc command line options.
656658
pub fn short_optgroups() -> Vec<getopts::OptGroup> {
659+
rustc_short_optgroups().into_iter()
660+
.filter(|g|g.is_stable())
661+
.map(|g|g.opt_group)
662+
.collect()
663+
}
664+
665+
/// Returns all of the stable rustc command line options.
666+
pub fn optgroups() -> Vec<getopts::OptGroup> {
667+
rustc_optgroups().into_iter()
668+
.filter(|g|g.is_stable())
669+
.map(|g|g.opt_group)
670+
.collect()
671+
}
672+
673+
#[deriving(Copy, Clone, PartialEq, Eq, Show)]
674+
pub enum OptionStability { Stable, Unstable }
675+
676+
#[deriving(Clone, PartialEq, Eq)]
677+
pub struct RustcOptGroup {
678+
pub opt_group: getopts::OptGroup,
679+
pub stability: OptionStability,
680+
}
681+
682+
impl RustcOptGroup {
683+
pub fn is_stable(&self) -> bool {
684+
self.stability == OptionStability::Stable
685+
}
686+
687+
fn stable(g: getopts::OptGroup) -> RustcOptGroup {
688+
RustcOptGroup { opt_group: g, stability: OptionStability::Stable }
689+
}
690+
691+
fn unstable(g: getopts::OptGroup) -> RustcOptGroup {
692+
RustcOptGroup { opt_group: g, stability: OptionStability::Unstable }
693+
}
694+
}
695+
696+
// The `opt` local module holds wrappers around the `getopts` API that
697+
// adds extra rustc-specific metadata to each option; such metadata
698+
// is exposed by . The public
699+
// functions below ending with `_u` are the functions that return
700+
// *unstable* options, i.e. options that are only enabled when the
701+
// user also passes the `-Z unstable-options` debugging flag.
702+
mod opt {
703+
// The `fn opt_u` etc below are written so that we can use them
704+
// in the future; do not warn about them not being used right now.
705+
#![allow(dead_code)]
706+
707+
use getopts;
708+
use super::RustcOptGroup;
709+
710+
type R = RustcOptGroup;
711+
type S<'a> = &'a str;
712+
713+
fn stable(g: getopts::OptGroup) -> R { RustcOptGroup::stable(g) }
714+
fn unstable(g: getopts::OptGroup) -> R { RustcOptGroup::unstable(g) }
715+
716+
// FIXME (pnkfelix): We default to stable since the current set of
717+
// options is defacto stable. However, it would be good to revise the
718+
// code so that a stable option is the thing that takes extra effort
719+
// to encode.
720+
721+
pub fn opt(a: S, b: S, c: S, d: S) -> R { stable(getopts::optopt(a, b, c, d)) }
722+
pub fn multi(a: S, b: S, c: S, d: S) -> R { stable(getopts::optmulti(a, b, c, d)) }
723+
pub fn flag(a: S, b: S, c: S) -> R { stable(getopts::optflag(a, b, c)) }
724+
pub fn flagopt(a: S, b: S, c: S, d: S) -> R { stable(getopts::optflagopt(a, b, c, d)) }
725+
726+
pub fn opt_u(a: S, b: S, c: S, d: S) -> R { unstable(getopts::optopt(a, b, c, d)) }
727+
pub fn multi_u(a: S, b: S, c: S, d: S) -> R { unstable(getopts::optmulti(a, b, c, d)) }
728+
pub fn flag_u(a: S, b: S, c: S) -> R { unstable(getopts::optflag(a, b, c)) }
729+
pub fn flagopt_u(a: S, b: S, c: S, d: S) -> R { unstable(getopts::optflagopt(a, b, c, d)) }
730+
}
731+
732+
/// Returns the "short" subset of the rustc command line options,
733+
/// including metadata for each option, such as whether the option is
734+
/// part of the stable long-term interface for rustc.
735+
pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
657736
vec![
658-
optflag("h", "help", "Display this message"),
659-
optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
660-
optmulti("L", "", "Add a directory to the library search path", "PATH"),
661-
optmulti("l", "", "Link the generated crate(s) to the specified native
737+
opt::flag("h", "help", "Display this message"),
738+
opt::multi("", "cfg", "Configure the compilation environment", "SPEC"),
739+
opt::multi("L", "", "Add a directory to the library search path", "PATH"),
740+
opt::multi("l", "", "Link the generated crate(s) to the specified native
662741
library NAME. The optional KIND can be one of,
663742
static, dylib, or framework. If omitted, dylib is
664743
assumed.", "NAME[:KIND]"),
665-
optmulti("", "crate-type", "Comma separated list of types of crates
744+
opt::multi("", "crate-type", "Comma separated list of types of crates
666745
for the compiler to emit",
667746
"[bin|lib|rlib|dylib|staticlib]"),
668-
optopt("", "crate-name", "Specify the name of the crate being built",
747+
opt::opt("", "crate-name", "Specify the name of the crate being built",
669748
"NAME"),
670-
optmulti("", "emit", "Comma separated list of types of output for \
749+
opt::multi("", "emit", "Comma separated list of types of output for \
671750
the compiler to emit",
672751
"[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
673-
optmulti("", "print", "Comma separated list of compiler information to \
752+
"[asm|llvm-bc|llvm-ir|obj|link]"),
753+
opt::multi("", "print", "Comma separated list of compiler information to \
674754
print on stdout",
675755
"[crate-name|output-file-names|sysroot]"),
676-
optflag("g", "", "Equivalent to -C debuginfo=2"),
677-
optflag("O", "", "Equivalent to -C opt-level=2"),
678-
optopt("o", "", "Write output to <filename>", "FILENAME"),
679-
optopt("", "out-dir", "Write output to compiler-chosen filename \
756+
opt::flag("g", "", "Equivalent to -C debuginfo=2"),
757+
opt::flag("O", "", "Equivalent to -C opt-level=2"),
758+
opt::opt("o", "", "Write output to <filename>", "FILENAME"),
759+
opt::opt("", "out-dir", "Write output to compiler-chosen filename \
680760
in <dir>", "DIR"),
681-
optopt("", "explain", "Provide a detailed explanation of an error \
761+
opt::opt("", "explain", "Provide a detailed explanation of an error \
682762
message", "OPT"),
683-
optflag("", "test", "Build a test harness"),
684-
optopt("", "target", "Target triple cpu-manufacturer-kernel[-os] \
763+
opt::flag("", "test", "Build a test harness"),
764+
opt::opt("", "target", "Target triple cpu-manufacturer-kernel[-os] \
685765
to compile for (see chapter 3.4 of \
686766
http://www.sourceware.org/autobook/
687767
for details)",
688768
"TRIPLE"),
689-
optmulti("W", "warn", "Set lint warnings", "OPT"),
690-
optmulti("A", "allow", "Set lint allowed", "OPT"),
691-
optmulti("D", "deny", "Set lint denied", "OPT"),
692-
optmulti("F", "forbid", "Set lint forbidden", "OPT"),
693-
optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
694-
optflag("V", "version", "Print version info and exit"),
695-
optflag("v", "verbose", "Use verbose output"),
769+
opt::multi("W", "warn", "Set lint warnings", "OPT"),
770+
opt::multi("A", "allow", "Set lint allowed", "OPT"),
771+
opt::multi("D", "deny", "Set lint denied", "OPT"),
772+
opt::multi("F", "forbid", "Set lint forbidden", "OPT"),
773+
opt::multi("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
774+
opt::flag("V", "version", "Print version info and exit"),
775+
opt::flag("v", "verbose", "Use verbose output"),
696776
]
697777
}
698778

699-
// rustc command line options
700-
pub fn optgroups() -> Vec<getopts::OptGroup> {
701-
let mut opts = short_optgroups();
779+
/// Returns all rustc command line options, including metadata for
780+
/// each option, such as whether the option is part of the stable
781+
/// long-term interface for rustc.
782+
pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
783+
let mut opts = rustc_short_optgroups();
702784
opts.push_all(&[
703-
optmulti("", "extern", "Specify where an external rust library is \
785+
opt::multi("", "extern", "Specify where an external rust library is \
704786
located",
705787
"NAME=PATH"),
706-
optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
707-
optopt("", "sysroot", "Override the system root", "PATH"),
708-
optmulti("Z", "", "Set internal debugging options", "FLAG"),
709-
optopt("", "color", "Configure coloring of output:
788+
opt::opt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
789+
opt::opt("", "sysroot", "Override the system root", "PATH"),
790+
opt::multi("Z", "", "Set internal debugging options", "FLAG"),
791+
opt::opt("", "color", "Configure coloring of output:
710792
auto = colorize, if output goes to a tty (default);
711793
always = always colorize output;
712794
never = never colorize output", "auto|always|never"),
713795

714796
// DEPRECATED
715-
optflag("", "print-crate-name", "Output the crate name and exit"),
716-
optflag("", "print-file-name", "Output the file(s) that would be \
797+
opt::flag("", "print-crate-name", "Output the crate name and exit"),
798+
opt::flag("", "print-file-name", "Output the file(s) that would be \
717799
written if compilation \
718800
continued and exit"),
719-
optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
801+
opt::opt("", "debuginfo", "Emit DWARF debug info to the objects created:
720802
0 = no debug info,
721803
1 = line-tables only (for stacktraces and breakpoints),
722804
2 = full debug info with variable and type information \
723805
(same as -g)", "LEVEL"),
724-
optflag("", "no-trans", "Run all passes except translation; no output"),
725-
optflag("", "no-analysis", "Parse and expand the source, but run no \
806+
opt::flag("", "no-trans", "Run all passes except translation; no output"),
807+
opt::flag("", "no-analysis", "Parse and expand the source, but run no \
726808
analysis and produce no output"),
727-
optflag("", "parse-only", "Parse only; do not compile, assemble, \
809+
opt::flag("", "parse-only", "Parse only; do not compile, assemble, \
728810
or link"),
729-
optflagopt("", "pretty",
811+
opt::flagopt("", "pretty",
730812
"Pretty-print the input instead of compiling;
731813
valid types are: `normal` (un-annotated source),
732814
`expanded` (crates expanded),
733-
`typed` (crates expanded, with type annotations),
734-
`expanded,identified` (fully parenthesized, AST nodes with IDs), or
735-
`flowgraph=<nodeid>` (graphviz formatted flowgraph for node)",
815+
`typed` (crates expanded, with type annotations), or
816+
`expanded,identified` (fully parenthesized, AST nodes with IDs).",
736817
"TYPE"),
737-
optflagopt("", "dep-info",
818+
opt::flagopt_u("", "xpretty",
819+
"Pretty-print the input instead of compiling, unstable variants;
820+
valid types are any of the types for `--pretty`, as well as:
821+
`flowgraph=<nodeid>` (graphviz formatted flowgraph for node), or
822+
`everybody_loops` (all function bodies replaced with `loop {}`).",
823+
"TYPE"),
824+
opt::flagopt("", "dep-info",
738825
"Output dependency info to <filename> after compiling, \
739826
in a format suitable for use by Makefiles", "FILENAME"),
740827
]);
741828
opts
742829
}
743830

744-
745831
// Convert strings provided as --cfg [cfgspec] into a crate_cfg
746832
pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
747833
cfgspecs.into_iter().map(|s| {

src/librustc_driver/lib.rs

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,19 @@ fn run_compiler(args: &[String]) {
139139
}
140140

141141
let pretty = matches.opt_default("pretty", "normal").map(|a| {
142-
pretty::parse_pretty(&sess, a[])
142+
// stable pretty-print variants only
143+
pretty::parse_pretty(&sess, a.as_slice(), false)
143144
});
145+
let pretty = if pretty.is_none() &&
146+
sess.debugging_opt(config::UNSTABLE_OPTIONS) {
147+
matches.opt_str("xpretty").map(|a| {
148+
// extended with unstable pretty-print variants
149+
pretty::parse_pretty(&sess, a.as_slice(), true)
150+
})
151+
} else {
152+
pretty
153+
};
154+
144155
match pretty.into_iter().next() {
145156
Some((ppm, opt_uii)) => {
146157
pretty::pretty_print_input(sess, cfg, &input, ppm, opt_uii, ofile);
@@ -197,12 +208,16 @@ pub fn version(binary: &str, matches: &getopts::Matches) {
197208
}
198209
}
199210

200-
fn usage(verbose: bool) {
211+
fn usage(verbose: bool, include_unstable_options: bool) {
201212
let groups = if verbose {
202-
config::optgroups()
213+
config::rustc_optgroups()
203214
} else {
204-
config::short_optgroups()
215+
config::rustc_short_optgroups()
205216
};
217+
let groups : Vec<_> = groups.into_iter()
218+
.filter(|x| include_unstable_options || x.is_stable())
219+
.map(|x|x.opt_group)
220+
.collect();
206221
let message = format!("Usage: rustc [OPTIONS] INPUT");
207222
let extra_help = if verbose {
208223
""
@@ -365,20 +380,45 @@ pub fn handle_options(mut args: Vec<String>) -> Option<getopts::Matches> {
365380
let _binary = args.remove(0).unwrap();
366381

367382
if args.is_empty() {
368-
usage(false);
383+
// user did not write `-v` nor `-Z unstable-options`, so do not
384+
// include that extra information.
385+
usage(false, false);
369386
return None;
370387
}
371388

372389
let matches =
373390
match getopts::getopts(args[], config::optgroups()[]) {
374391
Ok(m) => m,
375-
Err(f) => {
376-
early_error(f.to_string()[]);
392+
Err(f_stable_attempt) => {
393+
// redo option parsing, including unstable options this time,
394+
// in anticipation that the mishandled option was one of the
395+
// unstable ones.
396+
let all_groups : Vec<getopts::OptGroup>
397+
= config::rustc_optgroups().into_iter().map(|x|x.opt_group).collect();
398+
match getopts::getopts(args.as_slice(), all_groups.as_slice()) {
399+
Ok(m_unstable) => {
400+
let r = m_unstable.opt_strs("Z");
401+
let include_unstable_options = r.iter().any(|x| *x == "unstable-options");
402+
if include_unstable_options {
403+
m_unstable
404+
} else {
405+
early_error(f_stable_attempt.to_string().as_slice());
406+
}
407+
}
408+
Err(_) => {
409+
// ignore the error from the unstable attempt; just
410+
// pass the error we got from the first try.
411+
early_error(f_stable_attempt.to_string().as_slice());
412+
}
413+
}
377414
}
378415
};
379416

417+
let r = matches.opt_strs("Z");
418+
let include_unstable_options = r.iter().any(|x| *x == "unstable-options");
419+
380420
if matches.opt_present("h") || matches.opt_present("help") {
381-
usage(matches.opt_present("verbose"));
421+
usage(matches.opt_present("verbose"), include_unstable_options);
382422
return None;
383423
}
384424

0 commit comments

Comments
 (0)