diff --git a/examples/rustc-driver-example.rs b/examples/rustc-driver-example.rs new file mode 100644 index 00000000..3c483e77 --- /dev/null +++ b/examples/rustc-driver-example.rs @@ -0,0 +1,103 @@ +#![feature(rustc_private)] + +extern crate rustc; +extern crate rustc_error_codes; +extern crate rustc_errors; +extern crate rustc_hash; +extern crate rustc_hir; +extern crate rustc_interface; +extern crate rustc_span; + +use rustc::session; +use rustc::session::config; +use rustc_errors::registry; +use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_interface::interface; +use rustc_span::source_map; +use std::path; +use std::process; +use std::str; + +fn main() { + let out = process::Command::new("rustc") + .arg("--print=sysroot") + .current_dir(".") + .output() + .unwrap(); + let sysroot = str::from_utf8(&out.stdout).unwrap().trim(); + let filename = "main.rs"; + let contents = "static HELLO: &str = \"Hello, world!\"; fn main() { println!(\"{}\", HELLO); }"; + let errors = registry::Registry::new(&rustc_error_codes::DIAGNOSTICS); + let config = interface::Config { + // Command line options + opts: config::Options { + maybe_sysroot: Some(path::PathBuf::from(sysroot)), + ..config::Options::default() + }, + + // cfg! configuration in addition to the default ones + // FxHashSet<(String, Option)> + crate_cfg: FxHashSet::default(), + + input: config::Input::Str { + name: source_map::FileName::Custom(String::from(filename)), + input: String::from(contents), + }, + // Option + input_path: None, + // Option + output_dir: None, + // Option + output_file: None, + // Option> + file_loader: None, + diagnostic_output: session::DiagnosticOutput::Default, + + // Set to capture stderr output during compiler execution + // Option>>> + stderr: None, + + // Option + crate_name: None, + // FxHashMap + lint_caps: FxHashMap::default(), + + // This is a callback from the driver that is called when we're registering lints; + // it is called during plugin registration when we have the LintStore in a non-shared state. + // + // Note that if you find a Some here you probably want to call that function in the new + // function being registered. + // Option> + register_lints: None, + + // This is a callback from the driver that is called just after we have populated + // the list of queries. + // + // The second parameter is local providers and the third parameter is external providers. + // Option, &mut ty::query::Providers<'_>)> + override_queries: None, + + // Registry of diagnostics codes. + registry: errors, + }; + interface::run_compiler(config, |compiler| { + compiler.enter(|queries| { + // Parse the program and print the syntax tree. + let parse = queries.parse().unwrap().take(); + println!("{:#?}", parse); + // Analyze the program and inspect the types of definitions. + queries.global_ctxt().unwrap().take().enter(|tcx| { + for (_, item) in &tcx.hir().krate().items { + match item.kind { + rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { + let name = item.ident; + let ty = tcx.type_of(tcx.hir().local_def_id(item.hir_id)); + println!("{:?}:\t{:?}", name, ty) + } + _ => (), + } + } + }) + }); + }); +}