summaryrefslogtreecommitdiffstats
path: root/tests/ui-fulldeps/stable-mir/check_defs.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui-fulldeps/stable-mir/check_defs.rs')
-rw-r--r--tests/ui-fulldeps/stable-mir/check_defs.rs132
1 files changed, 132 insertions, 0 deletions
diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs
new file mode 100644
index 000000000..e9a2599d8
--- /dev/null
+++ b/tests/ui-fulldeps/stable-mir/check_defs.rs
@@ -0,0 +1,132 @@
+// run-pass
+//! Test that users are able to use stable mir APIs to retrieve information about crate definitions.
+
+// 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 std::assert_matches::assert_matches;
+use mir::{mono::Instance, TerminatorKind::*};
+use rustc_middle::ty::TyCtxt;
+use rustc_smir::rustc_internal;
+use stable_mir::ty::{RigidTy, TyKind, Ty, UintTy};
+use stable_mir::*;
+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<()> {
+ let entry = stable_mir::entry_fn().unwrap();
+ let main_fn = Instance::try_from(entry).unwrap();
+ assert_eq!(main_fn.name(), "main");
+ assert_eq!(main_fn.trimmed_name(), "main");
+
+ let instances = get_instances(main_fn.body().unwrap());
+ assert_eq!(instances.len(), 2);
+ test_fn(instances[0], "from_u32", "std::char::from_u32", "core");
+ test_fn(instances[1], "Vec::<u8>::new", "std::vec::Vec::<u8>::new", "alloc");
+ test_vec_new(instances[1]);
+ ControlFlow::Continue(())
+}
+
+fn test_fn(instance: Instance, expected_trimmed: &str, expected_qualified: &str, krate: &str) {
+ let trimmed = instance.trimmed_name();
+ let qualified = instance.name();
+ assert_eq!(&trimmed, expected_trimmed);
+ assert_eq!(&qualified, expected_qualified);
+
+ let item = CrateItem::try_from(instance).unwrap();
+ let trimmed = item.trimmed_name();
+ let qualified = item.name();
+ assert_eq!(trimmed, expected_trimmed.replace("u8", "T"));
+ assert_eq!(qualified, expected_qualified.replace("u8", "T"));
+ assert_eq!(&item.krate().name, krate);
+}
+
+fn extract_elem_ty(ty: Ty) -> Ty {
+ match ty.kind() {
+ TyKind::RigidTy(RigidTy::Adt(_, args)) => {
+ *args.0[0].expect_ty()
+ }
+ _ => unreachable!("Expected Vec ADT, but found: {ty:?}")
+ }
+}
+
+/// Check signature and type of `Vec::<u8>::new` and its generic version.
+fn test_vec_new(instance: mir::mono::Instance) {
+ let sig = instance.fn_abi().unwrap();
+ assert_eq!(&sig.args, &[]);
+ let elem_ty = extract_elem_ty(sig.ret.ty);
+ assert_matches!(elem_ty.kind(), TyKind::RigidTy(RigidTy::Uint(UintTy::U8)));
+
+ // Get the signature for Vec::<T>::new.
+ let item = CrateItem::try_from(instance).unwrap();
+ let ty = item.ty();
+ let gen_sig = ty.kind().fn_sig().unwrap().skip_binder();
+ let gen_ty = extract_elem_ty(gen_sig.output());
+ assert_matches!(gen_ty.kind(), TyKind::Param(_));
+}
+
+/// Inspect the instance body
+fn get_instances(body: mir::Body) -> Vec<Instance> {
+ body.blocks.iter().filter_map(|bb| {
+ match &bb.terminator.kind {
+ Call { func, .. } => {
+ let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else { unreachable!
+ () };
+ let RigidTy::FnDef(def, args) = ty else { unreachable!() };
+ Instance::resolve(def, &args).ok()
+ }
+ _ => {
+ None
+ }
+ }
+ }).collect::<Vec<_>>()
+}
+
+/// 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
+/// it will run the compiler.
+fn main() {
+ let path = "defs_input.rs";
+ generate_input(&path).unwrap();
+ let args = vec![
+ "rustc".to_string(),
+ "-Cpanic=abort".to_string(),
+ "--crate-name".to_string(),
+ CRATE_NAME.to_string(),
+ path.to_string(),
+ ];
+ run!(args, tcx, test_stable_mir(tcx)).unwrap();
+}
+
+fn generate_input(path: &str) -> std::io::Result<()> {
+ let mut file = std::fs::File::create(path)?;
+ write!(
+ file,
+ r#"
+
+ fn main() {{
+ let _c = core::char::from_u32(99);
+ let _v = Vec::<u8>::new();
+ }}
+ "#
+ )?;
+ Ok(())
+}