Skip to content

Commit c8e471f

Browse files
committed
also allow visiting places and mplaces
1 parent 7d7bd9b commit c8e471f

File tree

1 file changed

+76
-9
lines changed

1 file changed

+76
-9
lines changed

src/librustc_mir/interpret/visitor.rs

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc::mir::interpret::{
1010
};
1111

1212
use super::{
13-
Machine, EvalContext, MPlaceTy, OpTy,
13+
Machine, EvalContext, MPlaceTy, PlaceTy, OpTy,
1414
};
1515

1616
// A thing that we can project into, and that has a layout.
@@ -21,13 +21,16 @@ pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
2121
// Get this value's layout.
2222
fn layout(&self) -> TyLayout<'tcx>;
2323

24-
// Get the underlying `MPlaceTy`, or panic if there is no such thing.
25-
fn to_mem_place(self) -> MPlaceTy<'tcx, M::PointerTag>;
24+
// Make this a `MPlaceTy`, or panic if that's not possible.
25+
fn force_allocation(
26+
self,
27+
ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
28+
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>>;
2629

27-
// Create this from an `MPlaceTy`
30+
// Create this from an `MPlaceTy`.
2831
fn from_mem_place(MPlaceTy<'tcx, M::PointerTag>) -> Self;
2932

30-
// Project to the n-th field
33+
// Project to the n-th field.
3134
fn project_field(
3235
self,
3336
ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
@@ -45,8 +48,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
4548
}
4649

4750
#[inline(always)]
48-
fn to_mem_place(self) -> MPlaceTy<'tcx, M::PointerTag> {
49-
self.to_mem_place()
51+
fn force_allocation(
52+
self,
53+
_ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
54+
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
55+
Ok(self.to_mem_place())
5056
}
5157

5258
#[inline(always)]
@@ -63,6 +69,66 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
6369
ectx.operand_field(self, field)
6470
}
6571
}
72+
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
73+
for MPlaceTy<'tcx, M::PointerTag>
74+
{
75+
#[inline(always)]
76+
fn layout(&self) -> TyLayout<'tcx> {
77+
self.layout
78+
}
79+
80+
#[inline(always)]
81+
fn force_allocation(
82+
self,
83+
_ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
84+
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
85+
Ok(self)
86+
}
87+
88+
#[inline(always)]
89+
fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
90+
mplace
91+
}
92+
93+
#[inline(always)]
94+
fn project_field(
95+
self,
96+
ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
97+
field: u64,
98+
) -> EvalResult<'tcx, Self> {
99+
ectx.mplace_field(self, field)
100+
}
101+
}
102+
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
103+
for PlaceTy<'tcx, M::PointerTag>
104+
{
105+
#[inline(always)]
106+
fn layout(&self) -> TyLayout<'tcx> {
107+
self.layout
108+
}
109+
110+
#[inline(always)]
111+
fn force_allocation(
112+
self,
113+
ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
114+
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
115+
ectx.force_allocation(self)
116+
}
117+
118+
#[inline(always)]
119+
fn from_mem_place(mplace: MPlaceTy<'tcx, M::PointerTag>) -> Self {
120+
mplace.into()
121+
}
122+
123+
#[inline(always)]
124+
fn project_field(
125+
self,
126+
ectx: &mut EvalContext<'a, 'mir, 'tcx, M>,
127+
field: u64,
128+
) -> EvalResult<'tcx, Self> {
129+
ectx.place_field(self, field)
130+
}
131+
}
66132

67133
// How to traverse a value and what to do when we are at the leaves.
68134
pub trait ValueVisitor<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: fmt::Debug {
@@ -135,7 +201,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
135201
// If it is a trait object, switch to the actual type that was used to create it.
136202
match v.layout().ty.sty {
137203
ty::Dynamic(..) => {
138-
let dest = v.value().to_mem_place(); // immediate trait objects are not a thing
204+
// immediate trait objects are not a thing
205+
let dest = v.value().force_allocation(self)?;
139206
let inner = self.unpack_dyn_trait(dest)?.1;
140207
// recurse with the inner type
141208
return v.with_field(Value::from_mem_place(inner), 0, |v| self.visit_value(v));
@@ -201,7 +268,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
201268
MPlaceTy::dangling(v.layout(), self)
202269
} else {
203270
// non-ZST array/slice/str cannot be immediate
204-
v.value().to_mem_place()
271+
v.value().force_allocation(self)?
205272
};
206273
// Now iterate over it.
207274
for (i, field) in self.mplace_array_fields(mplace)?.enumerate() {

0 commit comments

Comments
 (0)