diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 8df36e23c4a21..70d42dfbfcb9a 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -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 { + 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(&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()) } } diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs index 9fa4929d68e27..9d71697178e58 100644 --- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs +++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs @@ -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(()) diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 7f0e9b50335d3..4d2d7e26276b5 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -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 }) } diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs index 3cc71247e6744..6f82eba61fcea 100644 --- a/tests/ui-fulldeps/stable-mir/projections.rs +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -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. diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index 453e5372de4f8..f9972dc27e3ff 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -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()); diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs index 2c74276d550cf..9b3638a9f2f40 100644 --- a/tests/ui-fulldeps/stable-mir/smir_serde.rs +++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs @@ -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 = 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 = + 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(()) } diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index 0a6415d490e4b..cffb41742b4e4 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -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, pub ret_val: Option, pub args: Vec, - pub calls: Vec + pub calls: Vec, } 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()); }