Skip to content

Commit e74b303

Browse files
Example of rustc interface (#621)
* Example of rustc interface (https://internals.rust-lang.org/t/using-the-rustc-interface-crate/11982)
1 parent 1ed6139 commit e74b303

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

examples/rustc-driver-example.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#![feature(rustc_private)]
2+
3+
extern crate rustc;
4+
extern crate rustc_error_codes;
5+
extern crate rustc_errors;
6+
extern crate rustc_hash;
7+
extern crate rustc_hir;
8+
extern crate rustc_interface;
9+
extern crate rustc_span;
10+
11+
use rustc::session;
12+
use rustc::session::config;
13+
use rustc_errors::registry;
14+
use rustc_hash::{FxHashMap, FxHashSet};
15+
use rustc_interface::interface;
16+
use rustc_span::source_map;
17+
use std::path;
18+
use std::process;
19+
use std::str;
20+
21+
fn main() {
22+
let out = process::Command::new("rustc")
23+
.arg("--print=sysroot")
24+
.current_dir(".")
25+
.output()
26+
.unwrap();
27+
let sysroot = str::from_utf8(&out.stdout).unwrap().trim();
28+
let filename = "main.rs";
29+
let contents = "static HELLO: &str = \"Hello, world!\"; fn main() { println!(\"{}\", HELLO); }";
30+
let errors = registry::Registry::new(&rustc_error_codes::DIAGNOSTICS);
31+
let config = interface::Config {
32+
// Command line options
33+
opts: config::Options {
34+
maybe_sysroot: Some(path::PathBuf::from(sysroot)),
35+
..config::Options::default()
36+
},
37+
38+
// cfg! configuration in addition to the default ones
39+
// FxHashSet<(String, Option<String>)>
40+
crate_cfg: FxHashSet::default(),
41+
42+
input: config::Input::Str {
43+
name: source_map::FileName::Custom(String::from(filename)),
44+
input: String::from(contents),
45+
},
46+
// Option<PathBuf>
47+
input_path: None,
48+
// Option<PathBuf>
49+
output_dir: None,
50+
// Option<PathBuf>
51+
output_file: None,
52+
// Option<Box<dyn FileLoader + Send + Sync>>
53+
file_loader: None,
54+
diagnostic_output: session::DiagnosticOutput::Default,
55+
56+
// Set to capture stderr output during compiler execution
57+
// Option<Arc<Mutex<Vec<u8>>>>
58+
stderr: None,
59+
60+
// Option<String>
61+
crate_name: None,
62+
// FxHashMap<lint::LintId, lint::Level>
63+
lint_caps: FxHashMap::default(),
64+
65+
// This is a callback from the driver that is called when we're registering lints;
66+
// it is called during plugin registration when we have the LintStore in a non-shared state.
67+
//
68+
// Note that if you find a Some here you probably want to call that function in the new
69+
// function being registered.
70+
// Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>
71+
register_lints: None,
72+
73+
// This is a callback from the driver that is called just after we have populated
74+
// the list of queries.
75+
//
76+
// The second parameter is local providers and the third parameter is external providers.
77+
// Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)>
78+
override_queries: None,
79+
80+
// Registry of diagnostics codes.
81+
registry: errors,
82+
};
83+
interface::run_compiler(config, |compiler| {
84+
compiler.enter(|queries| {
85+
// Parse the program and print the syntax tree.
86+
let parse = queries.parse().unwrap().take();
87+
println!("{:#?}", parse);
88+
// Analyze the program and inspect the types of definitions.
89+
queries.global_ctxt().unwrap().take().enter(|tcx| {
90+
for (_, item) in &tcx.hir().krate().items {
91+
match item.kind {
92+
rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => {
93+
let name = item.ident;
94+
let ty = tcx.type_of(tcx.hir().local_def_id(item.hir_id));
95+
println!("{:?}:\t{:?}", name, ty)
96+
}
97+
_ => (),
98+
}
99+
}
100+
})
101+
});
102+
});
103+
}

0 commit comments

Comments
 (0)