Skip to content

SMIR: Expose Tables to users #116999

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

Closed
wants to merge 4 commits into from
Closed
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
2 changes: 0 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -4482,9 +4482,7 @@ name = "rustc_smir"
version = "0.0.0"
dependencies = [
"rustc_data_structures",
"rustc_driver",
"rustc_hir",
"rustc_interface",
"rustc_middle",
"rustc_span",
"rustc_target",
2 changes: 0 additions & 2 deletions compiler/rustc_smir/Cargo.toml
Original file line number Diff line number Diff line change
@@ -5,9 +5,7 @@ edition = "2021"

[dependencies]
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_driver = { path = "../rustc_driver" }
rustc_hir = { path = "../rustc_hir" }
rustc_interface = { path = "../rustc_interface" }
rustc_middle = { path = "../rustc_middle" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
3 changes: 1 addition & 2 deletions compiler/rustc_smir/src/lib.rs
Original file line number Diff line number Diff line change
@@ -16,5 +16,4 @@

pub mod rustc_internal;

// Make this module private for now since external users should not call these directly.
mod rustc_smir;
pub mod rustc_smir;
235 changes: 114 additions & 121 deletions compiler/rustc_smir/src/rustc_internal/mod.rs
Original file line number Diff line number Diff line change
@@ -3,122 +3,100 @@
//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
//! until stable MIR is complete.

use crate::rustc_internal;
use crate::rustc_smir::Tables;
use rustc_data_structures::fx;
use rustc_data_structures::fx::FxIndexMap;
use rustc_driver::{Callbacks, Compilation, RunCompiler};
use rustc_interface::{interface, Queries};
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::Span;
use stable_mir::ty::IndexedVal;
use stable_mir::CompilerError;
use std::cell::RefCell;
use std::fmt::Debug;
use std::hash::Hash;
use std::ops::{ControlFlow, Index};

impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
type Output = DefId;

#[inline(always)]
fn index(&self, index: stable_mir::DefId) -> &Self::Output {
&self.def_ids[index]
}
}

impl<'tcx> Index<stable_mir::ty::Span> for Tables<'tcx> {
type Output = Span;

#[inline(always)]
fn index(&self, index: stable_mir::ty::Span) -> &Self::Output {
&self.spans[index]
}
}

impl<'tcx> Tables<'tcx> {
pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem {
pub fn crate_item(&self, did: DefId) -> stable_mir::CrateItem {
stable_mir::CrateItem(self.create_def_id(did))
}

pub fn adt_def(&mut self, did: DefId) -> stable_mir::ty::AdtDef {
pub fn adt_def(&self, did: DefId) -> stable_mir::ty::AdtDef {
stable_mir::ty::AdtDef(self.create_def_id(did))
}

pub fn foreign_def(&mut self, did: DefId) -> stable_mir::ty::ForeignDef {
pub fn foreign_def(&self, did: DefId) -> stable_mir::ty::ForeignDef {
stable_mir::ty::ForeignDef(self.create_def_id(did))
}

pub fn fn_def(&mut self, did: DefId) -> stable_mir::ty::FnDef {
pub fn fn_def(&self, did: DefId) -> stable_mir::ty::FnDef {
stable_mir::ty::FnDef(self.create_def_id(did))
}

pub fn closure_def(&mut self, did: DefId) -> stable_mir::ty::ClosureDef {
pub fn closure_def(&self, did: DefId) -> stable_mir::ty::ClosureDef {
stable_mir::ty::ClosureDef(self.create_def_id(did))
}

pub fn generator_def(&mut self, did: DefId) -> stable_mir::ty::GeneratorDef {
pub fn generator_def(&self, did: DefId) -> stable_mir::ty::GeneratorDef {
stable_mir::ty::GeneratorDef(self.create_def_id(did))
}

pub fn alias_def(&mut self, did: DefId) -> stable_mir::ty::AliasDef {
pub fn alias_def(&self, did: DefId) -> stable_mir::ty::AliasDef {
stable_mir::ty::AliasDef(self.create_def_id(did))
}

pub fn param_def(&mut self, did: DefId) -> stable_mir::ty::ParamDef {
pub fn param_def(&self, did: DefId) -> stable_mir::ty::ParamDef {
stable_mir::ty::ParamDef(self.create_def_id(did))
}

pub fn br_named_def(&mut self, did: DefId) -> stable_mir::ty::BrNamedDef {
pub fn br_named_def(&self, did: DefId) -> stable_mir::ty::BrNamedDef {
stable_mir::ty::BrNamedDef(self.create_def_id(did))
}

pub fn trait_def(&mut self, did: DefId) -> stable_mir::ty::TraitDef {
pub fn trait_def(&self, did: DefId) -> stable_mir::ty::TraitDef {
stable_mir::ty::TraitDef(self.create_def_id(did))
}

pub fn generic_def(&mut self, did: DefId) -> stable_mir::ty::GenericDef {
pub fn generic_def(&self, did: DefId) -> stable_mir::ty::GenericDef {
stable_mir::ty::GenericDef(self.create_def_id(did))
}

pub fn const_def(&mut self, did: DefId) -> stable_mir::ty::ConstDef {
pub fn const_def(&self, did: DefId) -> stable_mir::ty::ConstDef {
stable_mir::ty::ConstDef(self.create_def_id(did))
}

pub fn impl_def(&mut self, did: DefId) -> stable_mir::ty::ImplDef {
pub fn impl_def(&self, did: DefId) -> stable_mir::ty::ImplDef {
stable_mir::ty::ImplDef(self.create_def_id(did))
}

pub fn region_def(&mut self, did: DefId) -> stable_mir::ty::RegionDef {
pub fn region_def(&self, did: DefId) -> stable_mir::ty::RegionDef {
stable_mir::ty::RegionDef(self.create_def_id(did))
}

pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov {
pub fn prov(&self, aid: AllocId) -> stable_mir::ty::Prov {
stable_mir::ty::Prov(self.create_alloc_id(aid))
}

pub(crate) fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
pub(crate) fn create_def_id(&self, did: DefId) -> stable_mir::DefId {
self.def_ids.create_or_fetch(did)
}

fn create_alloc_id(&mut self, aid: AllocId) -> stable_mir::AllocId {
fn create_alloc_id(&self, aid: AllocId) -> stable_mir::AllocId {
self.alloc_ids.create_or_fetch(aid)
}

pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span {
pub(crate) fn create_span(&self, span: Span) -> stable_mir::ty::Span {
self.spans.create_or_fetch(span)
}

pub(crate) fn instance_def(
&mut self,
&self,
instance: ty::Instance<'tcx>,
) -> stable_mir::mir::mono::InstanceDef {
self.instances.create_or_fetch(instance)
}

pub(crate) fn static_def(&mut self, did: DefId) -> stable_mir::mir::mono::StaticDef {
pub(crate) fn static_def(&self, did: DefId) -> stable_mir::mir::mono::StaticDef {
stable_mir::mir::mono::StaticDef(self.create_def_id(did))
}
}
@@ -127,107 +105,122 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
item.id.into()
}

pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
stable_mir::run(
Tables {
tcx,
def_ids: IndexMap::default(),
alloc_ids: IndexMap::default(),
spans: IndexMap::default(),
types: vec![],
instances: IndexMap::default(),
},
f,
);
pub fn run<'tcx>(tcx: TyCtxt<'tcx>, f: impl FnOnce(&Tables<'tcx>)) {
let tables = Tables {
tcx,
def_ids: IndexMap::default(),
alloc_ids: IndexMap::default(),
spans: IndexMap::default(),
types: RefCell::new(vec![]),
instances: IndexMap::default(),
};
stable_mir::run(&tables, || f(&tables));
}

pub struct StableMir<B = (), C = ()>
where
B: Send,
C: Send,
{
args: Vec<String>,
callback: fn(TyCtxt<'_>) -> ControlFlow<B, C>,
result: Option<ControlFlow<B, C>>,
}
#[macro_export]
macro_rules! run {
($args:expr, $callback:expr) => {
run!($args, tables, $callback)
};
($args:expr, $tables:ident, $callback:expr) => {{
use rustc_driver::{Callbacks, Compilation, RunCompiler};
use rustc_interface::{interface, Queries};
use rustc_smir::rustc_smir::Tables;
use stable_mir::CompilerError;
use std::ops::ControlFlow;

pub struct StableMir<B = (), C = ()>
where
B: Send,
C: Send,
{
args: Vec<String>,
callback: fn(&Tables<'_>) -> ControlFlow<B, C>,
result: Option<ControlFlow<B, C>>,
}

impl<B, C> StableMir<B, C>
where
B: Send,
C: Send,
{
/// Creates a new `StableMir` instance, with given test_function and arguments.
pub fn new(args: Vec<String>, callback: fn(TyCtxt<'_>) -> ControlFlow<B, C>) -> Self {
StableMir { args, callback, result: None }
}

/// Runs the compiler against given target and tests it with `test_function`
pub fn run(&mut self) -> Result<C, CompilerError<B>> {
let compiler_result =
rustc_driver::catch_fatal_errors(|| RunCompiler::new(&self.args.clone(), self).run());
match (compiler_result, self.result.take()) {
(Ok(Ok(())), Some(ControlFlow::Continue(value))) => Ok(value),
(Ok(Ok(())), Some(ControlFlow::Break(value))) => Err(CompilerError::Interrupted(value)),
(Ok(Ok(_)), None) => Err(CompilerError::Skipped),
(Ok(Err(_)), _) => Err(CompilerError::CompilationFailed),
(Err(_), _) => Err(CompilerError::ICE),
impl<B, C> StableMir<B, C>
where
B: Send,
C: Send,
{
/// Creates a new `StableMir` instance, with given test_function and arguments.
pub fn new(args: Vec<String>, callback: fn(&Tables<'_>) -> ControlFlow<B, C>) -> Self {
StableMir { args, callback, result: None }
}

/// Runs the compiler against given target and tests it with `test_function`
pub fn run(&mut self) -> Result<C, CompilerError<B>> {
let compiler_result = rustc_driver::catch_fatal_errors(|| {
RunCompiler::new(&self.args.clone(), self).run()
});
match (compiler_result, self.result.take()) {
(Ok(Ok(())), Some(ControlFlow::Continue(value))) => Ok(value),
(Ok(Ok(())), Some(ControlFlow::Break(value))) => {
Err(CompilerError::Interrupted(value))
}
(Ok(Ok(_)), None) => Err(CompilerError::Skipped),
(Ok(Err(_)), _) => Err(CompilerError::CompilationFailed),
(Err(_), _) => Err(CompilerError::ICE),
}
}
}
}
}

impl<B, C> Callbacks for StableMir<B, C>
where
B: Send,
C: Send,
{
/// Called after analysis. Return value instructs the compiler whether to
/// continue the compilation afterwards (defaults to `Compilation::Continue`)
fn after_analysis<'tcx>(
&mut self,
_compiler: &interface::Compiler,
queries: &'tcx Queries<'tcx>,
) -> Compilation {
queries.global_ctxt().unwrap().enter(|tcx| {
rustc_internal::run(tcx, || {
self.result = Some((self.callback)(tcx));
});
if self.result.as_ref().is_some_and(|val| val.is_continue()) {
Compilation::Continue
} else {
Compilation::Stop
impl<B, C> Callbacks for StableMir<B, C>
where
B: Send,
C: Send,
{
/// Called after analysis. Return value instructs the compiler whether to
/// continue the compilation afterwards (defaults to `Compilation::Continue`)
fn after_analysis<'tcx>(
&mut self,
_compiler: &interface::Compiler,
queries: &'tcx Queries<'tcx>,
) -> Compilation {
queries.global_ctxt().unwrap().enter(|tcx| {
rustc_smir::rustc_internal::run(tcx, |tables| {
self.result = Some((self.callback)(tables));
});
if self.result.as_ref().is_some_and(|val| val.is_continue()) {
Compilation::Continue
} else {
Compilation::Stop
}
})
}
})
}
}

StableMir::new($args, |$tables| $callback).run()
}};
}

/// Simmilar to rustc's `FxIndexMap`, `IndexMap` with extra
/// safety features added.
pub struct IndexMap<K, V> {
index_map: fx::FxIndexMap<K, V>,
index_map: RefCell<fx::FxIndexMap<K, V>>,
}

impl<K, V> Default for IndexMap<K, V> {
fn default() -> Self {
Self { index_map: FxIndexMap::default() }
Self { index_map: RefCell::new(FxIndexMap::default()) }
}
}

impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
pub fn create_or_fetch(&mut self, key: K) -> V {
let len = self.index_map.len();
let v = self.index_map.entry(key).or_insert(V::to_val(len));
pub fn create_or_fetch(&self, key: K) -> V {
let mut index_map = self.index_map.borrow_mut();
let len = index_map.len();
let v = index_map.entry(key).or_insert(V::to_val(len));
*v
}
}

impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V>
for IndexMap<K, V>
{
type Output = K;

fn index(&self, index: V) -> &Self::Output {
let (k, v) = self.index_map.get_index(index.to_index()).unwrap();
assert_eq!(*v, index, "Provided value doesn't match with indexed value");
impl<K: PartialEq + Hash + Eq + Copy, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
pub fn index_of(&self, index: V) -> K {
let map = self.index_map.borrow();
let (&k, &v) = map.get_index(index.to_index()).unwrap();
assert_eq!(v, index, "Provided value doesn't match with indexed value");
k
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_smir/src/rustc_smir/alloc.rs
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
pub fn new_allocation<'tcx>(
ty: rustc_middle::ty::Ty<'tcx>,
const_value: ConstValue<'tcx>,
tables: &mut Tables<'tcx>,
tables: &Tables<'tcx>,
) -> Allocation {
match const_value {
ConstValue::Scalar(scalar) => {
@@ -87,7 +87,7 @@ pub fn new_allocation<'tcx>(
pub(super) fn allocation_filter<'tcx>(
alloc: &rustc_middle::mir::interpret::Allocation,
alloc_range: AllocRange,
tables: &mut Tables<'tcx>,
tables: &Tables<'tcx>,
) -> Allocation {
let mut bytes: Vec<Option<u8>> = alloc
.inspect_with_uninit_and_ptr_outside_interpreter(
253 changes: 129 additions & 124 deletions compiler/rustc_smir/src/rustc_smir/mod.rs

Large diffs are not rendered by default.

46 changes: 23 additions & 23 deletions compiler/stable_mir/src/lib.rs
Original file line number Diff line number Diff line change
@@ -174,17 +174,17 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
}

pub trait Context {
fn entry_fn(&mut self) -> Option<CrateItem>;
fn entry_fn(&self) -> Option<CrateItem>;
/// Retrieve all items of the local crate that have a MIR associated with them.
fn all_local_items(&mut self) -> CrateItems;
fn mir_body(&mut self, item: DefId) -> mir::Body;
fn all_trait_decls(&mut self) -> TraitDecls;
fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl;
fn all_trait_impls(&mut self) -> ImplTraitDecls;
fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait;
fn generics_of(&mut self, def_id: DefId) -> Generics;
fn predicates_of(&mut self, def_id: DefId) -> GenericPredicates;
fn explicit_predicates_of(&mut self, def_id: DefId) -> GenericPredicates;
fn all_local_items(&self) -> CrateItems;
fn mir_body(&self, item: DefId) -> mir::Body;
fn all_trait_decls(&self) -> TraitDecls;
fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
fn all_trait_impls(&self) -> ImplTraitDecls;
fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait;
fn generics_of(&self, def_id: DefId) -> Generics;
fn predicates_of(&self, def_id: DefId) -> GenericPredicates;
fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates;
/// Get information about the local crate.
fn local_crate(&self) -> Crate;
/// Retrieve a list of all external crates.
@@ -206,48 +206,48 @@ pub trait Context {
fn get_lines(&self, span: &Span) -> LineInfo;

/// Returns the `kind` of given `DefId`
fn def_kind(&mut self, def_id: DefId) -> DefKind;
fn def_kind(&self, def_id: DefId) -> DefKind;

/// `Span` of an item
fn span_of_an_item(&mut self, def_id: DefId) -> Span;
fn span_of_an_item(&self, def_id: DefId) -> Span;

/// Obtain the representation of a type.
fn ty_kind(&mut self, ty: Ty) -> TyKind;
fn ty_kind(&self, ty: Ty) -> TyKind;

/// Create a new `Ty` from scratch without information from rustc.
fn mk_ty(&mut self, kind: TyKind) -> Ty;
fn mk_ty(&self, kind: TyKind) -> Ty;

/// Get the body of an Instance.
/// FIXME: Monomorphize the body.
fn instance_body(&mut self, instance: InstanceDef) -> Body;
fn instance_body(&self, instance: InstanceDef) -> Body;

/// Get the instance type with generic substitutions applied and lifetimes erased.
fn instance_ty(&mut self, instance: InstanceDef) -> Ty;
fn instance_ty(&self, instance: InstanceDef) -> Ty;

/// Get the instance.
fn instance_def_id(&mut self, instance: InstanceDef) -> DefId;
fn instance_def_id(&self, instance: InstanceDef) -> DefId;

/// Convert a non-generic crate item into an instance.
/// This function will panic if the item is generic.
fn mono_instance(&mut self, item: CrateItem) -> Instance;
fn mono_instance(&self, item: CrateItem) -> Instance;

/// Item requires monomorphization.
fn requires_monomorphization(&self, def_id: DefId) -> bool;
}

// A thread local variable that stores a pointer to the tables mapping between TyCtxt
// datastructures and stable MIR datastructures
scoped_thread_local! (static TLV: Cell<*mut ()>);
scoped_thread_local! (static TLV: Cell<*const ()>);

pub fn run(mut context: impl Context, f: impl FnOnce()) {
pub fn run<C: Context>(context: &C, f: impl FnOnce()) {
assert!(!TLV.is_set());
fn g<'a>(mut context: &mut (dyn Context + 'a), f: impl FnOnce()) {
let ptr: *mut () = &mut context as *mut &mut _ as _;
fn g<'a>(context: &(dyn Context + 'a), f: impl FnOnce()) {
let ptr: *const () = &context as *const &_ as _;
TLV.set(&Cell::new(ptr), || {
f();
});
}
g(&mut context, f);
g(context, f);
}

/// Loads the current context and calls a function with it.
21 changes: 10 additions & 11 deletions tests/ui-fulldeps/stable-mir/compilation-result.rs
Original file line number Diff line number Diff line change
@@ -4,19 +4,20 @@
// ignore-stage1
// ignore-cross-compile
// ignore-remote
// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
// edition: 2021

#![feature(rustc_private)]
#![feature(assert_matches)]

extern crate rustc_middle;
#[macro_use]
extern crate rustc_smir;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate stable_mir;

use rustc_middle::ty::TyCtxt;
use rustc_smir::rustc_internal;
use std::io::Write;
use std::ops::ControlFlow;

/// This test will generate and analyze a dummy crate using the stable mir.
/// For that, it will first write the dummy crate into a file.
@@ -33,28 +34,26 @@ fn main() {
}

fn test_continue(args: Vec<String>) {
let continue_fn = |_: TyCtxt| ControlFlow::Continue::<(), bool>(true);
let result = rustc_internal::StableMir::new(args, continue_fn).run();
let result = run!(args, ControlFlow::Continue::<(), bool>(true));
assert_eq!(result, Ok(true));
}

fn test_break(args: Vec<String>) {
let continue_fn = |_: TyCtxt| ControlFlow::Break::<bool, i32>(false);
let result = rustc_internal::StableMir::new(args, continue_fn).run();
let result = run!(args, ControlFlow::Break::<bool, i32>(false));
assert_eq!(result, Err(stable_mir::CompilerError::Interrupted(false)));
}

#[allow(unreachable_code)]
fn test_skipped(mut args: Vec<String>) {
args.push("--version".to_string());
let unreach_fn = |_: TyCtxt| -> ControlFlow<()> { unreachable!() };
let result = rustc_internal::StableMir::new(args, unreach_fn).run();
let result = run!(args, unreachable!() as ControlFlow<()>);
assert_eq!(result, Err(stable_mir::CompilerError::Skipped));
}

#[allow(unreachable_code)]
fn test_failed(mut args: Vec<String>) {
args.push("--cfg=broken".to_string());
let unreach_fn = |_: TyCtxt| -> ControlFlow<()> { unreachable!() };
let result = rustc_internal::StableMir::new(args, unreach_fn).run();
let result = run!(args, unreachable!() as ControlFlow<()>);
assert_eq!(result, Err(stable_mir::CompilerError::CompilationFailed));
}

14 changes: 9 additions & 5 deletions tests/ui-fulldeps/stable-mir/crate-info.rs
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
// ignore-stage1
// ignore-cross-compile
// ignore-remote
// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
// edition: 2021

#![feature(rustc_private)]
@@ -12,13 +13,15 @@

extern crate rustc_hir;
extern crate rustc_middle;
#[macro_use]
extern crate rustc_smir;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate stable_mir;

use rustc_hir::def::DefKind;
use rustc_middle::ty::TyCtxt;
use rustc_smir::rustc_internal;

use rustc_smir::rustc_smir::Tables;
use stable_mir::fold::Foldable;
use std::assert_matches::assert_matches;
use std::io::Write;
@@ -27,7 +30,7 @@ use std::ops::ControlFlow;
const CRATE_NAME: &str = "input";

/// This function uses the Stable MIR APIs to get information about the test crate.
fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
fn test_stable_mir(_tables: &Tables<'_>) -> ControlFlow<()> {
// Get the local crate using stable_mir API.
let local = stable_mir::local_crate();
assert_eq!(&local.name, CRATE_NAME);
@@ -127,7 +130,8 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
mut args,
)) => {
let func = def.body();
match func.locals[1].ty
match func.locals[1]
.ty
.fold(&mut args)
.continue_value()
.unwrap()
@@ -185,7 +189,7 @@ fn main() {
CRATE_NAME.to_string(),
path.to_string(),
];
rustc_internal::StableMir::new(args, test_stable_mir).run().unwrap();
run!(args, tcx, test_stable_mir(tcx)).unwrap();
}

fn generate_input(path: &str) -> std::io::Result<()> {
25 changes: 13 additions & 12 deletions tests/ui-fulldeps/stable-mir/instance.rs
Original file line number Diff line number Diff line change
@@ -4,40 +4,42 @@
// ignore-stage1
// ignore-cross-compile
// ignore-remote
// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
// edition: 2021

#![feature(rustc_private)]
#![feature(assert_matches)]
#![feature(control_flow_enum)]

extern crate rustc_middle;
#[macro_use]
extern crate rustc_smir;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate stable_mir;

use rustc_middle::ty::TyCtxt;

use rustc_smir::rustc_smir::Tables;
use stable_mir::*;
use rustc_smir::rustc_internal;
use std::io::Write;
use std::ops::ControlFlow;

const CRATE_NAME: &str = "input";

/// This function uses the Stable MIR APIs to get information about the test crate.
fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
fn test_stable_mir(_tables: &Tables<'_>) -> ControlFlow<()> {
let items = stable_mir::all_local_items();

// Get all items and split generic vs monomorphic items.
let (generic, mono) : (Vec<_>, Vec<_>) = items.into_iter().partition(|item| {
item.requires_monomorphization()
});
let (generic, mono): (Vec<_>, Vec<_>) =
items.into_iter().partition(|item| item.requires_monomorphization());
assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant");
assert_eq!(generic.len(), 2, "Expected 2 generic functions");

// For all monomorphic items, get the correspondent instances.
let instances = mono.iter().filter_map(|item| {
mir::mono::Instance::try_from(*item).ok()
}).collect::<Vec<mir::mono::Instance>>();
let instances = mono
.iter()
.filter_map(|item| mir::mono::Instance::try_from(*item).ok())
.collect::<Vec<mir::mono::Instance>>();
assert_eq!(instances.len(), mono.len());

// For all generic items, try_from should fail.
@@ -46,7 +48,6 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
ControlFlow::Continue(())
}


/// This test will generate and analyze a dummy crate using the stable mir.
/// For that, it will first write the dummy crate into a file.
/// Then it will create a `StableMir` using custom arguments and then
@@ -61,7 +62,7 @@ fn main() {
CRATE_NAME.to_string(),
path.to_string(),
];
rustc_internal::StableMir::new(args, test_stable_mir).run().unwrap();
run!(args, tables, test_stable_mir(tables)).unwrap();
}

fn generate_input(path: &str) -> std::io::Result<()> {