about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKirby Linvill <kjlinvill@gmail.com>2023-11-09 17:59:24 -0700
committerKirby Linvill <kjlinvill@gmail.com>2023-11-09 20:56:39 -0700
commit98228e67bc11a15e03c4db1bd61ffda6b4620ecb (patch)
tree5459d1a16dee48e27cbb4bc5a191f13f1c951cf4
parentb1585983ccd83c8bf15e5e19ec594c00b8a37a2e (diff)
downloadrust-98228e67bc11a15e03c4db1bd61ffda6b4620ecb.tar.gz
rust-98228e67bc11a15e03c4db1bd61ffda6b4620ecb.zip
Move SMIR projections tests to new file
-rw-r--r--tests/ui-fulldeps/stable-mir/crate-info.rs103
-rw-r--r--tests/ui-fulldeps/stable-mir/projections.rs175
2 files changed, 175 insertions, 103 deletions
diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs
index c6aaea14872..ed6b786f5e1 100644
--- a/tests/ui-fulldeps/stable-mir/crate-info.rs
+++ b/tests/ui-fulldeps/stable-mir/crate-info.rs
@@ -23,7 +23,6 @@ use rustc_hir::def::DefKind;
 use rustc_middle::ty::TyCtxt;
 use rustc_smir::rustc_internal;
 use stable_mir::mir::mono::Instance;
-use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind};
 use stable_mir::ty::{RigidTy, TyKind};
 use std::assert_matches::assert_matches;
 use std::io::Write;
@@ -164,99 +163,6 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
         stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool)
     );
 
-    let projections_fn = get_item(&items, (DefKind::Fn, "projections")).unwrap();
-    let body = projections_fn.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`.
-    match &body.blocks[0].statements[0].kind {
-        StatementKind::Assign(
-            stable_mir::mir::Place { local: _, projection: local_proj },
-            Rvalue::Ref(_, _, stable_mir::mir::Place { local: _, projection: r_proj }),
-        ) => {
-            // We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
-            // since we'd then have to add in the expected local and region values instead of
-            // matching on wildcards.
-            assert_matches!(local_proj[..], []);
-            match &r_proj[..] {
-                // Similarly we can't match against a type, only against its kind.
-                [ProjectionElem::Deref, ProjectionElem::Field(2, ty)] => assert_matches!(
-                    ty.kind(),
-                    TyKind::RigidTy(RigidTy::Uint(stable_mir::ty::UintTy::U8))
-                ),
-                other => panic!(
-                    "Unable to match against expected rvalue projection. Expected the projection \
-                     for `s.c`, which is a Deref and u8 Field. Got: {:?}",
-                    other
-                ),
-            };
-        }
-        other => panic!(
-            "Unable to match against expected Assign statement with a Ref rvalue. Expected the \
-             statement to assign `&s.c` to a local. Got: {:?}",
-            other
-        ),
-    };
-    // This statement assigns `slice[1]` to a local. The projections include a deref for `slice`,
-    // since `slice` is a reference, and an index.
-    match &body.blocks[2].statements[0].kind {
-        StatementKind::Assign(
-            stable_mir::mir::Place { local: _, projection: local_proj },
-            Rvalue::Use(stable_mir::mir::Operand::Copy(stable_mir::mir::Place {
-                local: _,
-                projection: r_proj,
-            })),
-        ) => {
-            // We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
-            // since we'd then have to add in the expected local values instead of matching on
-            // wildcards.
-            assert_matches!(local_proj[..], []);
-            assert_matches!(r_proj[..], [ProjectionElem::Deref, ProjectionElem::Index(_)]);
-        }
-        other => panic!(
-            "Unable to match against expected Assign statement with a Use rvalue. Expected the \
-             statement to assign `slice[1]` to a local. Got: {:?}",
-            other
-        ),
-    };
-    // The first terminator gets a slice of an array via the Index operation. Specifically it
-    // performs `&vals[1..3]`. There are no projections in this case, the arguments are just locals.
-    match &body.blocks[0].terminator.kind {
-        stable_mir::mir::TerminatorKind::Call { args, .. } =>
-        // We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
-        // since we'd then have to add in the expected local values instead of matching on
-        // wildcards.
-        {
-            match &args[..] {
-                [
-                    stable_mir::mir::Operand::Move(stable_mir::mir::Place {
-                        local: _,
-                        projection: arg1_proj,
-                    }),
-                    stable_mir::mir::Operand::Move(stable_mir::mir::Place {
-                        local: _,
-                        projection: arg2_proj,
-                    }),
-                ] => {
-                    assert_matches!(arg1_proj[..], []);
-                    assert_matches!(arg2_proj[..], []);
-                }
-                other => {
-                    panic!(
-                        "Unable to match against expected arguments to Index call. Expected two \
-                         move operands. Got: {:?}",
-                        other
-                    )
-                }
-            }
-        }
-        other => panic!(
-            "Unable to match against expected Call terminator. Expected a terminator that calls \
-             the Index operation. Got: {:?}",
-            other
-        ),
-    };
-
     ControlFlow::Continue(())
 }
 
@@ -336,15 +242,6 @@ fn generate_input(path: &str) -> std::io::Result<()> {
         }} else {{
             'b'
         }}
-    }}
-
-    pub struct Struct1 {{ _a: u8, _b: u16, c: u8 }}
-
-    pub fn projections(s: &Struct1) -> u8 {{
-        let v = &s.c;
-        let vals = [1, 2, 3, 4];
-        let slice = &vals[1..3];
-        v + slice[1]
     }}"#
     )?;
     Ok(())
diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs
new file mode 100644
index 00000000000..d1b4fc5b28e
--- /dev/null
+++ b/tests/ui-fulldeps/stable-mir/projections.rs
@@ -0,0 +1,175 @@
+// run-pass
+// Tests the Stable MIR projections API
+
+// 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_hir;
+extern crate rustc_middle;
+#[macro_use]
+extern crate rustc_smir;
+extern crate rustc_driver;
+extern crate rustc_interface;
+extern crate stable_mir;
+
+use rustc_hir::def::DefKind;
+use rustc_middle::ty::TyCtxt;
+use rustc_smir::rustc_internal;
+use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind};
+use stable_mir::ty::{RigidTy, TyKind};
+use std::assert_matches::assert_matches;
+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_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
+    // Find items in the local crate.
+    let items = stable_mir::all_local_items();
+
+    let body = get_item(&items, (DefKind::Fn, "projections")).unwrap().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`.
+    match &body.blocks[0].statements[0].kind {
+        StatementKind::Assign(
+            stable_mir::mir::Place { local: _, projection: local_proj },
+            Rvalue::Ref(_, _, stable_mir::mir::Place { local: _, projection: r_proj }),
+        ) => {
+            // We can't match on vecs, only on slices. Comparing statements for equality wouldn't be
+            // any easier since we'd then have to add in the expected local and region values
+            // instead of matching on wildcards.
+            assert_matches!(local_proj[..], []);
+            match &r_proj[..] {
+                // Similarly we can't match against a type, only against its kind.
+                [ProjectionElem::Deref, ProjectionElem::Field(2, ty)] => assert_matches!(
+                    ty.kind(),
+                    TyKind::RigidTy(RigidTy::Uint(stable_mir::ty::UintTy::U8))
+                ),
+                other => panic!(
+                    "Unable to match against expected rvalue projection. Expected the projection \
+                     for `s.c`, which is a Deref and u8 Field. Got: {:?}",
+                    other
+                ),
+            };
+        }
+        other => panic!(
+            "Unable to match against expected Assign statement with a Ref rvalue. Expected the \
+             statement to assign `&s.c` to a local. Got: {:?}",
+            other
+        ),
+    };
+    // This statement assigns `slice[1]` to a local. The projections include a deref for `slice`,
+    // since `slice` is a reference, and an index.
+    match &body.blocks[2].statements[0].kind {
+        StatementKind::Assign(
+            stable_mir::mir::Place { local: _, projection: local_proj },
+            Rvalue::Use(stable_mir::mir::Operand::Copy(stable_mir::mir::Place {
+                local: _,
+                projection: r_proj,
+            })),
+        ) => {
+            // We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
+            // since we'd then have to add in the expected local values instead of matching on
+            // wildcards.
+            assert_matches!(local_proj[..], []);
+            assert_matches!(r_proj[..], [ProjectionElem::Deref, ProjectionElem::Index(_)]);
+        }
+        other => panic!(
+            "Unable to match against expected Assign statement with a Use rvalue. Expected the \
+             statement to assign `slice[1]` to a local. Got: {:?}",
+            other
+        ),
+    };
+    // The first terminator gets a slice of an array via the Index operation. Specifically it
+    // performs `&vals[1..3]`. There are no projections in this case, the arguments are just locals.
+    match &body.blocks[0].terminator.kind {
+        stable_mir::mir::TerminatorKind::Call { args, .. } =>
+        // We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
+        // since we'd then have to add in the expected local values instead of matching on
+        // wildcards.
+        {
+            match &args[..] {
+                [
+                    stable_mir::mir::Operand::Move(stable_mir::mir::Place {
+                        local: _,
+                        projection: arg1_proj,
+                    }),
+                    stable_mir::mir::Operand::Move(stable_mir::mir::Place {
+                        local: _,
+                        projection: arg2_proj,
+                    }),
+                ] => {
+                    assert_matches!(arg1_proj[..], []);
+                    assert_matches!(arg2_proj[..], []);
+                }
+                other => {
+                    panic!(
+                        "Unable to match against expected arguments to Index call. Expected two \
+                         move operands. Got: {:?}",
+                        other
+                    )
+                }
+            }
+        }
+        other => panic!(
+            "Unable to match against expected Call terminator. Expected a terminator that calls \
+             the Index operation. Got: {:?}",
+            other
+        ),
+    };
+
+    ControlFlow::Continue(())
+}
+
+// Use internal API to find a function in a crate.
+fn get_item<'a>(
+    items: &'a stable_mir::CrateItems,
+    item: (DefKind, &str),
+) -> Option<&'a stable_mir::CrateItem> {
+    items.iter().find(|crate_item| {
+        crate_item.kind().to_string() == format!("{:?}", item.0) && crate_item.name() == item.1
+    })
+}
+
+/// 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 = "input.rs";
+    generate_input(&path).unwrap();
+    let args = vec![
+        "rustc".to_string(),
+        "--crate-type=lib".to_string(),
+        "--crate-name".to_string(),
+        CRATE_NAME.to_string(),
+        path.to_string(),
+    ];
+    run!(args, tcx, test_projections(tcx)).unwrap();
+}
+
+fn generate_input(path: &str) -> std::io::Result<()> {
+    let mut file = std::fs::File::create(path)?;
+    write!(
+        file,
+        r#"
+    pub struct Struct1 {{ _a: u8, _b: u16, c: u8 }}
+
+    pub fn projections(s: &Struct1) -> u8 {{
+        let v = &s.c;
+        let vals = [1, 2, 3, 4];
+        let slice = &vals[1..3];
+        v + slice[1]
+    }}"#
+    )?;
+    Ok(())
+}