// Tested with nightly-2025-03-28 #![feature(rustc_private)] extern crate rustc_ast; extern crate rustc_ast_pretty; 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_middle; extern crate rustc_session; extern crate rustc_span; use std::io; use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; use rustc_driver::{Compilation, run_compiler}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; struct MyFileLoader; impl rustc_span::source_map::FileLoader for MyFileLoader { fn file_exists(&self, path: &Path) -> bool { path == Path::new("main.rs") } fn read_file(&self, path: &Path) -> io::Result { if path == Path::new("main.rs") { Ok(r#" static MESSAGE: &str = "Hello, World!"; fn main() { println!("{MESSAGE}"); } "# .to_string()) } else { Err(io::Error::other("oops")) } } fn read_binary_file(&self, _path: &Path) -> io::Result> { Err(io::Error::other("oops")) } } struct MyCallbacks; impl rustc_driver::Callbacks for MyCallbacks { fn config(&mut self, config: &mut Config) { config.file_loader = Some(Box::new(MyFileLoader)); } fn after_crate_root_parsing( &mut self, _compiler: &Compiler, krate: &mut rustc_ast::Crate, ) -> Compilation { for item in &krate.items { println!("{}", item_to_string(&item)); } Compilation::Continue } fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { // Analyze the program and inspect the types of definitions. for id in tcx.hir_free_items() { let item = &tcx.hir_item(id); match item.kind { rustc_hir::ItemKind::Static(ident, ..) | rustc_hir::ItemKind::Fn { ident, .. } => { let ty = tcx.type_of(item.hir_id().owner.def_id); println!("{ident:?}:\t{ty:?}") } _ => (), } } Compilation::Stop } } fn main() { run_compiler( &[ // The first argument, which in practice contains the name of the binary being executed // (i.e. "rustc") is ignored by rustc. "ignored".to_string(), "main.rs".to_string(), ], &mut MyCallbacks, ); }