Skip to content

Make CrateItem::body() function return an option #138026

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

Merged
merged 1 commit into from
Mar 5, 2025
Merged
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
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
Loading