]>
Commit | Line | Data |
---|---|---|
6a06907d XL |
1 | #![feature(rustc_private)] |
2 | ||
3 | // NOTE: For the example to compile, you will need to first run the following: | |
4 | // rustup component add rustc-dev llvm-tools-preview | |
5 | ||
6 | extern crate rustc_ast_pretty; | |
7 | extern crate rustc_error_codes; | |
8 | extern crate rustc_errors; | |
9 | extern crate rustc_hash; | |
10 | extern crate rustc_hir; | |
11 | extern crate rustc_interface; | |
12 | extern crate rustc_session; | |
13 | extern crate rustc_span; | |
14 | ||
15 | use rustc_ast_pretty::pprust::item_to_string; | |
16 | use rustc_errors::registry; | |
17 | use rustc_session::config; | |
18 | use rustc_session::config::PpMode::PpmSource; | |
19 | use rustc_session::config::PpSourceMode::PpmExpanded; | |
20 | use rustc_span::source_map; | |
21 | use std::path; | |
22 | use std::process; | |
23 | use std::str; | |
24 | ||
25 | fn main() { | |
26 | let out = process::Command::new("rustc") | |
27 | .arg("--print=sysroot") | |
28 | .current_dir(".") | |
29 | .output() | |
30 | .unwrap(); | |
31 | let sysroot = str::from_utf8(&out.stdout).unwrap().trim(); | |
32 | let config = rustc_interface::Config { | |
33 | opts: config::Options { | |
34 | maybe_sysroot: Some(path::PathBuf::from(sysroot)), | |
35 | ..config::Options::default() | |
36 | }, | |
37 | input: config::Input::Str { | |
38 | name: source_map::FileName::Custom("main.rs".to_string()), | |
39 | input: "fn main() { let message = \"Hello, world!\"; println!(\"{}\", message); }" | |
40 | .to_string(), | |
41 | }, | |
42 | diagnostic_output: rustc_session::DiagnosticOutput::Default, | |
43 | crate_cfg: rustc_hash::FxHashSet::default(), | |
44 | input_path: None, | |
45 | output_dir: None, | |
46 | output_file: None, | |
47 | file_loader: None, | |
48 | stderr: None, | |
49 | crate_name: None, | |
50 | lint_caps: rustc_hash::FxHashMap::default(), | |
51 | register_lints: None, | |
52 | override_queries: None, | |
53 | make_codegen_backend: None, | |
54 | registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS), | |
55 | }; | |
56 | rustc_interface::run_compiler(config, |compiler| { | |
57 | compiler.enter(|queries| { | |
58 | // TODO: add this to -Z unpretty | |
59 | let ast_krate = queries.parse().unwrap().take(); | |
60 | let ast_krate_mod = ast_krate.module; | |
61 | for item in ast_krate_mod.items { | |
62 | println!("{}", item_to_string(&item)); | |
63 | } | |
64 | ||
65 | // Analyze the crate and inspect the types under the cursor. | |
66 | queries.global_ctxt().unwrap().take().enter(|tcx| { | |
67 | // Every compilation contains a single crate. | |
68 | let hir_krate = tcx.hir().krate(); | |
69 | // Iterate over the top-level items in the crate, looking for the main function. | |
70 | for (_, item) in &hir_krate.items { | |
71 | // Use pattern-matching to find a specific node inside the main function. | |
72 | if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind { | |
73 | let expr = &tcx.hir().body(body_id).value; | |
74 | if let rustc_hir::ExprKind::Block(block, _) = expr.kind { | |
75 | if let rustc_hir::StmtKind::Local(local) = block.stmts[0].kind { | |
76 | if let Some(expr) = local.init { | |
77 | let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!" | |
78 | let def_id = tcx.hir().local_def_id(item.hir_id); // def_id identifies the main function | |
79 | let ty = tcx.typeck(def_id).node_type(hir_id); | |
80 | println!("{:?}: {:?}", expr, ty); // prints expr(HirId { owner: DefIndex(3), local_id: 4 }: "Hello, world!"): &'static str | |
81 | } | |
82 | } | |
83 | } | |
84 | } | |
85 | } | |
86 | }) | |
87 | }); | |
88 | }); | |
89 | } |