Skip to content

Document how to get the type of an expression using rustc_interface #639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
- [High-level overview of the compiler source](./high-level-overview.md)
- [The Rustc Driver and Interface](./rustc-driver.md)
- [Rustdoc](./rustdoc.md)
- [Ex: Type checking through `rustc_interface`](./rustc-driver-interacting-with-the-ast.md)
- [Queries: demand-driven compilation](./query.md)
- [The Query Evaluation Model in Detail](./queries/query-evaluation-model-in-detail.md)
- [Incremental compilation](./queries/incremental-compilation.md)
Expand Down
41 changes: 41 additions & 0 deletions src/rustc-driver-interacting-with-the-ast.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Example: Type checking through `rustc_interface`

`rustc_interface` allows you to interact with Rust code at various stages of compilation.

## Getting the type of an expression

To get the type of an expression, use the `global_ctxt` to get a `TyCtxt`:

```rust
// In this example, config specifies the rust program:
// fn main() { let message = \"Hello, world!\"; println!(\"{}\", message); }
// Our goal is to get the type of the string literal "Hello, world!".
//
// See https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-example.rs for a complete example of configuring rustc_interface
rustc_interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
// Analyze the crate and inspect the types under the cursor.
queries.global_ctxt().unwrap().take().enter(|tcx| {
// Every compilation contains a single crate.
let krate = tcx.hir().krate();
// Iterate over the top-level items in the crate, looking for the main function.
for (_, item) in &krate.items {
// Use pattern-matching to find a specific node inside the main function.
if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind {
let expr = &tcx.hir().body(body_id).value;
if let rustc_hir::ExprKind::Block(block, _) = expr.kind {
if let rustc_hir::StmtKind::Local(local) = block.stmts[0].kind {
if let Some(expr) = local.init {
let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!"
let def_id = tcx.hir().local_def_id(item.hir_id); // def_id identifies the main function
let ty = tcx.typeck_tables_of(def_id).node_type(hir_id);
println!("{:?}: {:?}", expr, ty); // prints expr(HirId { owner: DefIndex(3), local_id: 4 }: "Hello, world!"): &'static str
}
}
}
}
}
})
});
});
```