| // 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<String> { | |
| 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<Arc<[u8]>> { | |
| 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, | |
| ); | |
| } |