Skip to content
Closed
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
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
## Installation

The Rust compiler's interface is not stable, so the only sensible way to develop a Rust compiler plugin is by pinning to a specific nightly. Each version of `rustc_plugin` is pinned to one nightly, and you *have* to use the same nightly version that we do. Therefore each release of `rustc_plugin` has a semantic version number (e.g. `0.1.0`) and the nightly version is added as a prerelease label (e.g. `-nightly-2023-08-25`). You can add a dependency to your `Cargo.toml` like this:

```toml
rustc_plugin = "=0.12.0-nightly-2024-12-15"
rustc_plugin = "=0.13.0-nightly-2025-02-04"
```

We will treat a change to the nightly version as a breaking change, so the semantic version will be correspondingly updated as a breaking update.
Expand All @@ -28,7 +28,7 @@ We will treat a change to the nightly version as a breaking change, so the seman
* [`Cargo.toml`](https://github.com/cognitive-engineering-lab/rustc_plugin/blob/main/crates/rustc_plugin/examples/print-all-items/Cargo.toml): normal Cargo manifest. Make sure to specify `rustc_private = true` to get Rust Analyzer support for the rustc API.
* [`src/`](https://github.com/cognitive-engineering-lab/rustc_plugin/tree/main/crates/rustc_plugin/examples/print-all-items/src)
* [`bin/`](https://github.com/cognitive-engineering-lab/rustc_plugin/tree/main/crates/rustc_plugin/examples/print-all-items/src/bin)
* [`cargo-print-all-items.rs`](https://github.com/cognitive-engineering-lab/rustc_plugin/blob/main/crates/rustc_plugin/examples/print-all-items/src/bin/cargo-print-all-items.rs): the CLI binary run directly by the user, e.g. by invoking `cargo print-all-items`.
* [`cargo-print-all-items.rs`](https://github.com/cognitive-engineering-lab/rustc_plugin/blob/main/crates/rustc_plugin/examples/print-all-items/src/bin/cargo-print-all-items.rs): the CLI binary run directly by the user, e.g. by invoking `cargo print-all-items`.
* [`print-all-items-driver.rs`](https://github.com/cognitive-engineering-lab/rustc_plugin/blob/main/crates/rustc_plugin/examples/print-all-items/src/bin/print-all-items-driver.rs): the implementation binary used by the CLI.
* [`lib.rs`](https://github.com/cognitive-engineering-lab/rustc_plugin/blob/main/crates/rustc_plugin/examples/print-all-items/src/lib.rs): Your plugin implementation, which exports a data structure that implements the `RustcPlugin` trait.

Expand All @@ -44,6 +44,7 @@ The `rustc_plugin` framework is responsible for marshalling arguments from the t

Normally, Rust libraries have a [minimum supported Rust version][msrv] because they promise to not use any breaking features implemented after that version. Rust compiler plugins are the opposite — they have a **maximum** supported Rust version (MaxSRV). A compiler plugin cannot analyze programs that use features implemented after the release date of the plugin's toolchain. The MaxSRV for every version of `rustc_plugin` is listed below:

* v0.13 (`nightly-2025-02-04`) - rustc 1.86
* v0.12 (`nightly-2024-12-15`) - rustc 1.84
* v0.11 (`nightly-2024-12-01`) - rustc 1.84
* v0.10 (`nightly-2024-05-20`) - rustc 1.79
Expand All @@ -59,6 +60,6 @@ Normally, Rust libraries have a [minimum supported Rust version][msrv] because t
[Argus]: https://github.com/cognitive-engineering-lab/argus
[Clippy]: https://github.com/rust-lang/rust-clippy
[example]: https://github.com/cognitive-engineering-lab/rustc_plugin/tree/main/crates/rustc_plugin/examples/print-all-items
[docs]: https://cognitive-engineering-lab.github.io/rustc_plugin/v0.12.0-nightly-2024-12-15/rustc_plugin/
[docs-utils]: https://cognitive-engineering-lab.github.io/rustc_plugin/v0.12.0-nightly-2024-12-15/rustc_utils/
[docs]: https://cognitive-engineering-lab.github.io/rustc_plugin/v0.13.0-nightly-2025-02-04/rustc_plugin/
[docs-utils]: https://cognitive-engineering-lab.github.io/rustc_plugin/v0.13.0-nightly-2025-02-04/rustc_utils/
[msrv]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field
5 changes: 3 additions & 2 deletions crates/rustc_plugin/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rustc_plugin"
version = "0.12.0-nightly-2024-12-15"
version = "0.13.0-nightly-2025-02-04"
edition = "2021"
authors = ["Will Crichton <[email protected]>"]
description = "A framework for writing plugins that integrate with the Rust compiler"
Expand All @@ -18,7 +18,8 @@ serde = "1"
serde_json = "1"

[dev-dependencies]
anyhow = {version = "1", features = ["backtrace"]}
anyhow = { version = "1", features = ["backtrace"] }
serial_test = "3.2"

[build-dependencies]
toml = "0.7"
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2024-12-15"
channel = "nightly-2025-02-04"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
3 changes: 1 addition & 2 deletions crates/rustc_plugin/examples/print-all-items/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ impl RustcPlugin for PrintAllItemsPlugin {
plugin_args: Self::Args,
) -> rustc_interface::interface::Result<()> {
let mut callbacks = PrintAllItemsCallbacks { args: plugin_args };
let compiler = rustc_driver::RunCompiler::new(&compiler_args, &mut callbacks);
compiler.run();
rustc_driver::run_compiler(&compiler_args, &mut callbacks);
Ok(())
}
}
Expand Down
5 changes: 2 additions & 3 deletions crates/rustc_plugin/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub fn driver_main<T: RustcPlugin>(plugin: T) {
log::debug!("Running plugin...");
let plugin_args: T::Args =
serde_json::from_str(&env::var(PLUGIN_ARGS).unwrap()).unwrap();
plugin.run(args, plugin_args)
plugin.run(args, plugin_args).expect("plugin failure");
} else {
log::debug!(
"Running normal Rust. Relevant variables:\
Expand All @@ -161,8 +161,7 @@ run_on_all_crates={run_on_all_crates}, \
primary_package={primary_package}, \
is_target_crate={is_target_crate}"
);
rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
Ok(())
rustc_driver::run_compiler(&args, &mut DefaultCallbacks);
}
}))
}
5 changes: 5 additions & 0 deletions crates/rustc_plugin/tests/test_example.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{env, fs, path::Path, process::Command, sync::Once};

use anyhow::{ensure, Context, Result};
use serial_test::serial;

static SETUP: Once = Once::new();

Expand Down Expand Up @@ -57,13 +58,15 @@ fn run(dir: &str, f: impl FnOnce(&mut Command)) -> Result<String> {
// TODO: why do these tests need to be run sequentially?

#[test]
#[serial]
fn basic() -> Result<()> {
let output = run("workspaces/basic", |_cmd| {})?;
assert!(output.contains(r#"There is an item "add" of type "function""#));
Ok(())
}

#[test]
#[serial]
fn arg() -> Result<()> {
let output = run("workspaces/basic", |cmd| {
cmd.arg("-a");
Expand All @@ -73,6 +76,7 @@ fn arg() -> Result<()> {
}

#[test]
#[serial]
fn feature() -> Result<()> {
let output = run("workspaces/basic", |cmd| {
cmd.args(["--", "--features", "sub"]);
Expand All @@ -85,6 +89,7 @@ fn feature() -> Result<()> {
}

#[test]
#[serial]
fn multi() -> Result<()> {
run("workspaces/multi", |_cmd| {})?;
Ok(())
Expand Down
18 changes: 10 additions & 8 deletions crates/rustc_utils/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rustc_utils"
version = "0.12.0-nightly-2024-12-15"
version = "0.13.0-nightly-2025-02-04"
edition = "2021"
authors = ["Will Crichton <[email protected]>"]
description = "Utilities for working with the Rust compiler"
Expand All @@ -23,13 +23,15 @@ anyhow = "1"
log = "0.4"
intervaltree = "0.2"
cfg-if = "1"
serde = {version = "1", features = ["derive"], optional = true}
textwrap = {version = "0.16", optional = true}
regex = {version = "1", optional = true}
ts-rs = {version = "7", optional = true}
indexical = {version = "0.3.1", default-features = false, features = ["rustc"], optional = true}
serde = { version = "1", features = ["derive"], optional = true }
textwrap = { version = "0.16", optional = true }
regex = { version = "1", optional = true }
ts-rs = { version = "7", optional = true }
indexical = { version = "0.3.1", default-features = false, features = [
"rustc",
], optional = true }

[dev-dependencies]
rustc_utils = {path = ".", features = ["test"]}
rustc_utils = { path = ".", features = ["test"] }
test-log = "0.2"
env_logger = {version = "0.9", default-features = false}
env_logger = { version = "0.9", default-features = false }
8 changes: 4 additions & 4 deletions crates/rustc_utils/src/mir/control_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ use rustc_data_structures::graph::{
DirectedGraph, Predecessors, StartNode, Successors,
};
use rustc_index::{
bit_set::{BitSet, SparseBitMatrix},
bit_set::{DenseBitSet, SparseBitMatrix},
Idx,
};
use smallvec::SmallVec;

struct ReversedGraph<'a, G: ControlFlowGraph> {
graph: &'a G,
exit: G::Node,
unreachable: BitSet<G::Node>,
unreachable: DenseBitSet<G::Node>,
}

impl<G: ControlFlowGraph> DirectedGraph for ReversedGraph<'_, G> {
Expand Down Expand Up @@ -76,7 +76,7 @@ impl<Node: Idx> PostDominators<Node> {
let mut reversed = ReversedGraph {
graph,
exit,
unreachable: BitSet::new_empty(num_nodes),
unreachable: DenseBitSet::new_empty(num_nodes),
};

let reachable = iterate::post_order_from(&reversed, exit);
Expand Down Expand Up @@ -194,7 +194,7 @@ impl<Node: Idx + Ord> ControlDependencies<Node> {
}

/// Returns the set of all node that are control-dependent on the given `node`.
pub fn dependent_on(&self, node: Node) -> Option<&BitSet<Node>> {
pub fn dependent_on(&self, node: Node) -> Option<&DenseBitSet<Node>> {
self.0.row(node)
}
}
Expand Down
17 changes: 11 additions & 6 deletions crates/rustc_utils/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ impl CompileBuilder {
pub fn compile(&self, f: impl for<'tcx> FnOnce(CompileResult<'tcx>) + Send) {
let mut callbacks = TestCallbacks {
callback: Some(move |tcx: TyCtxt<'_>| f(CompileResult { tcx })),
file_loader: Some(StringLoader(self.input.clone())),
};
let args = [
"rustc",
Expand All @@ -116,9 +117,7 @@ impl CompileBuilder {
.collect::<Box<_>>();

rustc_driver::catch_fatal_errors(|| {
let mut compiler = rustc_driver::RunCompiler::new(&args, &mut callbacks);
compiler.set_file_loader(Some(Box::new(StringLoader(self.input.clone()))));
compiler.run();
rustc_driver::run_compiler(&args, &mut callbacks);
})
.unwrap();
}
Expand Down Expand Up @@ -152,7 +151,7 @@ impl<'tcx> CompileResult<'tcx> {
let body_id = hir
.items()
.find_map(|id| match hir.item(id).kind {
ItemKind::Fn(_, _, body) => Some(body),
ItemKind::Fn { body, .. } => Some(body),
_ => None,
})
.unwrap();
Expand Down Expand Up @@ -180,16 +179,22 @@ impl<'tcx> CompileResult<'tcx> {
}
}

struct TestCallbacks<Cb> {
struct TestCallbacks<Cb, Fl> {
callback: Option<Cb>,
file_loader: Option<Fl>,
}

impl<Cb> rustc_driver::Callbacks for TestCallbacks<Cb>
impl<Cb, Fl> rustc_driver::Callbacks for TestCallbacks<Cb, Fl>
where
Cb: FnOnce(TyCtxt<'_>),
Fl: FileLoader + Send + Sync + 'static,
{
fn config(&mut self, config: &mut rustc_interface::Config) {
config.override_queries = Some(borrowck_facts::override_queries);
config.file_loader = self
.file_loader
.take()
.map(|fl| Box::new(fl) as Box<(dyn FileLoader + Send + Sync)>);
}

fn after_analysis(
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2024-12-15"
channel = "nightly-2025-02-04"
components = ["clippy", "rust-src", "rustc-dev", "llvm-tools-preview"]
Loading