diff options
Diffstat (limited to 'src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs')
| -rw-r--r-- | src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs new file mode 100644 index 00000000000..be37dd867b2 --- /dev/null +++ b/src/doc/rustc-dev-guide/examples/rustc-interface-getting-diagnostics.rs @@ -0,0 +1,98 @@ +#![feature(rustc_private)] + +extern crate rustc_data_structures; +extern crate rustc_driver; +extern crate rustc_error_codes; +extern crate rustc_errors; +extern crate rustc_hash; +extern crate rustc_hir; +extern crate rustc_interface; +extern crate rustc_session; +extern crate rustc_span; + +use rustc_errors::emitter::Emitter; +use rustc_errors::registry::{self, Registry}; +use rustc_errors::translation::Translate; +use rustc_errors::{DiagCtxt, DiagInner, FluentBundle}; +use rustc_session::config; +use rustc_span::source_map::SourceMap; + +use std::sync::{Arc, Mutex}; + +struct DebugEmitter { + source_map: Arc<SourceMap>, + diagnostics: Arc<Mutex<Vec<DiagInner>>>, +} + +impl Translate for DebugEmitter { + fn fluent_bundle(&self) -> Option<&FluentBundle> { + None + } + + fn fallback_fluent_bundle(&self) -> &FluentBundle { + panic!("this emitter should not translate message") + } +} + +impl Emitter for DebugEmitter { + fn emit_diagnostic(&mut self, diag: DiagInner, _: &Registry) { + self.diagnostics.lock().unwrap().push(diag); + } + + fn source_map(&self) -> Option<&SourceMap> { + Some(&self.source_map) + } +} + +fn main() { + let buffer: Arc<Mutex<Vec<DiagInner>>> = Arc::default(); + let diagnostics = buffer.clone(); + let config = rustc_interface::Config { + opts: config::Options::default(), + // This program contains a type error. + input: config::Input::Str { + name: rustc_span::FileName::Custom("main.rs".into()), + input: " +fn main() { + let x: &str = 1; +} +" + .into(), + }, + crate_cfg: Vec::new(), + crate_check_cfg: Vec::new(), + output_dir: None, + output_file: None, + file_loader: None, + locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES.to_owned(), + lint_caps: rustc_hash::FxHashMap::default(), + psess_created: Some(Box::new(|parse_sess| { + parse_sess.set_dcx(DiagCtxt::new(Box::new(DebugEmitter { + source_map: parse_sess.clone_source_map(), + diagnostics, + }))); + })), + register_lints: None, + override_queries: None, + registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), + make_codegen_backend: None, + expanded_args: Vec::new(), + ice_file: None, + hash_untracked_state: None, + using_internal_features: Arc::default(), + }; + rustc_interface::run_compiler(config, |compiler| { + let krate = rustc_interface::passes::parse(&compiler.sess); + rustc_interface::create_and_enter_global_ctxt(&compiler, krate, |tcx| { + // Run the analysis phase on the local crate to trigger the type error. + let _ = tcx.analysis(()); + }); + // If the compiler has encountered errors when this closure returns, it will abort (!) the program. + // We avoid this by resetting the error count before returning + compiler.sess.dcx().reset_err_count(); + }); + // Read buffered diagnostics. + buffer.lock().unwrap().iter().for_each(|diagnostic| { + println!("{diagnostic:#?}"); + }); +} |
