Skip to content

Commit

Permalink
Rollup merge of rust-lang#138026 - celinval:chores-item-has-body, r=c…
Browse files Browse the repository at this point in the history
…ompiler-errors

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 rust-lang/project-stable-mir#34

r? `@oli-obk`
  • Loading branch information
workingjubilee authored Mar 5, 2025
2 parents a69982e + 4d75c4f commit 3065925
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 47 deletions.
21 changes: 16 additions & 5 deletions compiler/stable_mir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand All @@ -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())
}
}

Expand Down
12 changes: 7 additions & 5 deletions tests/ui-fulldeps/stable-mir/check_ty_fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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(())
Expand Down
23 changes: 13 additions & 10 deletions tests/ui-fulldeps/stable-mir/crate-info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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];
Expand All @@ -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(),
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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() {
Expand All @@ -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(),
Expand Down Expand Up @@ -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
})
}

Expand Down
10 changes: 4 additions & 6 deletions tests/ui-fulldeps/stable-mir/projections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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`.
Expand All @@ -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: {:?}",
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion tests/ui-fulldeps/stable-mir/smir_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
24 changes: 10 additions & 14 deletions tests/ui-fulldeps/stable-mir/smir_serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 serde_json::to_string;
use stable_mir::mir::Body;
use std::io::{Write, BufWriter};
use std::io::{BufWriter, Write};
use std::ops::ControlFlow;
use serde_json::to_string;


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(())
}

Expand Down
12 changes: 6 additions & 6 deletions tests/ui-fulldeps/stable-mir/smir_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ 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;

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());
Expand All @@ -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> {
Expand Down Expand Up @@ -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());
}
Expand Down

0 comments on commit 3065925

Please sign in to comment.