rust/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
Florian Brucker dce265224a Fix examples to work with nightly-2025-02-13
While there were comments indicating which nightly versions the examples
were tested with, those versions did not work for me: neither did the
examples compile, nor did they produce the expected output.

This commit fixes the compilation issues, using nightly-2025-02-13 for
all examples (previously the version differed between the examples) and,
in the case of the `rustc_driver` examples, also fixes the argument
passing: rustc ignores the first argument, so we need to pass the
filename as the second (otherwise we only get the help text printed).

Note that the `rustc-interface-getting-diagnostics.rs` example still
does not produce any output, which I assume is not how it is intended.
However, I don't know enough to fix it.

To avoid inconsistencies between the documented version and the actually
required version I've moved the version comment from the Markdown into
the Rust code where it hopefully won't be forgotten as easily.

Finally I've clarified in the examples' README that you also need to use
the proper nightly version when compiling the examples, not just when
running them.
2025-02-15 19:44:32 +01:00

101 lines
2.6 KiB
Rust

// Tested with nightly-2025-02-13
#![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#"
fn main() {
let message = "Hello, World!";
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().items() {
let hir = tcx.hir();
let item = hir.item(id);
match item.kind {
rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn { .. } => {
let name = item.ident;
let ty = tcx.type_of(item.hir_id().owner.def_id);
println!("{name:?}:\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,
);
}