|  | 
| 1 | 1 | #![feature(rustc_private)] | 
| 2 | 2 | 
 | 
|  | 3 | +extern crate rustc_ast; | 
|  | 4 | +extern crate rustc_ast_pretty; | 
|  | 5 | +extern crate rustc_data_structures; | 
| 3 | 6 | extern crate rustc_driver; | 
| 4 | 7 | extern crate rustc_error_codes; | 
| 5 | 8 | extern crate rustc_errors; | 
| 6 | 9 | extern crate rustc_hash; | 
| 7 | 10 | extern crate rustc_hir; | 
| 8 | 11 | extern crate rustc_interface; | 
|  | 12 | +extern crate rustc_middle; | 
| 9 | 13 | extern crate rustc_session; | 
| 10 | 14 | extern crate rustc_span; | 
| 11 | 15 | 
 | 
| 12 |  | -use std::{path, process, str, sync::Arc}; | 
|  | 16 | +use std::io; | 
|  | 17 | +use std::path::Path; | 
| 13 | 18 | 
 | 
| 14 |  | -use rustc_errors::registry; | 
| 15 |  | -use rustc_hash::FxHashMap; | 
| 16 |  | -use rustc_session::config; | 
|  | 19 | +use rustc_ast_pretty::pprust::item_to_string; | 
|  | 20 | +use rustc_data_structures::sync::Lrc; | 
|  | 21 | +use rustc_driver::{Compilation, RunCompiler}; | 
|  | 22 | +use rustc_interface::interface::Compiler; | 
|  | 23 | +use rustc_middle::ty::TyCtxt; | 
| 17 | 24 | 
 | 
|  | 25 | +struct MyFileLoader; | 
|  | 26 | + | 
|  | 27 | +impl rustc_span::source_map::FileLoader for MyFileLoader { | 
|  | 28 | +    fn file_exists(&self, path: &Path) -> bool { | 
|  | 29 | +        path == Path::new("main.rs") | 
|  | 30 | +    } | 
|  | 31 | + | 
|  | 32 | +    fn read_file(&self, path: &Path) -> io::Result<String> { | 
|  | 33 | +        if path == Path::new("main.rs") { | 
|  | 34 | +            Ok(r#" | 
| 18 | 35 | fn main() { | 
| 19 |  | -    let out = process::Command::new("rustc") | 
| 20 |  | -        .arg("--print=sysroot") | 
| 21 |  | -        .current_dir(".") | 
| 22 |  | -        .output() | 
| 23 |  | -        .unwrap(); | 
| 24 |  | -    let sysroot = str::from_utf8(&out.stdout).unwrap().trim(); | 
| 25 |  | -    let config = rustc_interface::Config { | 
| 26 |  | -        // Command line options | 
| 27 |  | -        opts: config::Options { | 
| 28 |  | -            maybe_sysroot: Some(path::PathBuf::from(sysroot)), | 
| 29 |  | -            ..config::Options::default() | 
| 30 |  | -        }, | 
| 31 |  | -        // cfg! configuration in addition to the default ones | 
| 32 |  | -        crate_cfg: Vec::new(),       // FxHashSet<(String, Option<String>)> | 
| 33 |  | -        crate_check_cfg: Vec::new(), // CheckCfg | 
| 34 |  | -        input: config::Input::Str { | 
| 35 |  | -            name: rustc_span::FileName::Custom("main.rs".into()), | 
| 36 |  | -            input: r#" | 
| 37 |  | -static HELLO: &str = "Hello, world!"; | 
| 38 |  | -fn main() { | 
| 39 |  | -    println!("{HELLO}"); | 
|  | 36 | +    let message = "Hello, World!"; | 
|  | 37 | +    println!("{message}"); | 
| 40 | 38 | } | 
| 41 | 39 | "# | 
| 42 |  | -            .into(), | 
| 43 |  | -        }, | 
| 44 |  | -        output_dir: None,  // Option<PathBuf> | 
| 45 |  | -        output_file: None, // Option<PathBuf> | 
| 46 |  | -        file_loader: None, // Option<Box<dyn FileLoader + Send + Sync>> | 
| 47 |  | -        locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES, | 
| 48 |  | -        lint_caps: FxHashMap::default(), // FxHashMap<lint::LintId, lint::Level> | 
| 49 |  | -        // This is a callback from the driver that is called when [`ParseSess`] is created. | 
| 50 |  | -        psess_created: None, //Option<Box<dyn FnOnce(&mut ParseSess) + Send>> | 
| 51 |  | -        // This is a callback from the driver that is called when we're registering lints; | 
| 52 |  | -        // it is called during plugin registration when we have the LintStore in a non-shared state. | 
| 53 |  | -        // | 
| 54 |  | -        // Note that if you find a Some here you probably want to call that function in the new | 
| 55 |  | -        // function being registered. | 
| 56 |  | -        register_lints: None, // Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> | 
| 57 |  | -        // This is a callback from the driver that is called just after we have populated | 
| 58 |  | -        // the list of queries. | 
| 59 |  | -        // | 
| 60 |  | -        // The second parameter is local providers and the third parameter is external providers. | 
| 61 |  | -        override_queries: None, // Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)> | 
| 62 |  | -        // Registry of diagnostics codes. | 
| 63 |  | -        registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), | 
| 64 |  | -        make_codegen_backend: None, | 
| 65 |  | -        expanded_args: Vec::new(), | 
| 66 |  | -        ice_file: None, | 
| 67 |  | -        hash_untracked_state: None, | 
| 68 |  | -        using_internal_features: Arc::default(), | 
| 69 |  | -    }; | 
| 70 |  | -    rustc_interface::run_compiler(config, |compiler| { | 
| 71 |  | -        compiler.enter(|queries| { | 
| 72 |  | -            // Parse the program and print the syntax tree. | 
| 73 |  | -            let parse = queries.parse().unwrap().get_mut().clone(); | 
| 74 |  | -            println!("{parse:?}"); | 
| 75 |  | -            // Analyze the program and inspect the types of definitions. | 
| 76 |  | -            queries.global_ctxt().unwrap().enter(|tcx| { | 
| 77 |  | -                for id in tcx.hir().items() { | 
| 78 |  | -                    let hir = tcx.hir(); | 
| 79 |  | -                    let item = hir.item(id); | 
| 80 |  | -                    match item.kind { | 
| 81 |  | -                        rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { | 
| 82 |  | -                            let name = item.ident; | 
| 83 |  | -                            let ty = tcx.type_of(item.hir_id().owner.def_id); | 
| 84 |  | -                            println!("{name:?}:\t{ty:?}") | 
| 85 |  | -                        } | 
| 86 |  | -                        _ => (), | 
| 87 |  | -                    } | 
|  | 40 | +            .to_string()) | 
|  | 41 | +        } else { | 
|  | 42 | +            Err(io::Error::other("oops")) | 
|  | 43 | +        } | 
|  | 44 | +    } | 
|  | 45 | + | 
|  | 46 | +    fn read_binary_file(&self, _path: &Path) -> io::Result<Lrc<[u8]>> { | 
|  | 47 | +        Err(io::Error::other("oops")) | 
|  | 48 | +    } | 
|  | 49 | +} | 
|  | 50 | + | 
|  | 51 | +struct MyCallbacks; | 
|  | 52 | + | 
|  | 53 | +impl rustc_driver::Callbacks for MyCallbacks { | 
|  | 54 | +    fn after_crate_root_parsing( | 
|  | 55 | +        &mut self, | 
|  | 56 | +        _compiler: &Compiler, | 
|  | 57 | +        krate: &rustc_ast::Crate, | 
|  | 58 | +    ) -> Compilation { | 
|  | 59 | +        for item in &krate.items { | 
|  | 60 | +            println!("{}", item_to_string(&item)); | 
|  | 61 | +        } | 
|  | 62 | + | 
|  | 63 | +        Compilation::Continue | 
|  | 64 | +    } | 
|  | 65 | + | 
|  | 66 | +    fn after_analysis(&mut self, _compiler: &Compiler, tcx: TyCtxt<'_>) -> Compilation { | 
|  | 67 | +        // Analyze the program and inspect the types of definitions. | 
|  | 68 | +        for id in tcx.hir().items() { | 
|  | 69 | +            let hir = tcx.hir(); | 
|  | 70 | +            let item = hir.item(id); | 
|  | 71 | +            match item.kind { | 
|  | 72 | +                rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { | 
|  | 73 | +                    let name = item.ident; | 
|  | 74 | +                    let ty = tcx.type_of(item.hir_id().owner.def_id); | 
|  | 75 | +                    println!("{name:?}:\t{ty:?}") | 
| 88 | 76 |                 } | 
| 89 |  | -            }) | 
| 90 |  | -        }); | 
| 91 |  | -    }); | 
|  | 77 | +                _ => (), | 
|  | 78 | +            } | 
|  | 79 | +        } | 
|  | 80 | + | 
|  | 81 | +        Compilation::Stop | 
|  | 82 | +    } | 
|  | 83 | +} | 
|  | 84 | + | 
|  | 85 | +fn main() { | 
|  | 86 | +    match RunCompiler::new(&["main.rs".to_string()], &mut MyCallbacks) { | 
|  | 87 | +        mut compiler => { | 
|  | 88 | +            compiler.set_file_loader(Some(Box::new(MyFileLoader))); | 
|  | 89 | +            compiler.run(); | 
|  | 90 | +        } | 
|  | 91 | +    } | 
| 92 | 92 | } | 
0 commit comments