Skip to content

Commit 98228e6

Browse files
committed
Move SMIR projections tests to new file
1 parent b158598 commit 98228e6

File tree

2 files changed

+175
-103
lines changed

2 files changed

+175
-103
lines changed

tests/ui-fulldeps/stable-mir/crate-info.rs

Lines changed: 0 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use rustc_hir::def::DefKind;
2323
use rustc_middle::ty::TyCtxt;
2424
use rustc_smir::rustc_internal;
2525
use stable_mir::mir::mono::Instance;
26-
use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind};
2726
use stable_mir::ty::{RigidTy, TyKind};
2827
use std::assert_matches::assert_matches;
2928
use std::io::Write;
@@ -164,99 +163,6 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
164163
stable_mir::ty::TyKind::RigidTy(stable_mir::ty::RigidTy::Bool)
165164
);
166165

167-
let projections_fn = get_item(&items, (DefKind::Fn, "projections")).unwrap();
168-
let body = projections_fn.body();
169-
assert_eq!(body.blocks.len(), 4);
170-
// The first statement assigns `&s.c` to a local. The projections include a deref for `s`, since
171-
// `s` is passed as a reference argument, and a field access for field `c`.
172-
match &body.blocks[0].statements[0].kind {
173-
StatementKind::Assign(
174-
stable_mir::mir::Place { local: _, projection: local_proj },
175-
Rvalue::Ref(_, _, stable_mir::mir::Place { local: _, projection: r_proj }),
176-
) => {
177-
// We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
178-
// since we'd then have to add in the expected local and region values instead of
179-
// matching on wildcards.
180-
assert_matches!(local_proj[..], []);
181-
match &r_proj[..] {
182-
// Similarly we can't match against a type, only against its kind.
183-
[ProjectionElem::Deref, ProjectionElem::Field(2, ty)] => assert_matches!(
184-
ty.kind(),
185-
TyKind::RigidTy(RigidTy::Uint(stable_mir::ty::UintTy::U8))
186-
),
187-
other => panic!(
188-
"Unable to match against expected rvalue projection. Expected the projection \
189-
for `s.c`, which is a Deref and u8 Field. Got: {:?}",
190-
other
191-
),
192-
};
193-
}
194-
other => panic!(
195-
"Unable to match against expected Assign statement with a Ref rvalue. Expected the \
196-
statement to assign `&s.c` to a local. Got: {:?}",
197-
other
198-
),
199-
};
200-
// This statement assigns `slice[1]` to a local. The projections include a deref for `slice`,
201-
// since `slice` is a reference, and an index.
202-
match &body.blocks[2].statements[0].kind {
203-
StatementKind::Assign(
204-
stable_mir::mir::Place { local: _, projection: local_proj },
205-
Rvalue::Use(stable_mir::mir::Operand::Copy(stable_mir::mir::Place {
206-
local: _,
207-
projection: r_proj,
208-
})),
209-
) => {
210-
// We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
211-
// since we'd then have to add in the expected local values instead of matching on
212-
// wildcards.
213-
assert_matches!(local_proj[..], []);
214-
assert_matches!(r_proj[..], [ProjectionElem::Deref, ProjectionElem::Index(_)]);
215-
}
216-
other => panic!(
217-
"Unable to match against expected Assign statement with a Use rvalue. Expected the \
218-
statement to assign `slice[1]` to a local. Got: {:?}",
219-
other
220-
),
221-
};
222-
// The first terminator gets a slice of an array via the Index operation. Specifically it
223-
// performs `&vals[1..3]`. There are no projections in this case, the arguments are just locals.
224-
match &body.blocks[0].terminator.kind {
225-
stable_mir::mir::TerminatorKind::Call { args, .. } =>
226-
// We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
227-
// since we'd then have to add in the expected local values instead of matching on
228-
// wildcards.
229-
{
230-
match &args[..] {
231-
[
232-
stable_mir::mir::Operand::Move(stable_mir::mir::Place {
233-
local: _,
234-
projection: arg1_proj,
235-
}),
236-
stable_mir::mir::Operand::Move(stable_mir::mir::Place {
237-
local: _,
238-
projection: arg2_proj,
239-
}),
240-
] => {
241-
assert_matches!(arg1_proj[..], []);
242-
assert_matches!(arg2_proj[..], []);
243-
}
244-
other => {
245-
panic!(
246-
"Unable to match against expected arguments to Index call. Expected two \
247-
move operands. Got: {:?}",
248-
other
249-
)
250-
}
251-
}
252-
}
253-
other => panic!(
254-
"Unable to match against expected Call terminator. Expected a terminator that calls \
255-
the Index operation. Got: {:?}",
256-
other
257-
),
258-
};
259-
260166
ControlFlow::Continue(())
261167
}
262168

@@ -336,15 +242,6 @@ fn generate_input(path: &str) -> std::io::Result<()> {
336242
}} else {{
337243
'b'
338244
}}
339-
}}
340-
341-
pub struct Struct1 {{ _a: u8, _b: u16, c: u8 }}
342-
343-
pub fn projections(s: &Struct1) -> u8 {{
344-
let v = &s.c;
345-
let vals = [1, 2, 3, 4];
346-
let slice = &vals[1..3];
347-
v + slice[1]
348245
}}"#
349246
)?;
350247
Ok(())
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// run-pass
2+
// Tests the Stable MIR projections API
3+
4+
// ignore-stage1
5+
// ignore-cross-compile
6+
// ignore-remote
7+
// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
8+
// edition: 2021
9+
10+
#![feature(rustc_private)]
11+
#![feature(assert_matches)]
12+
#![feature(control_flow_enum)]
13+
14+
extern crate rustc_hir;
15+
extern crate rustc_middle;
16+
#[macro_use]
17+
extern crate rustc_smir;
18+
extern crate rustc_driver;
19+
extern crate rustc_interface;
20+
extern crate stable_mir;
21+
22+
use rustc_hir::def::DefKind;
23+
use rustc_middle::ty::TyCtxt;
24+
use rustc_smir::rustc_internal;
25+
use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind};
26+
use stable_mir::ty::{RigidTy, TyKind};
27+
use std::assert_matches::assert_matches;
28+
use std::io::Write;
29+
use std::ops::ControlFlow;
30+
31+
const CRATE_NAME: &str = "input";
32+
33+
/// This function uses the Stable MIR APIs to get information about the test crate.
34+
fn test_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
35+
// Find items in the local crate.
36+
let items = stable_mir::all_local_items();
37+
38+
let body = get_item(&items, (DefKind::Fn, "projections")).unwrap().body();
39+
assert_eq!(body.blocks.len(), 4);
40+
// The first statement assigns `&s.c` to a local. The projections include a deref for `s`, since
41+
// `s` is passed as a reference argument, and a field access for field `c`.
42+
match &body.blocks[0].statements[0].kind {
43+
StatementKind::Assign(
44+
stable_mir::mir::Place { local: _, projection: local_proj },
45+
Rvalue::Ref(_, _, stable_mir::mir::Place { local: _, projection: r_proj }),
46+
) => {
47+
// We can't match on vecs, only on slices. Comparing statements for equality wouldn't be
48+
// any easier since we'd then have to add in the expected local and region values
49+
// instead of matching on wildcards.
50+
assert_matches!(local_proj[..], []);
51+
match &r_proj[..] {
52+
// Similarly we can't match against a type, only against its kind.
53+
[ProjectionElem::Deref, ProjectionElem::Field(2, ty)] => assert_matches!(
54+
ty.kind(),
55+
TyKind::RigidTy(RigidTy::Uint(stable_mir::ty::UintTy::U8))
56+
),
57+
other => panic!(
58+
"Unable to match against expected rvalue projection. Expected the projection \
59+
for `s.c`, which is a Deref and u8 Field. Got: {:?}",
60+
other
61+
),
62+
};
63+
}
64+
other => panic!(
65+
"Unable to match against expected Assign statement with a Ref rvalue. Expected the \
66+
statement to assign `&s.c` to a local. Got: {:?}",
67+
other
68+
),
69+
};
70+
// This statement assigns `slice[1]` to a local. The projections include a deref for `slice`,
71+
// since `slice` is a reference, and an index.
72+
match &body.blocks[2].statements[0].kind {
73+
StatementKind::Assign(
74+
stable_mir::mir::Place { local: _, projection: local_proj },
75+
Rvalue::Use(stable_mir::mir::Operand::Copy(stable_mir::mir::Place {
76+
local: _,
77+
projection: r_proj,
78+
})),
79+
) => {
80+
// We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
81+
// since we'd then have to add in the expected local values instead of matching on
82+
// wildcards.
83+
assert_matches!(local_proj[..], []);
84+
assert_matches!(r_proj[..], [ProjectionElem::Deref, ProjectionElem::Index(_)]);
85+
}
86+
other => panic!(
87+
"Unable to match against expected Assign statement with a Use rvalue. Expected the \
88+
statement to assign `slice[1]` to a local. Got: {:?}",
89+
other
90+
),
91+
};
92+
// The first terminator gets a slice of an array via the Index operation. Specifically it
93+
// performs `&vals[1..3]`. There are no projections in this case, the arguments are just locals.
94+
match &body.blocks[0].terminator.kind {
95+
stable_mir::mir::TerminatorKind::Call { args, .. } =>
96+
// We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
97+
// since we'd then have to add in the expected local values instead of matching on
98+
// wildcards.
99+
{
100+
match &args[..] {
101+
[
102+
stable_mir::mir::Operand::Move(stable_mir::mir::Place {
103+
local: _,
104+
projection: arg1_proj,
105+
}),
106+
stable_mir::mir::Operand::Move(stable_mir::mir::Place {
107+
local: _,
108+
projection: arg2_proj,
109+
}),
110+
] => {
111+
assert_matches!(arg1_proj[..], []);
112+
assert_matches!(arg2_proj[..], []);
113+
}
114+
other => {
115+
panic!(
116+
"Unable to match against expected arguments to Index call. Expected two \
117+
move operands. Got: {:?}",
118+
other
119+
)
120+
}
121+
}
122+
}
123+
other => panic!(
124+
"Unable to match against expected Call terminator. Expected a terminator that calls \
125+
the Index operation. Got: {:?}",
126+
other
127+
),
128+
};
129+
130+
ControlFlow::Continue(())
131+
}
132+
133+
// Use internal API to find a function in a crate.
134+
fn get_item<'a>(
135+
items: &'a stable_mir::CrateItems,
136+
item: (DefKind, &str),
137+
) -> Option<&'a stable_mir::CrateItem> {
138+
items.iter().find(|crate_item| {
139+
crate_item.kind().to_string() == format!("{:?}", item.0) && crate_item.name() == item.1
140+
})
141+
}
142+
143+
/// This test will generate and analyze a dummy crate using the stable mir.
144+
/// For that, it will first write the dummy crate into a file.
145+
/// Then it will create a `StableMir` using custom arguments and then
146+
/// it will run the compiler.
147+
fn main() {
148+
let path = "input.rs";
149+
generate_input(&path).unwrap();
150+
let args = vec![
151+
"rustc".to_string(),
152+
"--crate-type=lib".to_string(),
153+
"--crate-name".to_string(),
154+
CRATE_NAME.to_string(),
155+
path.to_string(),
156+
];
157+
run!(args, tcx, test_projections(tcx)).unwrap();
158+
}
159+
160+
fn generate_input(path: &str) -> std::io::Result<()> {
161+
let mut file = std::fs::File::create(path)?;
162+
write!(
163+
file,
164+
r#"
165+
pub struct Struct1 {{ _a: u8, _b: u16, c: u8 }}
166+
167+
pub fn projections(s: &Struct1) -> u8 {{
168+
let v = &s.c;
169+
let vals = [1, 2, 3, 4];
170+
let slice = &vals[1..3];
171+
v + slice[1]
172+
}}"#
173+
)?;
174+
Ok(())
175+
}

0 commit comments

Comments
 (0)