#![feature(rustc_private)] // NOTE: For the example to compile, you will need to first run the following: // rustup component add rustc-dev llvm-tools-preview // version: rustc 1.68.0-nightly (935dc0721 2022-12-19) 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 std::{path, process, str}; use rustc_errors::registry; use rustc_hash::{FxHashMap, FxHashSet}; use rustc_session::config::{self, CheckCfg}; use rustc_span::source_map; 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 config = rustc_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 crate_cfg: FxHashSet::default(), // FxHashSet<(String, Option)> crate_check_cfg: CheckCfg::default(), // CheckCfg input: config::Input::Str { name: source_map::FileName::Custom("main.rs".into()), input: r#" static HELLO: &str = "Hello, world!"; fn main() { println!("{HELLO}"); } "# .into(), }, input_path: None, // Option output_dir: None, // Option output_file: None, // Option file_loader: None, // Option> lint_caps: FxHashMap::default(), // FxHashMap // This is a callback from the driver that is called when [`ParseSess`] is created. parse_sess_created: None, //Option> // 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. register_lints: None, // Option> // 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. override_queries: None, // Option, &mut ty::query::Providers<'_>)> // Registry of diagnostics codes. registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS), make_codegen_backend: None, }; rustc_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 id in tcx.hir().items() { let hir = tcx.hir(); let item = hir.item(id); match item.kind { rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { let name = item.ident; let ty = tcx.type_of(hir.local_def_id(item.hir_id())); println!("{name:?}:\t{ty:?}") } _ => (), } } }) }); }); }