Skip to content

Commit f27cd60

Browse files
committed
no more action on ref or cast, but add new MIR statement for escaping a ptr to raw
1 parent 8315b11 commit f27cd60

File tree

23 files changed

+159
-110
lines changed

23 files changed

+159
-110
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ for mir::StatementKind<'gcx> {
257257
mir::StatementKind::EndRegion(ref region_scope) => {
258258
region_scope.hash_stable(hcx, hasher);
259259
}
260+
mir::StatementKind::EscapeToRaw(ref place) => {
261+
place.hash_stable(hcx, hasher);
262+
}
260263
mir::StatementKind::Retag { fn_entry, ref place } => {
261264
fn_entry.hash_stable(hcx, hasher);
262265
place.hash_stable(hcx, hasher);

src/librustc/mir/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,13 @@ pub enum StatementKind<'tcx> {
17661766
place: Place<'tcx>,
17671767
},
17681768

1769+
/// Escape the given reference to a raw pointer, so that it can be accessed
1770+
/// without precise provenance tracking. These statements are currently only interpreted
1771+
/// by miri and only generated when "-Z mir-emit-retag" is passed.
1772+
/// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
1773+
/// for more details.
1774+
EscapeToRaw(Operand<'tcx>),
1775+
17691776
/// Mark one terminating point of a region scope (i.e. static region).
17701777
/// (The starting point(s) arise implicitly from borrows.)
17711778
EndRegion(region::Scope),
@@ -1827,6 +1834,7 @@ impl<'tcx> Debug for Statement<'tcx> {
18271834
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
18281835
Retag { fn_entry, ref place } =>
18291836
write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place),
1837+
EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place),
18301838
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
18311839
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
18321840
SetDiscriminant {
@@ -2968,6 +2976,7 @@ EnumTypeFoldableImpl! {
29682976
(StatementKind::StorageDead)(a),
29692977
(StatementKind::InlineAsm) { asm, outputs, inputs },
29702978
(StatementKind::Retag) { fn_entry, place },
2979+
(StatementKind::EscapeToRaw)(place),
29712980
(StatementKind::EndRegion)(a),
29722981
(StatementKind::AscribeUserType)(a, v, b),
29732982
(StatementKind::Nop),

src/librustc/mir/visit.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,9 @@ macro_rules! make_mir_visitor {
385385
location
386386
);
387387
}
388+
StatementKind::EscapeToRaw(ref $($mutability)* op) => {
389+
self.visit_operand(op, location);
390+
}
388391
StatementKind::StorageLive(ref $($mutability)* local) => {
389392
self.visit_local(
390393
local,
@@ -1022,7 +1025,7 @@ pub enum MutatingUseContext<'tcx> {
10221025
/// f(&mut x.y);
10231026
///
10241027
Projection,
1025-
/// Retagging (updating the "Stacked Borrows" tag)
1028+
/// Retagging, a "Stacked Borrows" shadow state operation
10261029
Retag,
10271030
}
10281031

src/librustc_codegen_llvm/mir/statement.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,9 @@ impl FunctionCx<'a, 'll, 'tcx> {
105105
bx
106106
}
107107
mir::StatementKind::FakeRead(..) |
108-
mir::StatementKind::EndRegion(_) |
108+
mir::StatementKind::EndRegion(..) |
109109
mir::StatementKind::Retag { .. } |
110+
mir::StatementKind::EscapeToRaw { .. } |
110111
mir::StatementKind::AscribeUserType(..) |
111112
mir::StatementKind::Nop => bx,
112113
}

src/librustc_mir/borrow_check/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
601601
StatementKind::Nop
602602
| StatementKind::AscribeUserType(..)
603603
| StatementKind::Retag { .. }
604+
| StatementKind::EscapeToRaw { .. }
604605
| StatementKind::StorageLive(..) => {
605606
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
606607
// to borrow check.

src/librustc_mir/borrow_check/nll/invalidation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
137137
StatementKind::Nop |
138138
StatementKind::AscribeUserType(..) |
139139
StatementKind::Retag { .. } |
140+
StatementKind::EscapeToRaw { .. } |
140141
StatementKind::StorageLive(..) => {
141142
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
142143
// to borrow check.

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,11 +1290,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
12901290
}
12911291
}
12921292
StatementKind::FakeRead(..)
1293-
| StatementKind::StorageLive(_)
1294-
| StatementKind::StorageDead(_)
1293+
| StatementKind::StorageLive(..)
1294+
| StatementKind::StorageDead(..)
12951295
| StatementKind::InlineAsm { .. }
12961296
| StatementKind::EndRegion(_)
12971297
| StatementKind::Retag { .. }
1298+
| StatementKind::EscapeToRaw { .. }
12981299
| StatementKind::Nop => {}
12991300
}
13001301
}

src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
339339
mir::StatementKind::SetDiscriminant { .. } |
340340
mir::StatementKind::StorageLive(..) |
341341
mir::StatementKind::Retag { .. } |
342+
mir::StatementKind::EscapeToRaw { .. } |
342343
mir::StatementKind::AscribeUserType(..) |
343344
mir::StatementKind::Nop => {}
344345

src/librustc_mir/dataflow/move_paths/builder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
301301
span_bug!(stmt.source_info.span,
302302
"SetDiscriminant should not exist during borrowck");
303303
}
304-
StatementKind::EndRegion(_) |
304+
StatementKind::EndRegion(..) |
305305
StatementKind::Retag { .. } |
306+
StatementKind::EscapeToRaw { .. } |
306307
StatementKind::AscribeUserType(..) |
307308
StatementKind::Nop => {}
308309
}

src/librustc_mir/interpret/cast.rs

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,40 +44,28 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
4444
}
4545

4646
Misc => {
47-
let src_layout = src.layout;
4847
let src = self.read_immediate(src)?;
4948

50-
let src = if M::ENABLE_PTR_TRACKING_HOOKS && src_layout.ty.is_region_ptr() {
51-
// The only `Misc` casts on references are those creating raw pointers.
52-
assert!(dest.layout.ty.is_unsafe_ptr());
53-
// For the purpose of the "ptr tag hooks", treat this as creating
54-
// a new, raw reference.
55-
let place = self.ref_to_mplace(src)?;
56-
self.create_ref(place, None)?
57-
} else {
58-
*src
59-
};
60-
61-
if self.type_is_fat_ptr(src_layout.ty) {
62-
match (src, self.type_is_fat_ptr(dest.layout.ty)) {
49+
if self.type_is_fat_ptr(src.layout.ty) {
50+
match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
6351
// pointers to extern types
6452
(Immediate::Scalar(_),_) |
6553
// slices and trait objects to other slices/trait objects
6654
(Immediate::ScalarPair(..), true) => {
6755
// No change to immediate
68-
self.write_immediate(src, dest)?;
56+
self.write_immediate(*src, dest)?;
6957
}
7058
// slices and trait objects to thin pointers (dropping the metadata)
7159
(Immediate::ScalarPair(data, _), false) => {
7260
self.write_scalar(data, dest)?;
7361
}
7462
}
7563
} else {
76-
match src_layout.variants {
64+
match src.layout.variants {
7765
layout::Variants::Single { index } => {
78-
if let Some(def) = src_layout.ty.ty_adt_def() {
66+
if let Some(def) = src.layout.ty.ty_adt_def() {
7967
// Cast from a univariant enum
80-
assert!(src_layout.is_zst());
68+
assert!(src.layout.is_zst());
8169
let discr_val = def
8270
.discriminant_for_variant(*self.tcx, index)
8371
.val;
@@ -90,8 +78,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
9078
layout::Variants::NicheFilling { .. } => {},
9179
}
9280

93-
let src = src.to_scalar()?;
94-
let dest_val = self.cast_scalar(src, src_layout, dest.layout)?;
81+
let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
9582
self.write_scalar(dest_val, dest)?;
9683
}
9784
}

src/librustc_mir/interpret/machine.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,18 +211,6 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
211211
kind: MemoryKind<Self::MemoryKinds>,
212212
) -> EvalResult<'tcx, Pointer<Self::PointerTag>>;
213213

214-
/// Executed when evaluating the `&` operator: Creating a new reference.
215-
/// This has the chance to adjust the tag. It should not change anything else!
216-
/// `mutability` can be `None` in case a raw ptr is being created.
217-
#[inline]
218-
fn tag_reference(
219-
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
220-
place: MPlaceTy<'tcx, Self::PointerTag>,
221-
_mutability: Option<hir::Mutability>,
222-
) -> EvalResult<'tcx, Scalar<Self::PointerTag>> {
223-
Ok(place.ptr)
224-
}
225-
226214
/// Executed when evaluating the `*` operator: Following a reference.
227215
/// This has the chance to adjust the tag. It should not change anything else!
228216
/// `mutability` can be `None` in case a raw ptr is being dereferenced.
@@ -235,7 +223,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
235223
Ok(place.ptr)
236224
}
237225

238-
/// Execute a validation operation
226+
/// Execute a retagging operation
239227
#[inline]
240228
fn retag(
241229
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
@@ -244,4 +232,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
244232
) -> EvalResult<'tcx> {
245233
Ok(())
246234
}
235+
236+
/// Execute an escape-to-raw operation
237+
#[inline]
238+
fn escape_to_raw(
239+
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
240+
_ptr: OpTy<'tcx, Self::PointerTag>,
241+
) -> EvalResult<'tcx> {
242+
Ok(())
243+
}
247244
}

src/librustc_mir/interpret/place.rs

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,16 @@ impl<Tag> MemPlace<Tag> {
151151
// it now must be aligned.
152152
self.to_scalar_ptr_align().0.to_ptr()
153153
}
154+
155+
/// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space.
156+
/// This is the inverse of `ref_to_mplace`.
157+
#[inline(always)]
158+
pub fn to_ref(self) -> Immediate<Tag> {
159+
match self.meta {
160+
None => Immediate::Scalar(self.ptr.into()),
161+
Some(meta) => Immediate::ScalarPair(self.ptr.into(), meta.into()),
162+
}
163+
}
154164
}
155165

156166
impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
@@ -266,7 +276,7 @@ where
266276
M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<Tag, M::AllocExtra>)>,
267277
{
268278
/// Take a value, which represents a (thin or fat) reference, and make it a place.
269-
/// Alignment is just based on the type. This is the inverse of `create_ref`.
279+
/// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`.
270280
pub fn ref_to_mplace(
271281
&self,
272282
val: ImmTy<'tcx, M::PointerTag>,
@@ -294,24 +304,6 @@ where
294304
Ok(mplace)
295305
}
296306

297-
/// Turn a mplace into a (thin or fat) pointer, as a reference, pointing to the same space.
298-
/// This is the inverse of `ref_to_mplace`.
299-
/// `mutbl` indicates whether we are create a shared or mutable ref, or a raw pointer (`None`).
300-
pub fn create_ref(
301-
&mut self,
302-
mut place: MPlaceTy<'tcx, M::PointerTag>,
303-
mutbl: Option<hir::Mutability>,
304-
) -> EvalResult<'tcx, Immediate<M::PointerTag>> {
305-
// Pointer tag tracking might want to adjust the tag
306-
if M::ENABLE_PTR_TRACKING_HOOKS {
307-
place.mplace.ptr = M::tag_reference(self, place, mutbl)?
308-
}
309-
Ok(match place.meta {
310-
None => Immediate::Scalar(place.ptr.into()),
311-
Some(meta) => Immediate::ScalarPair(place.ptr.into(), meta.into()),
312-
})
313-
}
314-
315307
/// Offset a pointer to project to a field. Unlike place_field, this is always
316308
/// possible without allocating, so it can take &self. Also return the field's layout.
317309
/// This supports both struct and array fields.

src/librustc_mir/interpret/step.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//!
1313
//! The main entry point is the `step` method.
1414
15-
use rustc::{hir, mir};
15+
use rustc::mir;
1616
use rustc::ty::layout::LayoutOf;
1717
use rustc::mir::interpret::{EvalResult, Scalar, PointerArithmetic};
1818

@@ -118,12 +118,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
118118
// interpreter is solely intended for borrowck'ed code.
119119
FakeRead(..) => {}
120120

121-
// Retagging.
121+
// Stacked Borrows.
122122
Retag { fn_entry, ref place } => {
123123
let dest = self.eval_place(place)?;
124124
M::retag(self, fn_entry, dest)?;
125125
}
126+
EscapeToRaw(ref op) => {
127+
let op = self.eval_operand(op, None)?;
128+
M::escape_to_raw(self, op)?;
129+
}
126130

131+
// Statements we do not track.
127132
EndRegion(..) => {}
128133
AscribeUserType(..) => {}
129134

@@ -247,19 +252,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
247252
)?;
248253
}
249254

250-
Ref(_, borrow_kind, ref place) => {
255+
Ref(_, _, ref place) => {
251256
let src = self.eval_place(place)?;
252257
let val = self.force_allocation(src)?;
253-
let mutbl = match borrow_kind {
254-
mir::BorrowKind::Mut { .. } |
255-
mir::BorrowKind::Unique =>
256-
hir::MutMutable,
257-
mir::BorrowKind::Shared |
258-
mir::BorrowKind::Shallow =>
259-
hir::MutImmutable,
260-
};
261-
let val = self.create_ref(val, Some(mutbl))?;
262-
self.write_immediate(val, dest)?;
258+
self.write_immediate(val.to_ref(), dest)?;
263259
}
264260

265261
NullaryOp(mir::NullOp::Box, _) => {

src/librustc_mir/interpret/terminator.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
447447
};
448448

449449
let arg = OpTy {
450-
op: Operand::Immediate(self.create_ref(
451-
place,
452-
None // this is a "raw reference"
453-
)?),
450+
op: Operand::Immediate(place.to_ref()),
454451
layout: self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?,
455452
};
456453

0 commit comments

Comments
 (0)