Skip to content

Commit 4c0332b

Browse files
authored
Rollup merge of rust-lang#115532 - oli-obk:smir_folder, r=compiler-errors
Implement SMIR generic parameter instantiation Also demonstrates the use of it with a test. This required a few smaller changes that may conflict with `@ericmarkmartin` work, but should be easy to resolve any conflicts on my end if their stuff lands first.
2 parents f3ac73d + c1e449c commit 4c0332b

File tree

7 files changed

+434
-40
lines changed

7 files changed

+434
-40
lines changed

compiler/rustc_smir/src/rustc_smir/mod.rs

+67-22
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ impl<'tcx> Context for Tables<'tcx> {
7777
impl_trait.stable(self)
7878
}
7979

80-
fn mir_body(&mut self, item: &stable_mir::CrateItem) -> stable_mir::mir::Body {
81-
let def_id = self[item.0];
80+
fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body {
81+
let def_id = self[item];
8282
let mir = self.tcx.optimized_mir(def_id);
8383
stable_mir::mir::Body {
8484
blocks: mir
@@ -102,8 +102,13 @@ impl<'tcx> Context for Tables<'tcx> {
102102
}
103103

104104
fn ty_kind(&mut self, ty: crate::stable_mir::ty::Ty) -> TyKind {
105-
let ty = self.types[ty.0];
106-
ty.stable(self)
105+
self.types[ty.0].clone().stable(self)
106+
}
107+
108+
fn mk_ty(&mut self, kind: TyKind) -> stable_mir::ty::Ty {
109+
let n = self.types.len();
110+
self.types.push(MaybeStable::Stable(kind));
111+
stable_mir::ty::Ty(n)
107112
}
108113

109114
fn generics_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
@@ -127,20 +132,47 @@ impl<'tcx> Context for Tables<'tcx> {
127132
}
128133
}
129134

135+
#[derive(Clone)]
136+
pub enum MaybeStable<S, R> {
137+
Stable(S),
138+
Rustc(R),
139+
}
140+
141+
impl<'tcx, S, R> MaybeStable<S, R> {
142+
fn stable(self, tables: &mut Tables<'tcx>) -> S
143+
where
144+
R: Stable<'tcx, T = S>,
145+
{
146+
match self {
147+
MaybeStable::Stable(s) => s,
148+
MaybeStable::Rustc(r) => r.stable(tables),
149+
}
150+
}
151+
}
152+
153+
impl<S, R: PartialEq> PartialEq<R> for MaybeStable<S, R> {
154+
fn eq(&self, other: &R) -> bool {
155+
match self {
156+
MaybeStable::Stable(_) => false,
157+
MaybeStable::Rustc(r) => r == other,
158+
}
159+
}
160+
}
161+
130162
pub struct Tables<'tcx> {
131163
pub tcx: TyCtxt<'tcx>,
132164
pub def_ids: Vec<DefId>,
133165
pub alloc_ids: Vec<AllocId>,
134-
pub types: Vec<Ty<'tcx>>,
166+
pub types: Vec<MaybeStable<stable_mir::ty::TyKind, Ty<'tcx>>>,
135167
}
136168

137169
impl<'tcx> Tables<'tcx> {
138170
fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty {
139-
if let Some(id) = self.types.iter().position(|&t| t == ty) {
171+
if let Some(id) = self.types.iter().position(|t| *t == ty) {
140172
return stable_mir::ty::Ty(id);
141173
}
142174
let id = self.types.len();
143-
self.types.push(ty);
175+
self.types.push(MaybeStable::Rustc(ty));
144176
stable_mir::ty::Ty(id)
145177
}
146178
}
@@ -1096,25 +1128,33 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
10961128
tables,
10971129
))
10981130
}
1099-
ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(&param)),
1131+
ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
11001132
ty::ErrorCt(_) => unreachable!(),
11011133
ty::InferCt(_) => unreachable!(),
11021134
ty::BoundCt(_, _) => unimplemented!(),
11031135
ty::PlaceholderCt(_) => unimplemented!(),
11041136
ty::Unevaluated(uv) => {
11051137
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
1106-
ty: tables.intern_ty(self.ty()),
11071138
def: tables.const_def(uv.def),
11081139
args: uv.args.stable(tables),
11091140
promoted: None,
11101141
})
11111142
}
11121143
ty::ExprCt(_) => unimplemented!(),
11131144
},
1145+
ty: tables.intern_ty(self.ty()),
11141146
}
11151147
}
11161148
}
11171149

1150+
impl<'tcx> Stable<'tcx> for ty::ParamConst {
1151+
type T = stable_mir::ty::ParamConst;
1152+
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
1153+
use stable_mir::ty::ParamConst;
1154+
ParamConst { index: self.index, name: self.name.to_string() }
1155+
}
1156+
}
1157+
11181158
impl<'tcx> Stable<'tcx> for ty::ParamTy {
11191159
type T = stable_mir::ty::ParamTy;
11201160
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
@@ -1183,22 +1223,27 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
11831223
}
11841224

11851225
impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
1186-
type T = stable_mir::ty::ConstantKind;
1226+
type T = stable_mir::ty::Const;
11871227

11881228
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
11891229
match *self {
1190-
ConstantKind::Ty(c) => c.stable(tables).literal,
1191-
ConstantKind::Unevaluated(unev_const, ty) => {
1192-
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
1193-
ty: tables.intern_ty(ty),
1194-
def: tables.const_def(unev_const.def),
1195-
args: unev_const.args.stable(tables),
1196-
promoted: unev_const.promoted.map(|u| u.as_u32()),
1197-
})
1198-
}
1199-
ConstantKind::Val(val, ty) => {
1200-
stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(ty, val, tables))
1201-
}
1230+
ConstantKind::Ty(c) => c.stable(tables),
1231+
ConstantKind::Unevaluated(unev_const, ty) => stable_mir::ty::Const {
1232+
literal: stable_mir::ty::ConstantKind::Unevaluated(
1233+
stable_mir::ty::UnevaluatedConst {
1234+
def: tables.const_def(unev_const.def),
1235+
args: unev_const.args.stable(tables),
1236+
promoted: unev_const.promoted.map(|u| u.as_u32()),
1237+
},
1238+
),
1239+
ty: tables.intern_ty(ty),
1240+
},
1241+
ConstantKind::Val(val, ty) => stable_mir::ty::Const {
1242+
literal: stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
1243+
ty, val, tables,
1244+
)),
1245+
ty: tables.intern_ty(ty),
1246+
},
12021247
}
12031248
}
12041249
}
+230
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
use std::ops::ControlFlow;
2+
3+
use crate::rustc_internal::Opaque;
4+
5+
use super::ty::{
6+
Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind,
7+
GenericArgs, Promoted, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst,
8+
};
9+
10+
pub trait Folder: Sized {
11+
type Break;
12+
fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
13+
ty.super_fold(self)
14+
}
15+
fn fold_const(&mut self, c: &Const) -> ControlFlow<Self::Break, Const> {
16+
c.super_fold(self)
17+
}
18+
}
19+
20+
pub trait Foldable: Sized + Clone {
21+
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
22+
self.super_fold(folder)
23+
}
24+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self>;
25+
}
26+
27+
impl Foldable for Ty {
28+
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
29+
folder.visit_ty(self)
30+
}
31+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
32+
let mut kind = self.kind();
33+
match &mut kind {
34+
super::ty::TyKind::RigidTy(ty) => *ty = ty.fold(folder)?,
35+
super::ty::TyKind::Alias(_, alias) => alias.args = alias.args.fold(folder)?,
36+
super::ty::TyKind::Param(_) => {}
37+
super::ty::TyKind::Bound(_, _) => {}
38+
}
39+
ControlFlow::Continue(kind.into())
40+
}
41+
}
42+
43+
impl Foldable for Const {
44+
fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
45+
folder.fold_const(self)
46+
}
47+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
48+
let mut this = self.clone();
49+
match &mut this.literal {
50+
super::ty::ConstantKind::Allocated(alloc) => *alloc = alloc.fold(folder)?,
51+
super::ty::ConstantKind::Unevaluated(uv) => *uv = uv.fold(folder)?,
52+
super::ty::ConstantKind::Param(_) => {}
53+
}
54+
this.ty = this.ty.fold(folder)?;
55+
ControlFlow::Continue(this)
56+
}
57+
}
58+
59+
impl Foldable for Opaque {
60+
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
61+
ControlFlow::Continue(self.clone())
62+
}
63+
}
64+
65+
impl Foldable for Allocation {
66+
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
67+
ControlFlow::Continue(self.clone())
68+
}
69+
}
70+
71+
impl Foldable for UnevaluatedConst {
72+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
73+
let UnevaluatedConst { def, args, promoted } = self;
74+
ControlFlow::Continue(UnevaluatedConst {
75+
def: def.fold(folder)?,
76+
args: args.fold(folder)?,
77+
promoted: promoted.fold(folder)?,
78+
})
79+
}
80+
}
81+
82+
impl Foldable for ConstDef {
83+
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
84+
ControlFlow::Continue(self.clone())
85+
}
86+
}
87+
88+
impl<T: Foldable> Foldable for Option<T> {
89+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
90+
ControlFlow::Continue(match self {
91+
Some(val) => Some(val.fold(folder)?),
92+
None => None,
93+
})
94+
}
95+
}
96+
97+
impl Foldable for Promoted {
98+
fn super_fold<V: Folder>(&self, _folder: &mut V) -> ControlFlow<V::Break, Self> {
99+
ControlFlow::Continue(self.clone())
100+
}
101+
}
102+
103+
impl Foldable for GenericArgs {
104+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
105+
ControlFlow::Continue(GenericArgs(self.0.fold(folder)?))
106+
}
107+
}
108+
109+
impl Foldable for GenericArgKind {
110+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
111+
let mut this = self.clone();
112+
match &mut this {
113+
GenericArgKind::Lifetime(lt) => *lt = lt.fold(folder)?,
114+
GenericArgKind::Type(t) => *t = t.fold(folder)?,
115+
GenericArgKind::Const(c) => *c = c.fold(folder)?,
116+
}
117+
ControlFlow::Continue(this)
118+
}
119+
}
120+
121+
impl Foldable for RigidTy {
122+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
123+
let mut this = self.clone();
124+
match &mut this {
125+
RigidTy::Bool
126+
| RigidTy::Char
127+
| RigidTy::Int(_)
128+
| RigidTy::Uint(_)
129+
| RigidTy::Float(_)
130+
| RigidTy::Never
131+
| RigidTy::Foreign(_)
132+
| RigidTy::Str => {}
133+
RigidTy::Array(t, c) => {
134+
*t = t.fold(folder)?;
135+
*c = c.fold(folder)?;
136+
}
137+
RigidTy::Slice(inner) => *inner = inner.fold(folder)?,
138+
RigidTy::RawPtr(ty, _) => *ty = ty.fold(folder)?,
139+
RigidTy::Ref(_, ty, _) => *ty = ty.fold(folder)?,
140+
RigidTy::FnDef(_, args) => *args = args.fold(folder)?,
141+
RigidTy::FnPtr(sig) => *sig = sig.fold(folder)?,
142+
RigidTy::Closure(_, args) => *args = args.fold(folder)?,
143+
RigidTy::Generator(_, args, _) => *args = args.fold(folder)?,
144+
RigidTy::Dynamic(pred, r, _) => {
145+
*pred = pred.fold(folder)?;
146+
*r = r.fold(folder)?;
147+
}
148+
RigidTy::Tuple(fields) => *fields = fields.fold(folder)?,
149+
RigidTy::Adt(_, args) => *args = args.fold(folder)?,
150+
}
151+
ControlFlow::Continue(this)
152+
}
153+
}
154+
155+
impl<T: Foldable> Foldable for Vec<T> {
156+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
157+
let mut this = self.clone();
158+
for arg in &mut this {
159+
*arg = arg.fold(folder)?;
160+
}
161+
ControlFlow::Continue(this)
162+
}
163+
}
164+
165+
impl<T: Foldable> Foldable for Binder<T> {
166+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
167+
ControlFlow::Continue(Self {
168+
value: self.value.fold(folder)?,
169+
bound_vars: self.bound_vars.clone(),
170+
})
171+
}
172+
}
173+
174+
impl Foldable for ExistentialPredicate {
175+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
176+
let mut this = self.clone();
177+
match &mut this {
178+
ExistentialPredicate::Trait(tr) => tr.generic_args = tr.generic_args.fold(folder)?,
179+
ExistentialPredicate::Projection(p) => {
180+
p.term = p.term.fold(folder)?;
181+
p.generic_args = p.generic_args.fold(folder)?;
182+
}
183+
ExistentialPredicate::AutoTrait(_) => {}
184+
}
185+
ControlFlow::Continue(this)
186+
}
187+
}
188+
189+
impl Foldable for TermKind {
190+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
191+
ControlFlow::Continue(match self {
192+
TermKind::Type(t) => TermKind::Type(t.fold(folder)?),
193+
TermKind::Const(c) => TermKind::Const(c.fold(folder)?),
194+
})
195+
}
196+
}
197+
198+
impl Foldable for FnSig {
199+
fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
200+
ControlFlow::Continue(Self {
201+
inputs_and_output: self.inputs_and_output.fold(folder)?,
202+
c_variadic: self.c_variadic,
203+
unsafety: self.unsafety,
204+
abi: self.abi.clone(),
205+
})
206+
}
207+
}
208+
209+
pub enum Never {}
210+
211+
/// In order to instantiate a `Foldable`'s generic parameters with specific arguments,
212+
/// `GenericArgs` can be used as a `Folder` that replaces all mentions of generic params
213+
/// with the entries in its list.
214+
impl Folder for GenericArgs {
215+
type Break = Never;
216+
217+
fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
218+
ControlFlow::Continue(match ty.kind() {
219+
TyKind::Param(p) => self[p],
220+
_ => *ty,
221+
})
222+
}
223+
224+
fn fold_const(&mut self, c: &Const) -> ControlFlow<Self::Break, Const> {
225+
ControlFlow::Continue(match &c.literal {
226+
ConstantKind::Param(p) => self[p.clone()].clone(),
227+
_ => c.clone(),
228+
})
229+
}
230+
}

0 commit comments

Comments
 (0)