Skip to content

Commit 4ec0ba9

Browse files
committed
Auto merge of #55716 - RalfJung:escape-to-raw, r=oli-obk
Add escape-to-raw MIR statement Add a new MIR "ghost state statement": Escaping a ptr to permit raw accesses. ~~This includes #55549, [click here](RalfJung/rust@miri-visitor...RalfJung:escape-to-raw) for just the new commits.~~
2 parents 7d3b9b1 + b891a81 commit 4ec0ba9

31 files changed

+267
-163
lines changed

src/librustc/ich/impls_mir.rs

+3
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ for mir::StatementKind<'gcx> {
220220
mir::StatementKind::EndRegion(ref region_scope) => {
221221
region_scope.hash_stable(hcx, hasher);
222222
}
223+
mir::StatementKind::EscapeToRaw(ref place) => {
224+
place.hash_stable(hcx, hasher);
225+
}
223226
mir::StatementKind::Retag { fn_entry, ref place } => {
224227
fn_entry.hash_stable(hcx, hasher);
225228
place.hash_stable(hcx, hasher);

src/librustc/mir/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1782,6 +1782,13 @@ pub enum StatementKind<'tcx> {
17821782
place: Place<'tcx>,
17831783
},
17841784

1785+
/// Escape the given reference to a raw pointer, so that it can be accessed
1786+
/// without precise provenance tracking. These statements are currently only interpreted
1787+
/// by miri and only generated when "-Z mir-emit-retag" is passed.
1788+
/// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
1789+
/// for more details.
1790+
EscapeToRaw(Operand<'tcx>),
1791+
17851792
/// Mark one terminating point of a region scope (i.e. static region).
17861793
/// (The starting point(s) arise implicitly from borrows.)
17871794
EndRegion(region::Scope),
@@ -1843,6 +1850,7 @@ impl<'tcx> Debug for Statement<'tcx> {
18431850
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
18441851
Retag { fn_entry, ref place } =>
18451852
write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place),
1853+
EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place),
18461854
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
18471855
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
18481856
SetDiscriminant {
@@ -3019,6 +3027,7 @@ EnumTypeFoldableImpl! {
30193027
(StatementKind::StorageDead)(a),
30203028
(StatementKind::InlineAsm) { asm, outputs, inputs },
30213029
(StatementKind::Retag) { fn_entry, place },
3030+
(StatementKind::EscapeToRaw)(place),
30223031
(StatementKind::EndRegion)(a),
30233032
(StatementKind::AscribeUserType)(a, v, b),
30243033
(StatementKind::Nop),

src/librustc/mir/visit.rs

+4-1
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

+2-1
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

+1
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
599599
StatementKind::Nop
600600
| StatementKind::AscribeUserType(..)
601601
| StatementKind::Retag { .. }
602+
| StatementKind::EscapeToRaw { .. }
602603
| StatementKind::StorageLive(..) => {
603604
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
604605
// to borrow check.

src/librustc_mir/borrow_check/nll/invalidation.rs

+1
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

+3-2
Original file line numberDiff line numberDiff line change
@@ -1311,11 +1311,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
13111311
}
13121312
}
13131313
StatementKind::FakeRead(..)
1314-
| StatementKind::StorageLive(_)
1315-
| StatementKind::StorageDead(_)
1314+
| StatementKind::StorageLive(..)
1315+
| StatementKind::StorageDead(..)
13161316
| StatementKind::InlineAsm { .. }
13171317
| StatementKind::EndRegion(_)
13181318
| StatementKind::Retag { .. }
1319+
| StatementKind::EscapeToRaw { .. }
13191320
| StatementKind::Nop => {}
13201321
}
13211322
}

src/librustc_mir/build/expr/as_place.rs

+3
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
8686
// region_scope=None so place indexes live forever. They are scalars so they
8787
// do not need storage annotations, and they are often copied between
8888
// places.
89+
// Making this a *fresh* temporary also means we do not have to worry about
90+
// the index changing later: Nothing will ever change this temporary.
91+
// The "retagging" transformation (for Stacked Borrows) relies on this.
8992
let idx = unpack!(block = this.as_temp(block, None, index, Mutability::Mut));
9093

9194
// bounds check:

src/librustc_mir/const_eval.rs

-1
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,6 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
351351
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
352352

353353
const STATIC_KIND: Option<!> = None; // no copying of statics allowed
354-
const ENABLE_PTR_TRACKING_HOOKS: bool = false; // we don't have no provenance
355354

356355
#[inline(always)]
357356
fn enforce_validity(_ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool {

src/librustc_mir/dataflow/impls/borrows.rs

+1
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

+2-1
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

+7-20
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/intrinsics.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -201,18 +201,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
201201
} else if Some(def_id) == self.tcx.lang_items().panic_fn() {
202202
assert!(args.len() == 1);
203203
// &(&'static str, &'static str, u32, u32)
204-
let ptr = self.read_immediate(args[0])?;
205-
let place = self.ref_to_mplace(ptr)?;
204+
let place = self.deref_operand(args[0])?;
206205
let (msg, file, line, col) = (
207206
self.mplace_field(place, 0)?,
208207
self.mplace_field(place, 1)?,
209208
self.mplace_field(place, 2)?,
210209
self.mplace_field(place, 3)?,
211210
);
212211

213-
let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?;
212+
let msg_place = self.deref_operand(msg.into())?;
214213
let msg = Symbol::intern(self.read_str(msg_place)?);
215-
let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?;
214+
let file_place = self.deref_operand(file.into())?;
216215
let file = Symbol::intern(self.read_str(file_place)?);
217216
let line = self.read_scalar(line.into())?.to_u32()?;
218217
let col = self.read_scalar(col.into())?.to_u32()?;
@@ -221,17 +220,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
221220
assert!(args.len() == 2);
222221
// &'static str, &(&'static str, u32, u32)
223222
let msg = args[0];
224-
let ptr = self.read_immediate(args[1])?;
225-
let place = self.ref_to_mplace(ptr)?;
223+
let place = self.deref_operand(args[1])?;
226224
let (file, line, col) = (
227225
self.mplace_field(place, 0)?,
228226
self.mplace_field(place, 1)?,
229227
self.mplace_field(place, 2)?,
230228
);
231229

232-
let msg_place = self.ref_to_mplace(self.read_immediate(msg.into())?)?;
230+
let msg_place = self.deref_operand(msg.into())?;
233231
let msg = Symbol::intern(self.read_str(msg_place)?);
234-
let file_place = self.ref_to_mplace(self.read_immediate(file.into())?)?;
232+
let file_place = self.deref_operand(file.into())?;
235233
let file = Symbol::intern(self.read_str(file_place)?);
236234
let line = self.read_scalar(line.into())?.to_u32()?;
237235
let col = self.read_scalar(col.into())?.to_u32()?;

src/librustc_mir/interpret/machine.rs

+10-18
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,6 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
9595
/// that is added to the memory so that the work is not done twice.
9696
const STATIC_KIND: Option<Self::MemoryKinds>;
9797

98-
/// As an optimization, you can prevent the pointer tracking hooks from ever being
99-
/// called. You should only do this if you do not care about provenance tracking.
100-
/// This controls the `tag_reference` and `tag_dereference` hooks.
101-
const ENABLE_PTR_TRACKING_HOOKS: bool;
102-
10398
/// Whether to enforce the validity invariant
10499
fn enforce_validity(ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool;
105100

@@ -181,18 +176,6 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
181176
kind: MemoryKind<Self::MemoryKinds>,
182177
) -> EvalResult<'tcx, Pointer<Self::PointerTag>>;
183178

184-
/// Executed when evaluating the `&` operator: Creating a new reference.
185-
/// This has the chance to adjust the tag. It should not change anything else!
186-
/// `mutability` can be `None` in case a raw ptr is being created.
187-
#[inline]
188-
fn tag_reference(
189-
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
190-
place: MPlaceTy<'tcx, Self::PointerTag>,
191-
_mutability: Option<hir::Mutability>,
192-
) -> EvalResult<'tcx, Scalar<Self::PointerTag>> {
193-
Ok(place.ptr)
194-
}
195-
196179
/// Executed when evaluating the `*` operator: Following a reference.
197180
/// This has the chance to adjust the tag. It should not change anything else!
198181
/// `mutability` can be `None` in case a raw ptr is being dereferenced.
@@ -205,7 +188,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
205188
Ok(place.ptr)
206189
}
207190

208-
/// Execute a validation operation
191+
/// Execute a retagging operation
209192
#[inline]
210193
fn retag(
211194
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
@@ -214,4 +197,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
214197
) -> EvalResult<'tcx> {
215198
Ok(())
216199
}
200+
201+
/// Execute an escape-to-raw operation
202+
#[inline]
203+
fn escape_to_raw(
204+
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
205+
_ptr: OpTy<'tcx, Self::PointerTag>,
206+
) -> EvalResult<'tcx> {
207+
Ok(())
208+
}
217209
}

src/librustc_mir/interpret/operand.rs

-11
Original file line numberDiff line numberDiff line change
@@ -431,17 +431,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
431431
})
432432
}
433433

434-
// Take an operand, representing a pointer, and dereference it to a place -- that
435-
// will always be a MemPlace.
436-
pub(super) fn deref_operand(
437-
&self,
438-
src: OpTy<'tcx, M::PointerTag>,
439-
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
440-
let val = self.read_immediate(src)?;
441-
trace!("deref to {} on {:?}", val.layout.ty, *val);
442-
Ok(self.ref_to_mplace(val)?)
443-
}
444-
445434
pub fn operand_projection(
446435
&self,
447436
base: OpTy<'tcx, M::PointerTag>,

0 commit comments

Comments
 (0)