mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-16 05:56:56 +00:00
Make CrateItem::body() function return an option
When we initially created `CrateItem`, it would only represent items that contain a body. That is no longer the case, for now, make this explicit by expanding the APIs to retrieve the item body. This is related to https://github.com/rust-lang/project-stable-mir/issues/34
This commit is contained in:
parent
f9e0239a7b
commit
4d75c4f8f3
@ -129,13 +129,21 @@ crate_def_with_ty! {
|
||||
}
|
||||
|
||||
impl CrateItem {
|
||||
/// This will return the body of an item.
|
||||
///
|
||||
/// This will panic if no body is available.
|
||||
pub fn body(&self) -> mir::Body {
|
||||
/// This will return the body of an item or panic if it's not available.
|
||||
pub fn expect_body(&self) -> mir::Body {
|
||||
with(|cx| cx.mir_body(self.0))
|
||||
}
|
||||
|
||||
/// Return the body of an item if available.
|
||||
pub fn body(&self) -> Option<mir::Body> {
|
||||
with(|cx| cx.has_body(self.0).then(|| cx.mir_body(self.0)))
|
||||
}
|
||||
|
||||
/// Check if a body is available for this item.
|
||||
pub fn has_body(&self) -> bool {
|
||||
with(|cx| cx.has_body(self.0))
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
with(|cx| cx.span_of_an_item(self.0))
|
||||
}
|
||||
@ -156,8 +164,11 @@ impl CrateItem {
|
||||
with(|cx| cx.is_foreign_item(self.0))
|
||||
}
|
||||
|
||||
/// Emit MIR for this item body.
|
||||
pub fn emit_mir<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
self.body().dump(w, &self.name())
|
||||
self.body()
|
||||
.ok_or_else(|| io::Error::other(format!("No body found for `{}`", self.name())))?
|
||||
.dump(w, &self.name())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,11 @@ extern crate rustc_interface;
|
||||
extern crate stable_mir;
|
||||
|
||||
use rustc_smir::rustc_internal;
|
||||
use stable_mir::ty::{RigidTy, TyKind, Ty, };
|
||||
use stable_mir::mir::{Body, MirVisitor, FieldIdx, Place, ProjectionElem, visit::{Location,
|
||||
PlaceContext}};
|
||||
use stable_mir::mir::{
|
||||
Body, FieldIdx, MirVisitor, Place, ProjectionElem,
|
||||
visit::{Location, PlaceContext},
|
||||
};
|
||||
use stable_mir::ty::{RigidTy, Ty, TyKind};
|
||||
use std::io::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
@ -29,8 +31,8 @@ const CRATE_NAME: &str = "input";
|
||||
/// This function uses the Stable MIR APIs to get information about the test crate.
|
||||
fn test_stable_mir() -> ControlFlow<()> {
|
||||
let main_fn = stable_mir::entry_fn();
|
||||
let body = main_fn.unwrap().body();
|
||||
let mut visitor = PlaceVisitor{ body: &body, tested: false};
|
||||
let body = main_fn.unwrap().expect_body();
|
||||
let mut visitor = PlaceVisitor { body: &body, tested: false };
|
||||
visitor.visit_body(&body);
|
||||
assert!(visitor.tested);
|
||||
ControlFlow::Continue(())
|
||||
|
@ -45,7 +45,7 @@ fn test_stable_mir() -> ControlFlow<()> {
|
||||
assert!(stable_mir::find_crates("std").len() == 1);
|
||||
|
||||
let bar = get_item(&items, (DefKind::Fn, "bar")).unwrap();
|
||||
let body = bar.body();
|
||||
let body = bar.expect_body();
|
||||
assert_eq!(body.locals().len(), 2);
|
||||
assert_eq!(body.blocks.len(), 1);
|
||||
let block = &body.blocks[0];
|
||||
@ -60,7 +60,7 @@ fn test_stable_mir() -> ControlFlow<()> {
|
||||
}
|
||||
|
||||
let foo_bar = get_item(&items, (DefKind::Fn, "foo_bar")).unwrap();
|
||||
let body = foo_bar.body();
|
||||
let body = foo_bar.expect_body();
|
||||
assert_eq!(body.locals().len(), 5);
|
||||
assert_eq!(body.blocks.len(), 4);
|
||||
let block = &body.blocks[0];
|
||||
@ -70,7 +70,7 @@ fn test_stable_mir() -> ControlFlow<()> {
|
||||
}
|
||||
|
||||
let types = get_item(&items, (DefKind::Fn, "types")).unwrap();
|
||||
let body = types.body();
|
||||
let body = types.expect_body();
|
||||
assert_eq!(body.locals().len(), 6);
|
||||
assert_matches!(
|
||||
body.locals()[0].ty.kind(),
|
||||
@ -100,7 +100,7 @@ fn test_stable_mir() -> ControlFlow<()> {
|
||||
);
|
||||
|
||||
let drop = get_item(&items, (DefKind::Fn, "drop")).unwrap();
|
||||
let body = drop.body();
|
||||
let body = drop.expect_body();
|
||||
assert_eq!(body.blocks.len(), 2);
|
||||
let block = &body.blocks[0];
|
||||
match &block.terminator.kind {
|
||||
@ -109,7 +109,7 @@ fn test_stable_mir() -> ControlFlow<()> {
|
||||
}
|
||||
|
||||
let assert = get_item(&items, (DefKind::Fn, "assert")).unwrap();
|
||||
let body = assert.body();
|
||||
let body = assert.expect_body();
|
||||
assert_eq!(body.blocks.len(), 2);
|
||||
let block = &body.blocks[0];
|
||||
match &block.terminator.kind {
|
||||
@ -123,7 +123,8 @@ fn test_stable_mir() -> ControlFlow<()> {
|
||||
match &block.terminator.kind {
|
||||
stable_mir::mir::TerminatorKind::Call { func, .. } => {
|
||||
let TyKind::RigidTy(ty) = func.ty(&body.locals()).unwrap().kind() else {
|
||||
unreachable!() };
|
||||
unreachable!()
|
||||
};
|
||||
let RigidTy::FnDef(def, args) = ty else { unreachable!() };
|
||||
let next_func = Instance::resolve(def, &args).unwrap();
|
||||
match next_func.body().unwrap().locals()[1].ty.kind() {
|
||||
@ -138,10 +139,10 @@ fn test_stable_mir() -> ControlFlow<()> {
|
||||
|
||||
let foo_const = get_item(&items, (DefKind::Const, "FOO")).unwrap();
|
||||
// Ensure we don't panic trying to get the body of a constant.
|
||||
foo_const.body();
|
||||
foo_const.expect_body();
|
||||
|
||||
let locals_fn = get_item(&items, (DefKind::Fn, "locals")).unwrap();
|
||||
let body = locals_fn.body();
|
||||
let body = locals_fn.expect_body();
|
||||
assert_eq!(body.locals().len(), 4);
|
||||
assert_matches!(
|
||||
body.ret_local().ty.kind(),
|
||||
@ -172,8 +173,10 @@ fn get_item<'a>(
|
||||
item: (DefKind, &str),
|
||||
) -> Option<&'a stable_mir::CrateItem> {
|
||||
items.iter().find(|crate_item| {
|
||||
matches!((item.0, crate_item.kind()), (DefKind::Fn, ItemKind::Fn) | (DefKind::Const,
|
||||
ItemKind::Const)) && crate_item.name() == item.1
|
||||
matches!(
|
||||
(item.0, crate_item.kind()),
|
||||
(DefKind::Fn, ItemKind::Fn) | (DefKind::Const, ItemKind::Const)
|
||||
) && crate_item.name() == item.1
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,10 @@ extern crate rustc_interface;
|
||||
extern crate stable_mir;
|
||||
|
||||
use rustc_smir::rustc_internal;
|
||||
use stable_mir::ItemKind;
|
||||
use stable_mir::crate_def::CrateDef;
|
||||
use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind};
|
||||
use stable_mir::ty::{RigidTy, TyKind, UintTy};
|
||||
use stable_mir::ItemKind;
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::io::Write;
|
||||
use std::ops::ControlFlow;
|
||||
@ -31,7 +31,7 @@ const CRATE_NAME: &str = "input";
|
||||
/// Tests projections within Place objects
|
||||
fn test_place_projections() -> ControlFlow<()> {
|
||||
let items = stable_mir::all_local_items();
|
||||
let body = get_item(&items, (ItemKind::Fn, "projections")).unwrap().body();
|
||||
let body = get_item(&items, (ItemKind::Fn, "projections")).unwrap().expect_body();
|
||||
assert_eq!(body.blocks.len(), 4);
|
||||
// The first statement assigns `&s.c` to a local. The projections include a deref for `s`, since
|
||||
// `s` is passed as a reference argument, and a field access for field `c`.
|
||||
@ -53,7 +53,7 @@ fn test_place_projections() -> ControlFlow<()> {
|
||||
);
|
||||
let ty = place.ty(body.locals()).unwrap();
|
||||
assert_matches!(ty.kind().rigid(), Some(RigidTy::Ref(..)));
|
||||
},
|
||||
}
|
||||
other => panic!(
|
||||
"Unable to match against expected rvalue projection. Expected the projection \
|
||||
for `s.c`, which is a Deref and u8 Field. Got: {:?}",
|
||||
@ -137,9 +137,7 @@ fn get_item<'a>(
|
||||
items: &'a stable_mir::CrateItems,
|
||||
item: (ItemKind, &str),
|
||||
) -> Option<&'a stable_mir::CrateItem> {
|
||||
items.iter().find(|crate_item| {
|
||||
crate_item.kind() == item.0 && crate_item.name() == item.1
|
||||
})
|
||||
items.iter().find(|crate_item| crate_item.kind() == item.0 && crate_item.name() == item.1)
|
||||
}
|
||||
|
||||
/// This test will generate and analyze a dummy crate using the stable mir.
|
||||
|
@ -26,7 +26,7 @@ const CRATE_NAME: &str = "input";
|
||||
|
||||
fn test_translation(tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
||||
let main_fn = stable_mir::entry_fn().unwrap();
|
||||
let body = main_fn.body();
|
||||
let body = main_fn.expect_body();
|
||||
let orig_ty = body.locals()[0].ty;
|
||||
let rustc_ty = rustc_internal::internal(tcx, &orig_ty);
|
||||
assert!(rustc_ty.is_unit());
|
||||
|
@ -14,33 +14,29 @@ extern crate rustc_smir;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_interface;
|
||||
extern crate rustc_middle;
|
||||
extern crate stable_mir;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate stable_mir;
|
||||
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_smir::rustc_internal;
|
||||
use stable_mir::mir::Body;
|
||||
use std::io::{Write, BufWriter};
|
||||
use std::ops::ControlFlow;
|
||||
use serde_json::to_string;
|
||||
|
||||
use stable_mir::mir::Body;
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
const CRATE_NAME: &str = "input";
|
||||
|
||||
fn serialize_to_json(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
||||
let path = "output.json";
|
||||
let mut writer = BufWriter::new(std::fs::File::create(path)
|
||||
.expect("Failed to create path"));
|
||||
let mut writer = BufWriter::new(std::fs::File::create(path).expect("Failed to create path"));
|
||||
let local_crate = stable_mir::local_crate();
|
||||
let items: Vec<Body> = stable_mir::all_local_items()
|
||||
.iter()
|
||||
.map(|item| { item.body() })
|
||||
.collect();
|
||||
let crate_data = ( local_crate.name, items );
|
||||
writer.write_all(to_string(&crate_data)
|
||||
.expect("serde_json failed")
|
||||
.as_bytes()).expect("JSON serialization failed");
|
||||
let items: Vec<Body> =
|
||||
stable_mir::all_local_items().iter().map(|item| item.expect_body()).collect();
|
||||
let crate_data = (local_crate.name, items);
|
||||
writer
|
||||
.write_all(to_string(&crate_data).expect("serde_json failed").as_bytes())
|
||||
.expect("JSON serialization failed");
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,10 @@ extern crate rustc_driver;
|
||||
extern crate rustc_interface;
|
||||
extern crate stable_mir;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use rustc_smir::rustc_internal;
|
||||
use stable_mir::*;
|
||||
use stable_mir::mir::MirVisitor;
|
||||
use stable_mir::*;
|
||||
use std::collections::HashSet;
|
||||
use std::io::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
@ -27,7 +27,7 @@ const CRATE_NAME: &str = "input";
|
||||
|
||||
fn test_visitor() -> ControlFlow<()> {
|
||||
let main_fn = stable_mir::entry_fn();
|
||||
let main_body = main_fn.unwrap().body();
|
||||
let main_body = main_fn.unwrap().expect_body();
|
||||
let main_visitor = TestVisitor::collect(&main_body);
|
||||
assert!(main_visitor.ret_val.is_some());
|
||||
assert!(main_visitor.args.is_empty());
|
||||
@ -51,7 +51,7 @@ struct TestVisitor<'a> {
|
||||
pub tys: HashSet<ty::Ty>,
|
||||
pub ret_val: Option<mir::LocalDecl>,
|
||||
pub args: Vec<mir::LocalDecl>,
|
||||
pub calls: Vec<mir::mono::Instance>
|
||||
pub calls: Vec<mir::mono::Instance>,
|
||||
}
|
||||
|
||||
impl<'a> TestVisitor<'a> {
|
||||
@ -90,8 +90,8 @@ impl<'a> mir::MirVisitor for TestVisitor<'a> {
|
||||
fn visit_terminator(&mut self, term: &mir::Terminator, location: mir::visit::Location) {
|
||||
if let mir::TerminatorKind::Call { func, .. } = &term.kind {
|
||||
let ty::TyKind::RigidTy(ty) = func.ty(self.body.locals()).unwrap().kind() else {
|
||||
unreachable!
|
||||
() };
|
||||
unreachable!()
|
||||
};
|
||||
let ty::RigidTy::FnDef(def, args) = ty else { unreachable!() };
|
||||
self.calls.push(mir::mono::Instance::resolve(def, &args).unwrap());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user