]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_driver/lib.rs
Simplify
[rust.git] / src / librustc_driver / lib.rs
index 1078dadce25f596d1d1b6efc26c359d8cad0d8de..3ec73059721a244b71675ed6b97800aa0fa14824 100644 (file)
@@ -14,6 +14,8 @@
 //!
 //! This API is completely unstable and subject to change.
 
+#![deny(bare_trait_objects)]
+
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 use std::default::Default;
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::env;
+use std::error::Error;
 use std::ffi::OsString;
+use std::fmt::{self, Display};
 use std::io::{self, Read, Write};
-use std::iter::repeat;
 use std::mem;
 use std::panic;
 use std::path::{PathBuf, Path};
@@ -131,7 +134,7 @@ pub mod target_features {
     /// features is available on the target machine, by querying LLVM.
     pub fn add_configuration(cfg: &mut ast::CrateConfig,
                              sess: &Session,
-                             codegen_backend: &CodegenBackend) {
+                             codegen_backend: &dyn CodegenBackend) {
         let tf = Symbol::intern("target_feature");
 
         for feat in codegen_backend.target_features(sess) {
@@ -144,6 +147,12 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig,
     }
 }
 
+/// Exit status code used for successful compilation and help output.
+pub const EXIT_SUCCESS: isize = 0;
+
+/// Exit status code used for compilation failures and  invalid flags.
+pub const EXIT_FAILURE: isize = 1;
+
 const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
                                       md#bug-reports";
 
@@ -176,7 +185,7 @@ pub fn abort_on_err<T>(result: Result<T, CompileIncomplete>, sess: &Session) ->
 pub fn run<F>(run_compiler: F) -> isize
     where F: FnOnce() -> (CompileResult, Option<Session>) + Send + 'static
 {
-    monitor(move || {
+    let result = monitor(move || {
         let (result, session) = run_compiler();
         if let Err(CompileIncomplete::Errored(_)) = result {
             match session {
@@ -199,10 +208,14 @@ pub fn run<F>(run_compiler: F) -> isize
             }
         }
     });
-    0
+
+    match result {
+        Ok(()) => EXIT_SUCCESS,
+        Err(_) => EXIT_FAILURE,
+    }
 }
 
-fn load_backend_from_dylib(path: &Path) -> fn() -> Box<CodegenBackend> {
+fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
     // Note that we're specifically using `open_global_now` here rather than
     // `open`, namely we want the behavior on Unix of RTLD_GLOBAL and RTLD_NOW,
     // where NOW means "bind everything right now" because we don't want
@@ -235,12 +248,12 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box<CodegenBackend> {
     }
 }
 
-pub fn get_codegen_backend(sess: &Session) -> Box<CodegenBackend> {
+pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
     static INIT: Once = ONCE_INIT;
 
     #[allow(deprecated)]
     #[no_debug]
-    static mut LOAD: fn() -> Box<CodegenBackend> = || unreachable!();
+    static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
 
     INIT.call_once(|| {
         let codegen_name = sess.opts.debugging_opts.codegen_backend.as_ref()
@@ -264,7 +277,7 @@ pub fn get_codegen_backend(sess: &Session) -> Box<CodegenBackend> {
     backend
 }
 
-fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<CodegenBackend> {
+fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> {
     // For now we only allow this function to be called once as it'll dlopen a
     // few things, which seems to work best if we only do that once. In
     // general this assertion never trips due to the once guard in `get_codegen_backend`,
@@ -454,9 +467,9 @@ fn GetModuleFileNameW(hModule: usize,
 // See comments on CompilerCalls below for details about the callbacks argument.
 // The FileLoader provides a way to load files from sources other than the file system.
 pub fn run_compiler<'a>(args: &[String],
-                        callbacks: Box<CompilerCalls<'a> + sync::Send + 'a>,
-                        file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
-                        emitter_dest: Option<Box<Write + Send>>)
+                        callbacks: Box<dyn CompilerCalls<'a> + sync::Send + 'a>,
+                        file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
+                        emitter_dest: Option<Box<dyn Write + Send>>)
                         -> (CompileResult, Option<Session>)
 {
     syntax::with_globals(|| {
@@ -478,9 +491,9 @@ fn run_compiler_with_pool<'a>(
     matches: getopts::Matches,
     sopts: config::Options,
     cfg: ast::CrateConfig,
-    mut callbacks: Box<CompilerCalls<'a> + sync::Send + 'a>,
-    file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
-    emitter_dest: Option<Box<Write + Send>>
+    mut callbacks: Box<dyn CompilerCalls<'a> + sync::Send + 'a>,
+    file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
+    emitter_dest: Option<Box<dyn Write + Send>>
 ) -> (CompileResult, Option<Session>) {
     macro_rules! do_or_return {($expr: expr, $sess: expr) => {
         match $expr {
@@ -662,10 +675,10 @@ fn early_callback(&mut self,
     /// be called just before actual compilation starts (and before build_controller
     /// is called), after all arguments etc. have been completely handled.
     fn late_callback(&mut self,
-                     _: &CodegenBackend,
+                     _: &dyn CodegenBackend,
                      _: &getopts::Matches,
                      _: &Session,
-                     _: &CrateStore,
+                     _: &dyn CrateStore,
                      _: &Input,
                      _: &Option<PathBuf>,
                      _: &Option<PathBuf>)
@@ -870,10 +883,10 @@ fn no_input(&mut self,
     }
 
     fn late_callback(&mut self,
-                     codegen_backend: &CodegenBackend,
+                     codegen_backend: &dyn CodegenBackend,
                      matches: &getopts::Matches,
                      sess: &Session,
-                     cstore: &CrateStore,
+                     cstore: &dyn CrateStore,
                      input: &Input,
                      odir: &Option<PathBuf>,
                      ofile: &Option<PathBuf>)
@@ -979,7 +992,7 @@ pub fn enable_save_analysis(control: &mut CompileController) {
 
 impl RustcDefaultCalls {
     pub fn list_metadata(sess: &Session,
-                         cstore: &CrateStore,
+                         cstore: &dyn CrateStore,
                          matches: &getopts::Matches,
                          input: &Input)
                          -> Compilation {
@@ -1007,7 +1020,7 @@ pub fn list_metadata(sess: &Session,
     }
 
 
-    fn print_crate_info(codegen_backend: &CodegenBackend,
+    fn print_crate_info(codegen_backend: &dyn CodegenBackend,
                         sess: &Session,
                         input: Option<&Input>,
                         odir: &Option<PathBuf>,
@@ -1215,10 +1228,7 @@ fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static
     fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
                         -> Vec<(&'static str, Vec<lint::LintId>)> {
         let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
-        lints.sort_by(|&(x, _): &(&'static str, Vec<lint::LintId>),
-                       &(y, _): &(&'static str, Vec<lint::LintId>)| {
-            x.cmp(y)
-        });
+        lints.sort_by_key(|l| l.0);
         lints
     }
 
@@ -1242,9 +1252,7 @@ fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
                              .max()
                              .unwrap_or(0);
     let padded = |x: &str| {
-        let mut s = repeat(" ")
-                        .take(max_name_len - x.chars().count())
-                        .collect::<String>();
+        let mut s = " ".repeat(max_name_len - x.chars().count());
         s.push_str(x);
         s
     };
@@ -1276,9 +1284,7 @@ fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
                                         .unwrap_or(0));
 
     let padded = |x: &str| {
-        let mut s = repeat(" ")
-                        .take(max_name_len - x.chars().count())
-                        .collect::<String>();
+        let mut s = " ".repeat(max_name_len - x.chars().count());
         s.push_str(x);
         s
     };
@@ -1483,10 +1489,12 @@ fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec<as
     }
 }
 
-/// Runs `f` in a suitable thread for running `rustc`; returns a
-/// `Result` with either the return value of `f` or -- if a panic
-/// occurs -- the panic value.
-pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
+/// Runs `f` in a suitable thread for running `rustc`; returns a `Result` with either the return
+/// value of `f` or -- if a panic occurs -- the panic value.
+///
+/// This version applies the given name to the thread. This is used by rustdoc to ensure consistent
+/// doctest output across platforms and executions.
+pub fn in_named_rustc_thread<F, R>(name: String, f: F) -> Result<R, Box<dyn Any + Send>>
     where F: FnOnce() -> R + Send + 'static,
           R: Send + 'static,
 {
@@ -1550,7 +1558,7 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
 
     // The or condition is added from backward compatibility.
     if spawn_thread || env::var_os("RUST_MIN_STACK").is_some() {
-        let mut cfg = thread::Builder::new().name("rustc".to_string());
+        let mut cfg = thread::Builder::new().name(name);
 
         // FIXME: Hacks on hacks. If the env is trying to override the stack size
         // then *don't* set it explicitly.
@@ -1566,6 +1574,16 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
     }
 }
 
+/// Runs `f` in a suitable thread for running `rustc`; returns a
+/// `Result` with either the return value of `f` or -- if a panic
+/// occurs -- the panic value.
+pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<dyn Any + Send>>
+    where F: FnOnce() -> R + Send + 'static,
+          R: Send + 'static,
+{
+    in_named_rustc_thread("rustc".to_string(), f)
+}
+
 /// Get a list of extra command-line flags provided by the user, as strings.
 ///
 /// This function is used during ICEs to show more information useful for
@@ -1623,20 +1641,30 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
     }
 }
 
+#[derive(Debug)]
+pub struct CompilationFailure;
+
+impl Error for CompilationFailure {}
+
+impl Display for CompilationFailure {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "compilation had errors")
+    }
+}
+
 /// Run a procedure which will detect panics in the compiler and print nicer
 /// error messages rather than just failing the test.
 ///
 /// The diagnostic emitter yielded to the procedure should be used for reporting
 /// errors of the compiler.
-pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
-    let result = in_rustc_thread(move || {
+pub fn monitor<F: FnOnce() + Send + 'static>(f: F) -> Result<(), CompilationFailure> {
+    in_rustc_thread(move || {
         f()
-    });
-
-    if let Err(value) = result {
-        // Thread panicked without emitting a fatal diagnostic
-        if !value.is::<errors::FatalErrorMarker>() {
-            // Emit a newline
+    }).map_err(|value| {
+        if value.is::<errors::FatalErrorMarker>() {
+            CompilationFailure
+        } else {
+            // Thread panicked without emitting a fatal diagnostic
             eprintln!("");
 
             let emitter =
@@ -1675,10 +1703,10 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
                              &note,
                              errors::Level::Note);
             }
-        }
 
-        panic::resume_unwind(Box::new(errors::FatalErrorMarker));
-    }
+            panic::resume_unwind(Box::new(errors::FatalErrorMarker));
+        }
+    })
 }
 
 pub fn diagnostics_registry() -> errors::registry::Registry {