Skip to content

Commit a2bf09f

Browse files
committed
make rustc_public a crates.io crate
1 parent 3599f8e commit a2bf09f

File tree

15 files changed

+1408
-0
lines changed

15 files changed

+1408
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ resolver = "2"
44
members = [
55
"tools/compiletest",
66
"tools/test-drive",
7+
"rustc_public",
78
]
89

910
exclude = [

rustc_public/Cargo.toml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[package]
2+
name = "rustc_public"
3+
version = "0.1.0-preview"
4+
authors = ["rustc_public team"]
5+
description = "Define compiler intermediate representation usable by external tools"
6+
license = "MIT OR Apache-2.0"
7+
repository = "https://github.com/rust-lang/project-stable-mir"
8+
edition = "2024"
9+
10+
[lib]
11+
path = "src/lib.rs"
12+
13+
[dependencies]
14+
scoped-tls = "1.0"
15+
serde = { version = "1.0.125", features = [ "derive" ] }
16+
tracing = "0.1"
17+
18+
[build-dependencies]
19+
rustversion = "1"
20+
21+
[dev-dependencies]
22+
regex = "1.5.5"
23+
ui_test = "0.30.2"
24+
25+
[[test]]
26+
name = "compiletest"
27+
harness = false
28+
29+
[features]
30+
# Provides access to APIs that expose internals of the rust compiler.
31+
# APIs enabled by this feature are unstable. They can be removed or modified
32+
# at any point and they are not included in the crate's semantic versioning.
33+
rustc_internal = []
34+
35+
[package.metadata.rust-analyzer]
36+
# This crate uses #[feature(rustc_private)].
37+
# See https://github.com/rust-analyzer/rust-analyzer/pull/7891
38+
rustc_private = true

rustc_public/build.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use std::process::{self, Command};
2+
use std::{env, str};
3+
4+
use rustversion;
5+
6+
const MSRV: &str = "2025-07-24";
7+
const SUPPORTED: bool = rustversion::cfg!(since(2025-07-24));
8+
9+
fn main() {
10+
if !SUPPORTED {
11+
let current = rustc_version().unwrap_or(String::from("unknown"));
12+
eprintln!(
13+
"\nERROR: rustc_public requires rustc nightly-{MSRV} or newer\n\
14+
current: {current}\n\
15+
help: run `rustup update nightly`.\n"
16+
);
17+
process::exit(1);
18+
}
19+
println!("cargo:rerun-if-changed=build.rs");
20+
}
21+
22+
fn rustc_version() -> Option<String> {
23+
let rustc = env::var_os("RUSTC").unwrap_or_else(|| {
24+
eprintln!("RUSTC is not set during build script execution.\n");
25+
process::exit(1);
26+
});
27+
let output = Command::new(rustc).arg("--version").output().ok()?;
28+
let version = str::from_utf8(&output.stdout).ok()?;
29+
version.parse().ok()
30+
}

rustc_public/src/lib.rs

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
//! The WIP public interface to rustc internals.
2+
//!
3+
//! For more information see <https://github.com/rust-lang/project-stable-mir>
4+
//!
5+
//! # Note
6+
//!
7+
//! This API is still completely unstable and subject to change.
8+
9+
#![feature(rustc_private)]
10+
#![allow(rustc::usage_of_ty_tykind)]
11+
#![doc(
12+
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
13+
test(attr(allow(unused_variables), deny(warnings)))
14+
)]
15+
#![feature(sized_hierarchy)]
16+
//!
17+
//! This crate shall contain all type definitions and APIs that we expect third-party tools to invoke to
18+
//! interact with the compiler.
19+
//!
20+
//! The goal is to eventually be published on
21+
//! [crates.io](https://crates.io).
22+
23+
extern crate rustc_abi;
24+
extern crate rustc_driver;
25+
extern crate rustc_hir;
26+
extern crate rustc_middle;
27+
extern crate rustc_public_bridge;
28+
extern crate rustc_session;
29+
extern crate rustc_span;
30+
extern crate rustc_target;
31+
32+
use std::fmt::Debug;
33+
use std::{fmt, io};
34+
35+
pub(crate) use rustc_public_bridge::IndexedVal;
36+
use rustc_public_bridge::Tables;
37+
use rustc_public_bridge::context::CompilerCtxt;
38+
/// Export the rustc_internal APIs. Note that this module has no stability
39+
/// guarantees and it is not taken into account for semver.
40+
#[cfg(feature = "rustc_internal")]
41+
pub mod rustc_internal;
42+
use serde::Serialize;
43+
44+
use crate::compiler_interface::with;
45+
pub use crate::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId};
46+
pub use crate::error::*;
47+
use crate::mir::mono::StaticDef;
48+
use crate::mir::{Body, Mutability};
49+
use crate::ty::{AssocItem, FnDef, ForeignModuleDef, ImplDef, ProvenanceMap, Span, TraitDef, Ty};
50+
use crate::unstable::Stable;
51+
52+
pub mod abi;
53+
mod alloc;
54+
pub(crate) mod unstable;
55+
#[macro_use]
56+
pub mod crate_def;
57+
pub mod compiler_interface;
58+
#[macro_use]
59+
pub mod error;
60+
pub mod mir;
61+
pub mod target;
62+
pub mod ty;
63+
pub mod visitor;
64+
65+
/// Use String for now but we should replace it.
66+
pub type Symbol = String;
67+
68+
/// The number that identifies a crate.
69+
pub type CrateNum = usize;
70+
71+
impl Debug for DefId {
72+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73+
f.debug_struct("DefId").field("id", &self.0).field("name", &self.name()).finish()
74+
}
75+
}
76+
77+
impl IndexedVal for DefId {
78+
fn to_val(index: usize) -> Self {
79+
DefId(index)
80+
}
81+
82+
fn to_index(&self) -> usize {
83+
self.0
84+
}
85+
}
86+
87+
/// A list of crate items.
88+
pub type CrateItems = Vec<CrateItem>;
89+
90+
/// A list of trait decls.
91+
pub type TraitDecls = Vec<TraitDef>;
92+
93+
/// A list of impl trait decls.
94+
pub type ImplTraitDecls = Vec<ImplDef>;
95+
96+
/// A list of associated items.
97+
pub type AssocItems = Vec<AssocItem>;
98+
99+
/// Holds information about a crate.
100+
#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
101+
pub struct Crate {
102+
pub id: CrateNum,
103+
pub name: Symbol,
104+
pub is_local: bool,
105+
}
106+
107+
impl Crate {
108+
/// The list of foreign modules in this crate.
109+
pub fn foreign_modules(&self) -> Vec<ForeignModuleDef> {
110+
with(|cx| cx.foreign_modules(self.id))
111+
}
112+
113+
/// The list of traits declared in this crate.
114+
pub fn trait_decls(&self) -> TraitDecls {
115+
with(|cx| cx.trait_decls(self.id))
116+
}
117+
118+
/// The list of trait implementations in this crate.
119+
pub fn trait_impls(&self) -> ImplTraitDecls {
120+
with(|cx| cx.trait_impls(self.id))
121+
}
122+
123+
/// Return a list of function definitions from this crate independent on their visibility.
124+
pub fn fn_defs(&self) -> Vec<FnDef> {
125+
with(|cx| cx.crate_functions(self.id))
126+
}
127+
128+
/// Return a list of static items defined in this crate independent on their visibility.
129+
pub fn statics(&self) -> Vec<StaticDef> {
130+
with(|cx| cx.crate_statics(self.id))
131+
}
132+
}
133+
134+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)]
135+
pub enum ItemKind {
136+
Fn,
137+
Static,
138+
Const,
139+
Ctor(CtorKind),
140+
}
141+
142+
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize)]
143+
pub enum CtorKind {
144+
Const,
145+
Fn,
146+
}
147+
148+
pub type Filename = String;
149+
150+
crate_def_with_ty! {
151+
/// Holds information about an item in a crate.
152+
#[derive(Serialize)]
153+
pub CrateItem;
154+
}
155+
156+
impl CrateItem {
157+
/// This will return the body of an item or panic if it's not available.
158+
pub fn expect_body(&self) -> mir::Body {
159+
with(|cx| cx.mir_body(self.0))
160+
}
161+
162+
/// Return the body of an item if available.
163+
pub fn body(&self) -> Option<mir::Body> {
164+
with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0)))
165+
}
166+
167+
/// Check if a body is available for this item.
168+
pub fn has_body(&self) -> bool {
169+
with(|cx| cx.has_body(self.0))
170+
}
171+
172+
pub fn span(&self) -> Span {
173+
with(|cx| cx.span_of_an_item(self.0))
174+
}
175+
176+
pub fn kind(&self) -> ItemKind {
177+
with(|cx| cx.item_kind(*self))
178+
}
179+
180+
pub fn requires_monomorphization(&self) -> bool {
181+
with(|cx| cx.requires_monomorphization(self.0))
182+
}
183+
184+
pub fn ty(&self) -> Ty {
185+
with(|cx| cx.def_ty(self.0))
186+
}
187+
188+
pub fn is_foreign_item(&self) -> bool {
189+
with(|cx| cx.is_foreign_item(self.0))
190+
}
191+
192+
/// Emit MIR for this item body.
193+
pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
194+
self.body()
195+
.ok_or_else(|| io::Error::other(format!("No body found for `{}`", self.name())))?
196+
.dump(w, &self.name())
197+
}
198+
}
199+
200+
/// Return the function where execution starts if the current
201+
/// crate defines that. This is usually `main`, but could be
202+
/// `start` if the crate is a no-std crate.
203+
pub fn entry_fn() -> Option<CrateItem> {
204+
with(|cx| cx.entry_fn())
205+
}
206+
207+
/// Access to the local crate.
208+
pub fn local_crate() -> Crate {
209+
with(|cx| cx.local_crate())
210+
}
211+
212+
/// Try to find a crate or crates if multiple crates exist from given name.
213+
pub fn find_crates(name: &str) -> Vec<Crate> {
214+
with(|cx| cx.find_crates(name))
215+
}
216+
217+
/// Try to find a crate with the given name.
218+
pub fn external_crates() -> Vec<Crate> {
219+
with(|cx| cx.external_crates())
220+
}
221+
222+
/// Retrieve all items in the local crate that have a MIR associated with them.
223+
pub fn all_local_items() -> CrateItems {
224+
with(|cx| cx.all_local_items())
225+
}
226+
227+
pub fn all_trait_decls() -> TraitDecls {
228+
with(|cx| cx.all_trait_decls())
229+
}
230+
231+
pub fn all_trait_impls() -> ImplTraitDecls {
232+
with(|cx| cx.all_trait_impls())
233+
}
234+
235+
/// A type that provides internal information but that can still be used for debug purpose.
236+
#[derive(Clone, PartialEq, Eq, Hash, Serialize)]
237+
pub struct Opaque(String);
238+
239+
impl std::fmt::Display for Opaque {
240+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241+
write!(f, "{}", self.0)
242+
}
243+
}
244+
245+
impl std::fmt::Debug for Opaque {
246+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247+
write!(f, "{}", self.0)
248+
}
249+
}
250+
251+
pub fn opaque<T: Debug>(value: &T) -> Opaque {
252+
Opaque(format!("{value:?}"))
253+
}
254+
255+
macro_rules! bridge_impl {
256+
($name: ident, $ty: ty) => {
257+
impl rustc_public_bridge::bridge::$name<compiler_interface::BridgeTys> for $ty {
258+
fn new(def: crate::DefId) -> Self {
259+
Self(def)
260+
}
261+
}
262+
};
263+
}
264+
265+
bridge_impl!(CrateItem, crate::CrateItem);
266+
bridge_impl!(AdtDef, crate::ty::AdtDef);
267+
bridge_impl!(ForeignModuleDef, crate::ty::ForeignModuleDef);
268+
bridge_impl!(ForeignDef, crate::ty::ForeignDef);
269+
bridge_impl!(FnDef, crate::ty::FnDef);
270+
bridge_impl!(ClosureDef, crate::ty::ClosureDef);
271+
bridge_impl!(CoroutineDef, crate::ty::CoroutineDef);
272+
bridge_impl!(CoroutineClosureDef, crate::ty::CoroutineClosureDef);
273+
bridge_impl!(AliasDef, crate::ty::AliasDef);
274+
bridge_impl!(ParamDef, crate::ty::ParamDef);
275+
bridge_impl!(BrNamedDef, crate::ty::BrNamedDef);
276+
bridge_impl!(TraitDef, crate::ty::TraitDef);
277+
bridge_impl!(GenericDef, crate::ty::GenericDef);
278+
bridge_impl!(ConstDef, crate::ty::ConstDef);
279+
bridge_impl!(ImplDef, crate::ty::ImplDef);
280+
bridge_impl!(RegionDef, crate::ty::RegionDef);
281+
bridge_impl!(CoroutineWitnessDef, crate::ty::CoroutineWitnessDef);
282+
bridge_impl!(AssocDef, crate::ty::AssocDef);
283+
bridge_impl!(OpaqueDef, crate::ty::OpaqueDef);
284+
bridge_impl!(StaticDef, crate::mir::mono::StaticDef);
285+
286+
impl rustc_public_bridge::bridge::Prov<compiler_interface::BridgeTys> for crate::ty::Prov {
287+
fn new(aid: crate::mir::alloc::AllocId) -> Self {
288+
Self(aid)
289+
}
290+
}
291+
292+
impl rustc_public_bridge::bridge::Allocation<compiler_interface::BridgeTys>
293+
for crate::ty::Allocation
294+
{
295+
fn new<'tcx>(
296+
bytes: Vec<Option<u8>>,
297+
ptrs: Vec<(usize, rustc_middle::mir::interpret::AllocId)>,
298+
align: u64,
299+
mutability: rustc_middle::mir::Mutability,
300+
tables: &mut Tables<'tcx, compiler_interface::BridgeTys>,
301+
cx: &CompilerCtxt<'tcx, compiler_interface::BridgeTys>,
302+
) -> Self {
303+
Self {
304+
bytes,
305+
provenance: ProvenanceMap {
306+
ptrs: ptrs.iter().map(|(i, aid)| (*i, tables.prov(*aid))).collect(),
307+
},
308+
align,
309+
mutability: mutability.stable(tables, cx),
310+
}
311+
}
312+
}

0 commit comments

Comments
 (0)