8000 Add escape-to-raw MIR statement by RalfJung · Pull Request #55716 · rust-lang/rust · GitHub
[go: up one dir, main page]

Skip to content

Add escape-to-raw MIR statement #55716

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 15, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
array index accesses are stable places
  • Loading branch information
RalfJung committed Nov 7, 2018
commit f174099885fed58c8053cf02bf353b6822897b75
3 changes: 3 additions & 0 deletions src/librustc_mir/build/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// region_scope=None so place indexes live forever. They are scalars so they
// do not need storage annotations, and they are often copied between
// places.
// Making this a *fresh* temporary also means we do not have to worry about
// the index changing later: Nothing will ever change this temporary.
// The "retagging" transformation (for Stacked Borrows) relies on this.
let idx = unpack!(block = this.as_temp(block, None, index, Mutability::Mut));

// bounds check:
Expand Down
14 changes: 8 additions & 6 deletions src/librustc_mir/transform/add_retag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,19 @@ fn is_stable<'tcx>(
// Recurse for projections
Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref |
ProjectionElem::Index(_) =>
// Which place these point to depends on external circumstances
// (a local storing the array index, the current value of
// the projection base), so we stop tracking here.
// Which place this evaluates to can change with any memory write,
// so cannot assume this to be stable.
ProjectionElem::Deref =>
false,
// Array indices are intersting, but MIR building generates a *fresh*
// temporary for every array access, so the index cannot be changed as
// a side-effect.
ProjectionElem::Index { .. } |
// The rest is completely boring, they just offset by a constant.
ProjectionElem::Field { .. } |
ProjectionElem::ConstantIndex { .. } |
ProjectionElem::Subslice { .. } |
ProjectionElem::Downcast { .. } =>
// These just offset by a constant, entirely independent of everything else.
is_stable(&proj.base),
}
}
Expand Down
43 changes: 43 additions & 0 deletions src/test/mir-opt/array-index-is-temporary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Retagging (from Stacked Borrows) relies on the array index being a fresh
// temporary, so that side-effects cannot change it.
// Test that this is indeed the case.

unsafe fn foo(z: *mut usize) -> u32 {
*z = 2;
99
}

fn main() {
let mut x = [42, 43, 44];
let mut y = 1;
let z: *mut usize = &mut y;
x[y] = unsafe { foo(z) };
}

// END RUST SOURCE
// START rustc.main.EraseRegions.after.mir
// bb0: {
// ...
// _6 = &mut _2;
// _5 = &mut (*_6);
// _4 = move _5 as *mut usize (Misc);
// _3 = move _4;
// ...
// _8 = _3;
// _7 = const foo(move _8) -> bb1;
// }
//
// bb1: {
// ...
// _9 = _2;
// _10 = Len(_1);
// _11 = Lt(_9, _10);
// assert(move _11, "index out of bounds: the len is move _10 but the index is _9") -> bb2;
// }
//
// bb2: {
// _1[_9] = move _7;
// ...
// return;
// }
// END rustc.main.EraseRegions.after.mir
0