diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index ed28b05c12551..8dcbda917b243 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -414,6 +414,75 @@ impl<'a> CompileController<'a> { } } +/// This implementation makes it easier to create a custom driver when you only want to hook +/// into callbacks from `CompileController`. +/// +/// # Example +/// +/// ```no_run +/// # extern crate rustc_driver; +/// # use rustc_driver::driver::CompileController; +/// let mut controller = CompileController::basic(); +/// controller.after_analysis.callback = Box::new(move |_state| {}); +/// rustc_driver::run_compiler(&[], Box::new(controller), None, None); +/// ``` +impl<'a> ::CompilerCalls<'a> for CompileController<'a> { + fn early_callback( + &mut self, + matches: &::getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + descriptions: &::errors::registry::Registry, + output: ::ErrorOutputType, + ) -> Compilation { + ::RustcDefaultCalls.early_callback( + matches, + sopts, + cfg, + descriptions, + output, + ) + } + fn no_input( + &mut self, + matches: &::getopts::Matches, + sopts: &config::Options, + cfg: &ast::CrateConfig, + odir: &Option, + ofile: &Option, + descriptions: &::errors::registry::Registry, + ) -> Option<(Input, Option)> { + ::RustcDefaultCalls.no_input( + matches, + sopts, + cfg, + odir, + ofile, + descriptions, + ) + } + fn late_callback( + &mut self, + codegen_backend: &::CodegenBackend, + matches: &::getopts::Matches, + sess: &Session, + cstore: &::CrateStore, + input: &Input, + odir: &Option, + ofile: &Option, + ) -> Compilation { + ::RustcDefaultCalls + .late_callback(codegen_backend, matches, sess, cstore, input, odir, ofile) + } + fn build_controller( + self: Box, + _: &Session, + _: &::getopts::Matches + ) -> CompileController<'a> { + *self + } +} + pub struct PhaseController<'a> { pub stop: Compilation, // If true then the compiler will try to run the callback even if the phase diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 2f89814032ef6..67fd5da8c92d9 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -454,7 +454,7 @@ fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box { // 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: &mut (CompilerCalls<'a> + sync::Send), + callbacks: Box + sync::Send + 'a>, file_loader: Option>, emitter_dest: Option>) -> (CompileResult, Option) @@ -478,7 +478,7 @@ fn run_compiler_with_pool<'a>( matches: getopts::Matches, sopts: config::Options, cfg: ast::CrateConfig, - callbacks: &mut (CompilerCalls<'a> + sync::Send), + mut callbacks: Box + sync::Send + 'a>, file_loader: Option>, emitter_dest: Option> ) -> (CompileResult, Option) { @@ -642,12 +642,12 @@ impl Compilation { } } -// A trait for customising the compilation process. Offers a number of hooks for -// executing custom code or customising input. +/// A trait for customising the compilation process. Offers a number of hooks for +/// executing custom code or customising input. pub trait CompilerCalls<'a> { - // Hook for a callback early in the process of handling arguments. This will - // be called straight after options have been parsed but before anything - // else (e.g., selecting input and output). + /// Hook for a callback early in the process of handling arguments. This will + /// be called straight after options have been parsed but before anything + /// else (e.g., selecting input and output). fn early_callback(&mut self, _: &getopts::Matches, _: &config::Options, @@ -658,9 +658,9 @@ pub trait CompilerCalls<'a> { Compilation::Continue } - // Hook for a callback late in the process of handling arguments. This will - // be called just before actual compilation starts (and before build_controller - // is called), after all arguments etc. have been completely handled. + /// Hook for a callback late in the process of handling arguments. This will + /// 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, _: &getopts::Matches, @@ -673,9 +673,9 @@ pub trait CompilerCalls<'a> { Compilation::Continue } - // Called after we extract the input from the arguments. Gives the implementer - // an opportunity to change the inputs or to add some custom input handling. - // The default behaviour is to simply pass through the inputs. + /// Called after we extract the input from the arguments. Gives the implementer + /// an opportunity to change the inputs or to add some custom input handling. + /// The default behaviour is to simply pass through the inputs. fn some_input(&mut self, input: Input, input_path: Option) @@ -683,11 +683,11 @@ pub trait CompilerCalls<'a> { (input, input_path) } - // Called after we extract the input from the arguments if there is no valid - // input. Gives the implementer an opportunity to supply alternate input (by - // returning a Some value) or to add custom behaviour for this error such as - // emitting error messages. Returning None will cause compilation to stop - // at this point. + /// Called after we extract the input from the arguments if there is no valid + /// input. Gives the implementer an opportunity to supply alternate input (by + /// returning a Some value) or to add custom behaviour for this error such as + /// emitting error messages. Returning None will cause compilation to stop + /// at this point. fn no_input(&mut self, _: &getopts::Matches, _: &config::Options, @@ -701,10 +701,14 @@ pub trait CompilerCalls<'a> { // Create a CompilController struct for controlling the behaviour of // compilation. - fn build_controller(&mut self, _: &Session, _: &getopts::Matches) -> CompileController<'a>; + fn build_controller( + self: Box, + _: &Session, + _: &getopts::Matches + ) -> CompileController<'a>; } -// CompilerCalls instance for a regular rustc build. +/// CompilerCalls instance for a regular rustc build. #[derive(Copy, Clone)] pub struct RustcDefaultCalls; @@ -878,7 +882,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { .and_then(|| RustcDefaultCalls::list_metadata(sess, cstore, matches, input)) } - fn build_controller(&mut self, + fn build_controller(self: Box, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> { @@ -1693,7 +1697,7 @@ pub fn main() { })) .collect::>(); run_compiler(&args, - &mut RustcDefaultCalls, + Box::new(RustcDefaultCalls), None, None) }); diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index 9aa4f42c8ac86..b3a6fb4d590ae 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -31,11 +31,11 @@ use syntax::ast; use std::path::PathBuf; -struct TestCalls { - count: u32 +struct TestCalls<'a> { + count: &'a mut u32 } -impl<'a> CompilerCalls<'a> for TestCalls { +impl<'a> CompilerCalls<'a> for TestCalls<'a> { fn early_callback(&mut self, _: &getopts::Matches, _: &config::Options, @@ -43,7 +43,7 @@ impl<'a> CompilerCalls<'a> for TestCalls { _: &errors::registry::Registry, _: config::ErrorOutputType) -> Compilation { - self.count *= 2; + *self.count *= 2; Compilation::Continue } @@ -56,13 +56,13 @@ impl<'a> CompilerCalls<'a> for TestCalls { _: &Option, _: &Option) -> Compilation { - self.count *= 3; + *self.count *= 3; Compilation::Stop } fn some_input(&mut self, input: Input, input_path: Option) -> (Input, Option) { - self.count *= 5; + *self.count *= 5; (input, input_path) } @@ -77,7 +77,7 @@ impl<'a> CompilerCalls<'a> for TestCalls { panic!("This shouldn't happen"); } - fn build_controller(&mut self, + fn build_controller(self: Box, _: &Session, _: &getopts::Matches) -> driver::CompileController<'a> { @@ -87,9 +87,12 @@ impl<'a> CompilerCalls<'a> for TestCalls { fn main() { - let mut tc = TestCalls { count: 1 }; - // we should never get use this filename, but lets make sure they are valid args. - let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; - rustc_driver::run_compiler(&args, &mut tc, None, None); - assert_eq!(tc.count, 30); + let mut count = 1; + { + let tc = TestCalls { count: &mut count }; + // we should never get use this filename, but lets make sure they are valid args. + let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; + rustc_driver::run_compiler(&args, Box::new(tc), None, None); + } + assert_eq!(count, 30); }