1 // Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The Rust compiler.
15 //! This API is completely unstable and subject to change.
17 #![crate_name = "rustc_driver"]
18 #![unstable(feature = "rustc_private")]
20 #![crate_type = "dylib"]
21 #![crate_type = "rlib"]
22 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
23 html_favicon_url
= "http://www.rust-lang.org/favicon.ico",
24 html_root_url
= "http://doc.rust-lang.org/nightly/")]
26 #![feature(box_syntax)]
27 #![feature(collections)]
36 #![feature(rustc_diagnostic_macros)]
37 #![feature(rustc_private)]
38 #![feature(unsafe_destructor)]
39 #![feature(staged_api)]
45 extern crate graphviz
;
48 extern crate rustc_back
;
49 extern crate rustc_borrowck
;
50 extern crate rustc_privacy
;
51 extern crate rustc_resolve
;
52 extern crate rustc_trans
;
53 extern crate rustc_typeck
;
54 extern crate serialize
;
55 extern crate "rustc_llvm" as llvm
;
56 #[macro_use] extern crate log;
57 #[macro_use] extern crate syntax;
59 pub use syntax
::diagnostic
;
61 use driver
::CompileController
;
62 use pretty
::{PpMode, UserIdentifiedItem}
;
64 use rustc_resolve
as resolve
;
65 use rustc_trans
::back
::link
;
66 use rustc_trans
::save
;
67 use rustc
::session
::{config, Session, build_session}
;
68 use rustc
::session
::config
::{Input, PrintRequest}
;
69 use rustc
::lint
::Lint
;
72 use rustc
::util
::common
::time
;
74 use std
::cmp
::Ordering
::Equal
;
75 use std
::old_io
::{self, stdio}
;
76 use std
::iter
::repeat
;
78 use std
::sync
::mpsc
::channel
;
81 use rustc
::session
::early_error
;
85 use syntax
::diagnostic
::Emitter
;
86 use syntax
::diagnostics
;
95 static BUG_REPORT_URL
: &'
static str =
96 "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports";
99 pub fn run(args
: Vec
<String
>) -> int
{
100 monitor(move || run_compiler(&args
, &mut RustcDefaultCalls
));
104 // Parse args and run the compiler. This is the primary entry point for rustc.
105 // See comments on CompilerCalls below for details about the callbacks argument.
106 pub fn run_compiler
<'a
>(args
: &[String
],
107 callbacks
: &mut CompilerCalls
<'a
>) {
108 macro_rules
! do_or_return
{($expr
: expr
) => {
110 Compilation
::Stop
=> return,
111 Compilation
::Continue
=> {}
115 let matches
= match handle_options(args
.to_vec()) {
116 Some(matches
) => matches
,
120 let descriptions
= diagnostics_registry();
122 do_or_return
!(callbacks
.early_callback(&matches
, &descriptions
));
124 let sopts
= config
::build_session_options(&matches
);
126 let (odir
, ofile
) = make_output(&matches
);
127 let (input
, input_file_path
) = match make_input(&matches
.free
[]) {
128 Some((input
, input_file_path
)) => callbacks
.some_input(input
, input_file_path
),
129 None
=> match callbacks
.no_input(&matches
, &sopts
, &odir
, &ofile
, &descriptions
) {
130 Some((input
, input_file_path
)) => (input
, input_file_path
),
135 let mut sess
= build_session(sopts
, input_file_path
, descriptions
);
136 if sess
.unstable_options() {
137 sess
.opts
.show_span
= matches
.opt_str("show-span");
139 let cfg
= config
::build_configuration(&sess
);
141 do_or_return
!(callbacks
.late_callback(&matches
, &sess
, &input
, &odir
, &ofile
));
143 // It is somewhat unfortunate that this is hardwired in - this is forced by
144 // the fact that pretty_print_input requires the session by value.
145 let pretty
= callbacks
.parse_pretty(&sess
, &matches
);
147 Some((ppm
, opt_uii
)) => {
148 pretty
::pretty_print_input(sess
, cfg
, &input
, ppm
, opt_uii
, ofile
);
151 None
=> {/* continue */ }
154 let plugins
= sess
.opts
.debugging_opts
.extra_plugins
.clone();
155 let control
= callbacks
.build_controller(&sess
);
156 driver
::compile_input(sess
, cfg
, &input
, &odir
, &ofile
, Some(plugins
), control
);
159 // Extract output directory and file from matches.
160 fn make_output(matches
: &getopts
::Matches
) -> (Option
<Path
>, Option
<Path
>) {
161 let odir
= matches
.opt_str("out-dir").map(|o
| Path
::new(o
));
162 let ofile
= matches
.opt_str("o").map(|o
| Path
::new(o
));
166 // Extract input (string or file and optional path) from matches.
167 fn make_input(free_matches
: &[String
]) -> Option
<(Input
, Option
<Path
>)> {
168 if free_matches
.len() == 1 {
169 let ifile
= &free_matches
[0][];
171 let contents
= old_io
::stdin().read_to_end().unwrap();
172 let src
= String
::from_utf8(contents
).unwrap();
173 Some((Input
::Str(src
), None
))
175 Some((Input
::File(Path
::new(ifile
)), Some(Path
::new(ifile
))))
182 // Whether to stop or continue compilation.
183 #[derive(Copy, Debug, Eq, PartialEq)]
184 pub enum Compilation
{
190 pub fn and_then
<F
: FnOnce() -> Compilation
>(self, next
: F
) -> Compilation
{
192 Compilation
::Stop
=> Compilation
::Stop
,
193 Compilation
::Continue
=> next()
198 // A trait for customising the compilation process. Offers a number of hooks for
199 // executing custom code or customising input.
200 pub trait CompilerCalls
<'a
> {
201 // Hook for a callback early in the process of handling arguments. This will
202 // be called straight after options have been parsed but before anything
203 // else (e.g., selecting input and output).
204 fn early_callback(&mut self,
206 &diagnostics
::registry
::Registry
)
209 // Hook for a callback late in the process of handling arguments. This will
210 // be called just before actual compilation starts (and before build_controller
211 // is called), after all arguments etc. have been completely handled.
212 fn late_callback(&mut self,
220 // Called after we extract the input from the arguments. Gives the implementer
221 // an opportunity to change the inputs or to add some custom input handling.
222 // The default behaviour is to simply pass through the inputs.
223 fn some_input(&mut self, input
: Input
, input_path
: Option
<Path
>) -> (Input
, Option
<Path
>) {
227 // Called after we extract the input from the arguments if there is no valid
228 // input. Gives the implementer an opportunity to supply alternate input (by
229 // returning a Some value) or to add custom behaviour for this error such as
230 // emitting error messages. Returning None will cause compilation to stop
232 fn no_input(&mut self,
237 &diagnostics
::registry
::Registry
)
238 -> Option
<(Input
, Option
<Path
>)>;
240 // Parse pretty printing information from the arguments. The implementer can
241 // choose to ignore this (the default will return None) which will skip pretty
242 // printing. If you do want to pretty print, it is recommended to use the
243 // implementation of this method from RustcDefaultCalls.
244 // FIXME, this is a terrible bit of API. Parsing of pretty printing stuff
245 // should be done as part of the framework and the implementor should customise
246 // handling of it. However, that is not possible atm because pretty printing
247 // essentially goes off and takes another path through the compiler which
248 // means the session is either moved or not depending on what parse_pretty
249 // returns (we could fix this by cloning, but it's another hack). The proper
250 // solution is to handle pretty printing as if it were a compiler extension,
251 // extending CompileController to make this work (see for example the treatment
252 // of save-analysis in RustcDefaultCalls::build_controller).
253 fn parse_pretty(&mut self,
255 _matches
: &getopts
::Matches
)
256 -> Option
<(PpMode
, Option
<UserIdentifiedItem
>)> {
260 // Create a CompilController struct for controlling the behaviour of compilation.
261 fn build_controller(&mut self, &Session
) -> CompileController
<'a
>;
264 // CompilerCalls instance for a regular rustc build.
266 pub struct RustcDefaultCalls
;
268 impl<'a
> CompilerCalls
<'a
> for RustcDefaultCalls
{
269 fn early_callback(&mut self,
270 matches
: &getopts
::Matches
,
271 descriptions
: &diagnostics
::registry
::Registry
)
273 match matches
.opt_str("explain") {
275 match descriptions
.find_description(&code
[..]) {
276 Some(ref description
) => {
277 println
!("{}", description
);
280 early_error(&format
!("no extended information for {}", code
)[]);
283 return Compilation
::Stop
;
288 return Compilation
::Continue
;
291 fn no_input(&mut self,
292 matches
: &getopts
::Matches
,
293 sopts
: &config
::Options
,
295 ofile
: &Option
<Path
>,
296 descriptions
: &diagnostics
::registry
::Registry
)
297 -> Option
<(Input
, Option
<Path
>)> {
298 match matches
.free
.len() {
300 if sopts
.describe_lints
{
301 let mut ls
= lint
::LintStore
::new();
302 ls
.register_builtin(None
);
303 describe_lints(&ls
, false);
306 let sess
= build_session(sopts
.clone(), None
, descriptions
.clone());
307 let should_stop
= RustcDefaultCalls
::print_crate_info(&sess
, None
, odir
, ofile
);
308 if should_stop
== Compilation
::Stop
{
311 early_error("no input filename given");
313 1 => panic
!("make_input should have provided valid inputs"),
314 _
=> early_error("multiple input filenames provided")
320 fn parse_pretty(&mut self,
322 matches
: &getopts
::Matches
)
323 -> Option
<(PpMode
, Option
<UserIdentifiedItem
>)> {
324 let pretty
= if sess
.opts
.debugging_opts
.unstable_options
{
325 matches
.opt_default("pretty", "normal").map(|a
| {
326 // stable pretty-print variants only
327 pretty
::parse_pretty(sess
, &a
, false)
332 if pretty
.is_none() && sess
.unstable_options() {
333 matches
.opt_str("xpretty").map(|a
| {
334 // extended with unstable pretty-print variants
335 pretty
::parse_pretty(sess
, &a
, true)
342 fn late_callback(&mut self,
343 matches
: &getopts
::Matches
,
347 ofile
: &Option
<Path
>)
349 RustcDefaultCalls
::print_crate_info(sess
, Some(input
), odir
, ofile
).and_then(
350 || RustcDefaultCalls
::list_metadata(sess
, matches
, input
))
353 fn build_controller(&mut self, sess
: &Session
) -> CompileController
<'a
> {
354 let mut control
= CompileController
::basic();
356 if sess
.opts
.parse_only
||
357 sess
.opts
.show_span
.is_some() ||
358 sess
.opts
.debugging_opts
.ast_json_noexpand
{
359 control
.after_parse
.stop
= Compilation
::Stop
;
362 if sess
.opts
.no_analysis
|| sess
.opts
.debugging_opts
.ast_json
{
363 control
.after_write_deps
.stop
= Compilation
::Stop
;
366 if sess
.opts
.no_trans
{
367 control
.after_analysis
.stop
= Compilation
::Stop
;
370 if !sess
.opts
.output_types
.iter().any(|&i
| i
== config
::OutputTypeExe
) {
371 control
.after_llvm
.stop
= Compilation
::Stop
;
374 if sess
.opts
.debugging_opts
.save_analysis
{
375 control
.after_analysis
.callback
= box |state
| {
376 time(state
.session
.time_passes(), "save analysis", state
.krate
.unwrap(), |krate
|
377 save
::process_crate(state
.session
,
379 state
.analysis
.unwrap(),
382 control
.make_glob_map
= resolve
::MakeGlobMap
::Yes
;
389 impl RustcDefaultCalls
{
390 pub fn list_metadata(sess
: &Session
,
391 matches
: &getopts
::Matches
,
394 let r
= matches
.opt_strs("Z");
395 if r
.contains(&("ls".to_string())) {
397 &Input
::File(ref ifile
) => {
398 let mut stdout
= old_io
::stdout();
399 let path
= &(*ifile
);
400 metadata
::loader
::list_file_metadata(sess
.target
.target
.options
.is_like_osx
,
402 &mut stdout
).unwrap();
405 early_error("cannot list metadata for stdin");
408 return Compilation
::Stop
;
411 return Compilation
::Continue
;
415 fn print_crate_info(sess
: &Session
,
416 input
: Option
<&Input
>,
418 ofile
: &Option
<Path
>)
420 if sess
.opts
.prints
.len() == 0 {
421 return Compilation
::Continue
;
424 let attrs
= input
.map(|input
| parse_crate_attrs(sess
, input
));
425 for req
in &sess
.opts
.prints
{
427 PrintRequest
::Sysroot
=> println
!("{}", sess
.sysroot().display()),
428 PrintRequest
::FileNames
|
429 PrintRequest
::CrateName
=> {
430 let input
= match input
{
431 Some(input
) => input
,
432 None
=> early_error("no input file provided"),
434 let attrs
= attrs
.as_ref().unwrap();
435 let t_outputs
= driver
::build_output_filenames(input
,
440 let id
= link
::find_crate_name(Some(sess
),
443 if *req
== PrintRequest
::CrateName
{
447 let crate_types
= driver
::collect_crate_types(sess
, attrs
);
448 let metadata
= driver
::collect_crate_metadata(sess
, attrs
);
449 *sess
.crate_metadata
.borrow_mut() = metadata
;
450 for &style
in &crate_types
{
451 let fname
= link
::filename_for_input(sess
,
454 &t_outputs
.with_extension(""));
455 println
!("{}", fname
.filename_display());
460 return Compilation
::Stop
;
464 /// Returns a version string such as "0.12.0-dev".
465 pub fn release_str() -> Option
<&'
static str> {
466 option_env
!("CFG_RELEASE")
469 /// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
470 pub fn commit_hash_str() -> Option
<&'
static str> {
471 option_env
!("CFG_VER_HASH")
474 /// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
475 pub fn commit_date_str() -> Option
<&'
static str> {
476 option_env
!("CFG_VER_DATE")
479 pub fn build_date_str() -> Option
<&'
static str> {
480 option_env
!("CFG_BUILD_DATE")
483 /// Prints version information and returns None on success or an error
484 /// message on panic.
485 pub fn version(binary
: &str, matches
: &getopts
::Matches
) {
486 let verbose
= matches
.opt_present("verbose");
488 println
!("{} {}", binary
, option_env
!("CFG_VERSION").unwrap_or("unknown version"));
490 fn unw(x
: Option
<&str>) -> &str { x.unwrap_or("unknown") }
491 println
!("binary: {}", binary
);
492 println
!("commit-hash: {}", unw(commit_hash_str()));
493 println
!("commit-date: {}", unw(commit_date_str()));
494 println
!("build-date: {}", unw(build_date_str()));
495 println
!("host: {}", config
::host_triple());
496 println
!("release: {}", unw(release_str()));
500 fn usage(verbose
: bool
, include_unstable_options
: bool
) {
501 let groups
= if verbose
{
502 config
::rustc_optgroups()
504 config
::rustc_short_optgroups()
506 let groups
: Vec
<_
> = groups
.into_iter()
507 .filter(|x
| include_unstable_options
|| x
.is_stable())
510 let message
= format
!("Usage: rustc [OPTIONS] INPUT");
511 let extra_help
= if verbose
{
514 "\n --help -v Print the full set of options rustc accepts"
518 -C help Print codegen options
519 -W help Print 'lint' options and default settings
520 -Z help Print internal options for debugging rustc{}\n",
521 getopts
::usage(&message
, &groups
),
525 fn describe_lints(lint_store
: &lint
::LintStore
, loaded_plugins
: bool
) {
527 Available lint options:
528 -W <foo> Warn about <foo>
531 -F <foo> Forbid <foo> (deny, and deny all overrides)
535 fn sort_lints(lints
: Vec
<(&'
static Lint
, bool
)>) -> Vec
<&'
static Lint
> {
536 let mut lints
: Vec
<_
> = lints
.into_iter().map(|(x
, _
)| x
).collect();
537 lints
.sort_by(|x
: &&Lint
, y
: &&Lint
| {
538 match x
.default_level
.cmp(&y
.default_level
) {
539 // The sort doesn't case-fold but it's doubtful we care.
540 Equal
=> x
.name
.cmp(y
.name
),
547 fn sort_lint_groups(lints
: Vec
<(&'
static str, Vec
<lint
::LintId
>, bool
)>)
548 -> Vec
<(&'
static str, Vec
<lint
::LintId
>)> {
549 let mut lints
: Vec
<_
> = lints
.into_iter().map(|(x
, y
, _
)| (x
, y
)).collect();
550 lints
.sort_by(|&(x
, _
): &(&'
static str, Vec
<lint
::LintId
>),
551 &(y
, _
): &(&'
static str, Vec
<lint
::LintId
>)| {
557 let (plugin
, builtin
): (Vec
<_
>, _
) = lint_store
.get_lints()
558 .iter().cloned().partition(|&(_
, p
)| p
);
559 let plugin
= sort_lints(plugin
);
560 let builtin
= sort_lints(builtin
);
562 let (plugin_groups
, builtin_groups
): (Vec
<_
>, _
) = lint_store
.get_lint_groups()
563 .iter().cloned().partition(|&(_
, _
, p
)| p
);
564 let plugin_groups
= sort_lint_groups(plugin_groups
);
565 let builtin_groups
= sort_lint_groups(builtin_groups
);
567 let max_name_len
= plugin
.iter().chain(builtin
.iter())
568 .map(|&s
| s
.name
.width(true))
570 let padded
= |x
: &str| {
571 let mut s
= repeat(" ").take(max_name_len
- x
.chars().count())
572 .collect
::<String
>();
577 println
!("Lint checks provided by rustc:\n");
578 println
!(" {} {:7.7} {}", padded("name"), "default", "meaning");
579 println
!(" {} {:7.7} {}", padded("----"), "-------", "-------");
581 let print_lints
= |lints
: Vec
<&Lint
>| {
583 let name
= lint
.name_lower().replace("_", "-");
584 println
!(" {} {:7.7} {}",
585 padded(&name
[..]), lint
.default_level
.as_str(), lint
.desc
);
590 print_lints(builtin
);
594 let max_name_len
= plugin_groups
.iter().chain(builtin_groups
.iter())
595 .map(|&(s
, _
)| s
.width(true))
597 let padded
= |x
: &str| {
598 let mut s
= repeat(" ").take(max_name_len
- x
.chars().count())
599 .collect
::<String
>();
604 println
!("Lint groups provided by rustc:\n");
605 println
!(" {} {}", padded("name"), "sub-lints");
606 println
!(" {} {}", padded("----"), "---------");
608 let print_lint_groups
= |lints
: Vec
<(&'
static str, Vec
<lint
::LintId
>)>| {
609 for (name
, to
) in lints
{
610 let name
= name
.chars().map(|x
| x
.to_lowercase())
611 .collect
::<String
>().replace("_", "-");
612 let desc
= to
.into_iter().map(|x
| x
.as_str().replace("_", "-"))
613 .collect
::<Vec
<String
>>().connect(", ");
615 padded(&name
[..]), desc
);
620 print_lint_groups(builtin_groups
);
622 match (loaded_plugins
, plugin
.len(), plugin_groups
.len()) {
623 (false, 0, _
) | (false, _
, 0) => {
624 println
!("Compiler plugins can provide additional lints and lint groups. To see a \
625 listing of these, re-run `rustc -W help` with a crate filename.");
627 (false, _
, _
) => panic
!("didn't load lint plugins but got them anyway!"),
628 (true, 0, 0) => println
!("This crate does not load any lint plugins or lint groups."),
631 println
!("Lint checks provided by plugins loaded by this crate:\n");
635 println
!("Lint groups provided by plugins loaded by this crate:\n");
636 print_lint_groups(plugin_groups
);
642 fn describe_debug_flags() {
643 println
!("\nAvailable debug options:\n");
644 for &(name
, _
, opt_type_desc
, desc
) in config
::DB_OPTIONS
{
645 let (width
, extra
) = match opt_type_desc
{
646 Some(..) => (21, "=val"),
649 println
!(" -Z {:>width$}{} -- {}", name
.replace("_", "-"),
650 extra
, desc
, width
=width
);
654 fn describe_codegen_flags() {
655 println
!("\nAvailable codegen options:\n");
656 for &(name
, _
, opt_type_desc
, desc
) in config
::CG_OPTIONS
{
657 let (width
, extra
) = match opt_type_desc
{
658 Some(..) => (21, "=val"),
661 println
!(" -C {:>width$}{} -- {}", name
.replace("_", "-"),
662 extra
, desc
, width
=width
);
666 /// Process command line options. Emits messages as appropriate. If compilation
667 /// should continue, returns a getopts::Matches object parsed from args, otherwise
669 pub fn handle_options(mut args
: Vec
<String
>) -> Option
<getopts
::Matches
> {
670 // Throw away the first argument, the name of the binary
671 let _binary
= args
.remove(0);
674 // user did not write `-v` nor `-Z unstable-options`, so do not
675 // include that extra information.
681 match getopts
::getopts(&args
[..], &config
::optgroups()[]) {
683 Err(f_stable_attempt
) => {
684 // redo option parsing, including unstable options this time,
685 // in anticipation that the mishandled option was one of the
687 let all_groups
: Vec
<getopts
::OptGroup
>
688 = config
::rustc_optgroups().into_iter().map(|x
|x
.opt_group
).collect();
689 match getopts
::getopts(&args
, &all_groups
) {
691 let r
= m_unstable
.opt_strs("Z");
692 let include_unstable_options
= r
.iter().any(|x
| *x
== "unstable-options");
693 if include_unstable_options
{
696 early_error(&f_stable_attempt
.to_string());
700 // ignore the error from the unstable attempt; just
701 // pass the error we got from the first try.
702 early_error(&f_stable_attempt
.to_string());
708 let r
= matches
.opt_strs("Z");
709 let include_unstable_options
= r
.iter().any(|x
| *x
== "unstable-options");
711 if matches
.opt_present("h") || matches
.opt_present("help") {
712 usage(matches
.opt_present("verbose"), include_unstable_options
);
716 // Don't handle -W help here, because we might first load plugins.
718 let r
= matches
.opt_strs("Z");
719 if r
.iter().any(|x
| *x
== "help") {
720 describe_debug_flags();
724 let cg_flags
= matches
.opt_strs("C");
725 if cg_flags
.iter().any(|x
| *x
== "help") {
726 describe_codegen_flags();
730 if cg_flags
.contains(&"passes=list".to_string()) {
731 unsafe { ::llvm::LLVMRustPrintPasses(); }
735 if matches
.opt_present("version") {
736 version("rustc", &matches
);
743 fn parse_crate_attrs(sess
: &Session
, input
: &Input
) ->
744 Vec
<ast
::Attribute
> {
745 let result
= match *input
{
746 Input
::File(ref ifile
) => {
747 parse
::parse_crate_attrs_from_file(ifile
,
751 Input
::Str(ref src
) => {
752 parse
::parse_crate_attrs_from_source_str(
753 driver
::anon_src().to_string(),
759 result
.into_iter().collect()
762 /// Run a procedure which will detect panics in the compiler and print nicer
763 /// error messages rather than just failing the test.
765 /// The diagnostic emitter yielded to the procedure should be used for reporting
766 /// errors of the compiler.
767 pub fn monitor
<F
:FnOnce()+Send
+'
static>(f
: F
) {
768 static STACK_SIZE
: uint
= 8 * 1024 * 1024; // 8MB
770 let (tx
, rx
) = channel();
771 let w
= old_io
::ChanWriter
::new(tx
);
772 let mut r
= old_io
::ChanReader
::new(rx
);
774 let mut cfg
= thread
::Builder
::new().name("rustc".to_string());
776 // FIXME: Hacks on hacks. If the env is trying to override the stack size
777 // then *don't* set it explicitly.
778 if env
::var_os("RUST_MIN_STACK").is_none() {
779 cfg
= cfg
.stack_size(STACK_SIZE
);
782 match cfg
.spawn(move || { stdio::set_stderr(box w); f() }
).unwrap().join() {
783 Ok(()) => { /* fallthrough */ }
785 // Thread panicked without emitting a fatal diagnostic
786 if !value
.is
::<diagnostic
::FatalError
>() {
787 let mut emitter
= diagnostic
::EmitterWriter
::stderr(diagnostic
::Auto
, None
);
789 // a .span_bug or .bug call has already printed what
790 // it wants to print.
791 if !value
.is
::<diagnostic
::ExplicitBug
>() {
800 "the compiler unexpectedly panicked. this is a bug.".to_string(),
801 format
!("we would appreciate a bug report: {}",
803 "run with `RUST_BACKTRACE=1` for a backtrace".to_string(),
806 emitter
.emit(None
, ¬e
[..], None
, diagnostic
::Note
)
809 match r
.read_to_string() {
810 Ok(s
) => println
!("{}", s
),
813 &format
!("failed to read internal \
821 // Panic so the process returns a failure code, but don't pollute the
822 // output with some unnecessary panic messages, we've already
823 // printed everything that we needed to.
824 old_io
::stdio
::set_stderr(box old_io
::util
::NullWriter
);
830 pub fn diagnostics_registry() -> diagnostics
::registry
::Registry
{
831 use syntax
::diagnostics
::registry
::Registry
;
833 let all_errors
= Vec
::new() +
834 rustc
::diagnostics
::DIAGNOSTICS
.as_slice() +
835 rustc_typeck
::diagnostics
::DIAGNOSTICS
.as_slice() +
836 rustc_resolve
::diagnostics
::DIAGNOSTICS
.as_slice();
838 Registry
::new(&*all_errors
)
842 let result
= run(env
::args().collect());
843 std
::env
::set_exit_status(result
as i32);