Skip to content

Commit 3416087

Browse files
authored
Rollup merge of #141639 - NotLebedev:stable-mir-93, r=oli-obk
Expose discriminant values in stable_mir Resolves rust-lang/project-stable-mir#93 * Added `Discr` struct to stable mir as stable version of struct with same name * Added `discriminant_for_variant` method to `AdtDef` and `CoroutineDef`
2 parents 68ac5ab + 9505b6e commit 3416087

File tree

5 files changed

+254
-8
lines changed

5 files changed

+254
-8
lines changed

compiler/rustc_smir/src/rustc_smir/context.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use rustc_middle::ty::layout::{
1212
};
1313
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
1414
use rustc_middle::ty::{
15-
GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, ValTree,
15+
CoroutineArgsExt, GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt,
16+
ValTree,
1617
};
1718
use rustc_middle::{mir, ty};
1819
use rustc_span::def_id::LOCAL_CRATE;
@@ -22,9 +23,9 @@ use stable_mir::mir::mono::{InstanceDef, StaticDef};
2223
use stable_mir::mir::{BinOp, Body, Place, UnOp};
2324
use stable_mir::target::{MachineInfo, MachineSize};
2425
use stable_mir::ty::{
25-
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef,
26-
ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, Ty,
27-
TyConst, TyKind, UintTy, VariantDef,
26+
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef,
27+
ForeignDef, ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy,
28+
Span, Ty, TyConst, TyKind, UintTy, VariantDef, VariantIdx,
2829
};
2930
use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol};
3031

@@ -447,6 +448,30 @@ impl<'tcx> SmirCtxt<'tcx> {
447448
def.internal(&mut *tables, tcx).variants().len()
448449
}
449450

451+
/// Discriminant for a given variant index of AdtDef
452+
pub fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr {
453+
let mut tables = self.0.borrow_mut();
454+
let tcx = tables.tcx;
455+
let adt = adt.internal(&mut *tables, tcx);
456+
let variant = variant.internal(&mut *tables, tcx);
457+
adt.discriminant_for_variant(tcx, variant).stable(&mut *tables)
458+
}
459+
460+
/// Discriminant for a given variand index and args of a coroutine
461+
pub fn coroutine_discr_for_variant(
462+
&self,
463+
coroutine: CoroutineDef,
464+
args: &GenericArgs,
465+
variant: VariantIdx,
466+
) -> Discr {
467+
let mut tables = self.0.borrow_mut();
468+
let tcx = tables.tcx;
469+
let coroutine = coroutine.def_id().internal(&mut *tables, tcx);
470+
let args = args.internal(&mut *tables, tcx);
471+
let variant = variant.internal(&mut *tables, tcx);
472+
args.as_coroutine().discriminant_for_variant(coroutine, tcx, variant).stable(&mut *tables)
473+
}
474+
450475
/// The name of a variant.
451476
pub fn variant_name(&self, def: VariantDef) -> Symbol {
452477
let mut tables = self.0.borrow_mut();

compiler/rustc_smir/src/rustc_smir/convert/ty.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,3 +960,11 @@ impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData {
960960
}
961961
}
962962
}
963+
964+
impl<'tcx> Stable<'tcx> for rustc_middle::ty::util::Discr<'tcx> {
965+
type T = stable_mir::ty::Discr;
966+
967+
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
968+
stable_mir::ty::Discr { val: self.val, ty: self.ty.stable(tables) }
969+
}
970+
}

compiler/rustc_smir/src/stable_mir/compiler_interface.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef};
1313
use stable_mir::mir::{BinOp, Body, Place, UnOp};
1414
use stable_mir::target::MachineInfo;
1515
use stable_mir::ty::{
16-
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef,
17-
ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics,
18-
ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl,
19-
TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef,
16+
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef,
17+
ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates,
18+
Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span,
19+
TraitDecl, TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, VariantIdx,
2020
};
2121
use stable_mir::{
2222
AssocItems, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls,
@@ -230,6 +230,21 @@ impl<'tcx> SmirInterface<'tcx> {
230230
self.cx.adt_variants_len(def)
231231
}
232232

233+
/// Discriminant for a given variant index of AdtDef
234+
pub(crate) fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr {
235+
self.cx.adt_discr_for_variant(adt, variant)
236+
}
237+
238+
/// Discriminant for a given variand index and args of a coroutine
239+
pub(crate) fn coroutine_discr_for_variant(
240+
&self,
241+
coroutine: CoroutineDef,
242+
args: &GenericArgs,
243+
variant: VariantIdx,
244+
) -> Discr {
245+
self.cx.coroutine_discr_for_variant(coroutine, args, variant)
246+
}
247+
233248
/// The name of a variant.
234249
pub(crate) fn variant_name(&self, def: VariantDef) -> Symbol {
235250
self.cx.variant_name(def)

compiler/rustc_smir/src/stable_mir/ty.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,12 @@ crate_def! {
756756
pub CoroutineDef;
757757
}
758758

759+
impl CoroutineDef {
760+
pub fn discriminant_for_variant(&self, args: &GenericArgs, idx: VariantIdx) -> Discr {
761+
with(|cx| cx.coroutine_discr_for_variant(*self, args, idx))
762+
}
763+
}
764+
759765
crate_def! {
760766
#[derive(Serialize)]
761767
pub CoroutineClosureDef;
@@ -831,6 +837,15 @@ impl AdtDef {
831837
pub fn repr(&self) -> ReprOptions {
832838
with(|cx| cx.adt_repr(*self))
833839
}
840+
841+
pub fn discriminant_for_variant(&self, idx: VariantIdx) -> Discr {
842+
with(|cx| cx.adt_discr_for_variant(*self, idx))
843+
}
844+
}
845+
846+
pub struct Discr {
847+
pub val: u128,
848+
pub ty: Ty,
834849
}
835850

836851
/// Definition of a variant, which can be either a struct / union field or an enum variant.
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
//@ run-pass
2+
//! Test that users are able to use stable mir APIs to retrieve
3+
//! discriminant value and type for AdtDef and Coroutine variants
4+
5+
//@ ignore-stage1
6+
//@ ignore-cross-compile
7+
//@ ignore-remote
8+
//@ edition: 2024
9+
10+
#![feature(rustc_private)]
11+
#![feature(assert_matches)]
12+
13+
extern crate rustc_middle;
14+
#[macro_use]
15+
extern crate rustc_smir;
16+
extern crate rustc_driver;
17+
extern crate rustc_interface;
18+
extern crate stable_mir;
19+
20+
use std::io::Write;
21+
use std::ops::ControlFlow;
22+
23+
use stable_mir::CrateItem;
24+
use stable_mir::crate_def::CrateDef;
25+
use stable_mir::mir::{AggregateKind, Rvalue, Statement, StatementKind};
26+
use stable_mir::ty::{IntTy, RigidTy, Ty};
27+
28+
const CRATE_NAME: &str = "crate_variant_ty";
29+
30+
/// Test if we can retrieve discriminant info for different types.
31+
fn test_def_tys() -> ControlFlow<()> {
32+
check_adt_mono();
33+
check_adt_poly();
34+
check_adt_poly2();
35+
36+
ControlFlow::Continue(())
37+
}
38+
39+
fn check_adt_mono() {
40+
let mono = get_fn("mono").expect_body();
41+
42+
check_statement_is_aggregate_assign(
43+
&mono.blocks[0].statements[0],
44+
0,
45+
RigidTy::Int(IntTy::Isize),
46+
);
47+
check_statement_is_aggregate_assign(
48+
&mono.blocks[1].statements[0],
49+
1,
50+
RigidTy::Int(IntTy::Isize),
51+
);
52+
check_statement_is_aggregate_assign(
53+
&mono.blocks[2].statements[0],
54+
2,
55+
RigidTy::Int(IntTy::Isize),
56+
);
57+
}
58+
59+
fn check_adt_poly() {
60+
let poly = get_fn("poly").expect_body();
61+
62+
check_statement_is_aggregate_assign(
63+
&poly.blocks[0].statements[0],
64+
0,
65+
RigidTy::Int(IntTy::Isize),
66+
);
67+
check_statement_is_aggregate_assign(
68+
&poly.blocks[1].statements[0],
69+
1,
70+
RigidTy::Int(IntTy::Isize),
71+
);
72+
check_statement_is_aggregate_assign(
73+
&poly.blocks[2].statements[0],
74+
2,
75+
RigidTy::Int(IntTy::Isize),
76+
);
77+
}
78+
79+
fn check_adt_poly2() {
80+
let poly = get_fn("poly2").expect_body();
81+
82+
check_statement_is_aggregate_assign(
83+
&poly.blocks[0].statements[0],
84+
0,
85+
RigidTy::Int(IntTy::Isize),
86+
);
87+
check_statement_is_aggregate_assign(
88+
&poly.blocks[1].statements[0],
89+
1,
90+
RigidTy::Int(IntTy::Isize),
91+
);
92+
check_statement_is_aggregate_assign(
93+
&poly.blocks[2].statements[0],
94+
2,
95+
RigidTy::Int(IntTy::Isize),
96+
);
97+
}
98+
99+
fn get_fn(name: &str) -> CrateItem {
100+
stable_mir::all_local_items().into_iter().find(|it| it.name().eq(name)).unwrap()
101+
}
102+
103+
fn check_statement_is_aggregate_assign(
104+
statement: &Statement,
105+
expected_discr_val: u128,
106+
expected_discr_ty: RigidTy,
107+
) {
108+
if let Statement { kind: StatementKind::Assign(_, rvalue), .. } = statement
109+
&& let Rvalue::Aggregate(aggregate, _) = rvalue
110+
&& let AggregateKind::Adt(adt_def, variant_idx, ..) = aggregate
111+
{
112+
let discr = adt_def.discriminant_for_variant(*variant_idx);
113+
114+
assert_eq!(discr.val, expected_discr_val);
115+
assert_eq!(discr.ty, Ty::from_rigid_kind(expected_discr_ty));
116+
} else {
117+
unreachable!("Unexpected statement");
118+
}
119+
}
120+
121+
/// This test will generate and analyze a dummy crate using the stable mir.
122+
/// For that, it will first write the dummy crate into a file.
123+
/// Then it will create a `StableMir` using custom arguments and then
124+
/// it will run the compiler.
125+
fn main() {
126+
let path = "defs_ty_input.rs";
127+
generate_input(&path).unwrap();
128+
let args = &[
129+
"rustc".to_string(),
130+
"-Cpanic=abort".to_string(),
131+
"--crate-name".to_string(),
132+
CRATE_NAME.to_string(),
133+
path.to_string(),
134+
];
135+
run!(args, test_def_tys).unwrap();
136+
}
137+
138+
fn generate_input(path: &str) -> std::io::Result<()> {
139+
let mut file = std::fs::File::create(path)?;
140+
write!(
141+
file,
142+
r#"
143+
use std::hint::black_box;
144+
145+
enum Mono {{
146+
A,
147+
B(i32),
148+
C {{ a: i32, b: u32 }},
149+
}}
150+
151+
enum Poly<T> {{
152+
A,
153+
B(T),
154+
C {{ t: T }},
155+
}}
156+
157+
pub fn main() {{
158+
mono();
159+
poly();
160+
poly2::<i32>(1);
161+
}}
162+
163+
fn mono() {{
164+
black_box(Mono::A);
165+
black_box(Mono::B(6));
166+
black_box(Mono::C {{a: 1, b: 10 }});
167+
}}
168+
169+
fn poly() {{
170+
black_box(Poly::<i32>::A);
171+
black_box(Poly::B(1i32));
172+
black_box(Poly::C {{ t: 1i32 }});
173+
}}
174+
175+
fn poly2<T: Copy>(t: T) {{
176+
black_box(Poly::<T>::A);
177+
black_box(Poly::B(t));
178+
black_box(Poly::C {{ t: t }});
179+
}}
180+
"#
181+
)?;
182+
Ok(())
183+
}

0 commit comments

Comments
 (0)