Skip to content

Commit 87a3c1e

Browse files
committed
Auto merge of #55316 - RalfJung:retagging, r=oli-obk
Add Retagging statements This adds a `Retag` statement kind to MIR, used to perform the retagging operation from [Stacked Borrows](https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html). It also kills the old `Validate` statements that I added last year. NOTE: This includes #55270. Only [these commits are new](RalfJung/rust@stacked-borrows-ng...RalfJung:retagging).
2 parents d0c869c + d10304e commit 87a3c1e

37 files changed

+450
-922
lines changed

src/bootstrap/bin/rustc.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,15 @@ fn main() {
253253

254254
// When running miri tests, we need to generate MIR for all libraries
255255
if env::var("TEST_MIRI").ok().map_or(false, |val| val == "true") {
256+
// The flags here should be kept in sync with `add_miri_default_args`
257+
// in miri's `src/lib.rs`.
256258
cmd.arg("-Zalways-encode-mir");
257-
cmd.arg("-Zmir-emit-validate=1");
259+
// These options are preferred by miri, to be able to perform better validation,
260+
// but the bootstrap compiler might not understand them.
261+
if stage != "0" {
262+
cmd.arg("-Zmir-emit-retag");
263+
cmd.arg("-Zmir-opt-level=0");
264+
}
258265
}
259266

260267
// Force all crates compiled by this compiler to (a) be unstable and (b)

src/librustc/ich/impls_mir.rs

+3-20
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,9 @@ for mir::StatementKind<'gcx> {
257257
mir::StatementKind::EndRegion(ref region_scope) => {
258258
region_scope.hash_stable(hcx, hasher);
259259
}
260-
mir::StatementKind::Validate(ref op, ref places) => {
261-
op.hash_stable(hcx, hasher);
262-
places.hash_stable(hcx, hasher);
260+
mir::StatementKind::Retag { fn_entry, ref place } => {
261+
fn_entry.hash_stable(hcx, hasher);
262+
place.hash_stable(hcx, hasher);
263263
}
264264
mir::StatementKind::AscribeUserType(ref place, ref variance, ref c_ty) => {
265265
place.hash_stable(hcx, hasher);
@@ -278,23 +278,6 @@ for mir::StatementKind<'gcx> {
278278

279279
impl_stable_hash_for!(enum mir::FakeReadCause { ForMatchGuard, ForMatchedPlace, ForLet });
280280

281-
impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
282-
for mir::ValidationOperand<'gcx, T>
283-
where T: HashStable<StableHashingContext<'a>>
284-
{
285-
fn hash_stable<W: StableHasherResult>(&self,
286-
hcx: &mut StableHashingContext<'a>,
287-
hasher: &mut StableHasher<W>)
288-
{
289-
self.place.hash_stable(hcx, hasher);
290-
self.ty.hash_stable(hcx, hasher);
291-
self.re.hash_stable(hcx, hasher);
292-
self.mutbl.hash_stable(hcx, hasher);
293-
}
294-
}
295-
296-
impl_stable_hash_for!(enum mir::ValidationOp { Acquire, Release, Suspend(region_scope) });
297-
298281
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Place<'gcx> {
299282
fn hash_stable<W: StableHasherResult>(&self,
300283
hcx: &mut StableHashingContext<'a>,

src/librustc/mir/mod.rs

+14-64
Original file line numberDiff line numberDiff line change
@@ -1754,10 +1754,17 @@ pub enum StatementKind<'tcx> {
17541754
inputs: Box<[Operand<'tcx>]>,
17551755
},
17561756

1757-
/// Assert the given places to be valid inhabitants of their type. These statements are
1758-
/// currently only interpreted by miri and only generated when "-Z mir-emit-validate" is passed.
1759-
/// See <https://internals.rust-lang.org/t/types-as-contracts/5562/73> for more details.
1760-
Validate(ValidationOp, Vec<ValidationOperand<'tcx, Place<'tcx>>>),
1757+
/// Retag references in the given place, ensuring they got fresh tags. This is
1758+
/// part of the Stacked Borrows model. These statements are currently only interpreted
1759+
/// by miri and only generated when "-Z mir-emit-retag" is passed.
1760+
/// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
1761+
/// for more details.
1762+
Retag {
1763+
/// `fn_entry` indicates whether this is the initial retag that happens in the
1764+
/// function prolog.
1765+
fn_entry: bool,
1766+
place: Place<'tcx>,
1767+
},
17611768

17621769
/// Mark one terminating point of a region scope (i.e. static region).
17631770
/// (The starting point(s) arise implicitly from borrows.)
@@ -1810,57 +1817,6 @@ pub enum FakeReadCause {
18101817
ForLet,
18111818
}
18121819

1813-
/// The `ValidationOp` describes what happens with each of the operands of a
1814-
/// `Validate` statement.
1815-
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq)]
1816-
pub enum ValidationOp {
1817-
/// Recursively traverse the place following the type and validate that all type
1818-
/// invariants are maintained. Furthermore, acquire exclusive/read-only access to the
1819-
/// memory reachable from the place.
1820-
Acquire,
1821-
/// Recursive traverse the *mutable* part of the type and relinquish all exclusive
1822-
/// access.
1823-
Release,
1824-
/// Recursive traverse the *mutable* part of the type and relinquish all exclusive
1825-
/// access *until* the given region ends. Then, access will be recovered.
1826-
Suspend(region::Scope),
1827-
}
1828-
1829-
impl Debug for ValidationOp {
1830-
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1831-
use self::ValidationOp::*;
1832-
match *self {
1833-
Acquire => write!(fmt, "Acquire"),
1834-
Release => write!(fmt, "Release"),
1835-
// (reuse lifetime rendering policy from ppaux.)
1836-
Suspend(ref ce) => write!(fmt, "Suspend({})", ty::ReScope(*ce)),
1837-
}
1838-
}
1839-
}
1840-
1841-
// This is generic so that it can be reused by miri
1842-
#[derive(Clone, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
1843-
pub struct ValidationOperand<'tcx, T> {
1844-
pub place: T,
1845-
pub ty: Ty<'tcx>,
1846-
pub re: Option<region::Scope>,
1847-
pub mutbl: hir::Mutability,
1848-
}
1849-
1850-
impl<'tcx, T: Debug> Debug for ValidationOperand<'tcx, T> {
1851-
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
1852-
write!(fmt, "{:?}: {:?}", self.place, self.ty)?;
1853-
if let Some(ce) = self.re {
1854-
// (reuse lifetime rendering policy from ppaux.)
1855-
write!(fmt, "/{}", ty::ReScope(ce))?;
1856-
}
1857-
if let hir::MutImmutable = self.mutbl {
1858-
write!(fmt, " (imm)")?;
1859-
}
1860-
Ok(())
1861-
}
1862-
}
1863-
18641820
impl<'tcx> Debug for Statement<'tcx> {
18651821
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
18661822
use self::StatementKind::*;
@@ -1869,7 +1825,8 @@ impl<'tcx> Debug for Statement<'tcx> {
18691825
FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
18701826
// (reuse lifetime rendering policy from ppaux.)
18711827
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
1872-
Validate(ref op, ref places) => write!(fmt, "Validate({:?}, {:?})", op, places),
1828+
Retag { fn_entry, ref place } =>
1829+
write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place),
18731830
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
18741831
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
18751832
SetDiscriminant {
@@ -2944,7 +2901,6 @@ CloneTypeFoldableAndLiftImpls! {
29442901
SourceInfo,
29452902
UpvarDecl,
29462903
FakeReadCause,
2947-
ValidationOp,
29482904
SourceScope,
29492905
SourceScopeData,
29502906
SourceScopeLocalData,
@@ -2997,12 +2953,6 @@ BraceStructTypeFoldableImpl! {
29972953
}
29982954
}
29992955

3000-
BraceStructTypeFoldableImpl! {
3001-
impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Place<'tcx>> {
3002-
place, ty, re, mutbl
3003-
}
3004-
}
3005-
30062956
BraceStructTypeFoldableImpl! {
30072957
impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
30082958
source_info, kind
@@ -3017,7 +2967,7 @@ EnumTypeFoldableImpl! {
30172967
(StatementKind::StorageLive)(a),
30182968
(StatementKind::StorageDead)(a),
30192969
(StatementKind::InlineAsm) { asm, outputs, inputs },
3020-
(StatementKind::Validate)(a, b),
2970+
(StatementKind::Retag) { fn_entry, place },
30212971
(StatementKind::EndRegion)(a),
30222972
(StatementKind::AscribeUserType)(a, v, b),
30232973
(StatementKind::Nop),

src/librustc/mir/visit.rs

+24-13
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ macro_rules! make_mir_visitor {
152152
self.super_ascribe_user_ty(place, variance, user_ty, location);
153153
}
154154

155+
fn visit_retag(&mut self,
156+
fn_entry: & $($mutability)* bool,
157+
place: & $($mutability)* Place<'tcx>,
158+
location: Location) {
159+
self.super_retag(fn_entry, place, location);
160+
}
161+
155162
fn visit_place(&mut self,
156163
place: & $($mutability)* Place<'tcx>,
157164
context: PlaceContext<'tcx>,
@@ -371,17 +378,6 @@ macro_rules! make_mir_visitor {
371378
);
372379
}
373380
StatementKind::EndRegion(_) => {}
374-
StatementKind::Validate(_, ref $($mutability)* places) => {
375-
for operand in places {
376-
self.visit_place(
377-
& $($mutability)* operand.place,
378-
PlaceContext::NonUse(NonUseContext::Validate),
379-
location
380-
);
381-
self.visit_ty(& $($mutability)* operand.ty,
382-
TyContext::Location(location));
383-
}
384-
}
385381
StatementKind::SetDiscriminant{ ref $($mutability)* place, .. } => {
386382
self.visit_place(
387383
place,
@@ -417,6 +413,10 @@ macro_rules! make_mir_visitor {
417413
self.visit_operand(input, location);
418414
}
419415
}
416+
StatementKind::Retag { ref $($mutability)* fn_entry,
417+
ref $($mutability)* place } => {
418+
self.visit_retag(fn_entry, place, location);
419+
}
420420
StatementKind::AscribeUserType(
421421
ref $($mutability)* place,
422422
ref $($mutability)* variance,
@@ -719,6 +719,17 @@ macro_rules! make_mir_visitor {
719719
self.visit_user_type_projection(user_ty);
720720
}
721721

722+
fn super_retag(&mut self,
723+
_fn_entry: & $($mutability)* bool,
724+
place: & $($mutability)* Place<'tcx>,
725+
location: Location) {
726+
self.visit_place(
727+
place,
728+
PlaceContext::MutatingUse(MutatingUseContext::Retag),
729+
location,
730+
);
731+
}
732+
722733
fn super_place(&mut self,
723734
place: & $($mutability)* Place<'tcx>,
724735
context: PlaceContext<'tcx>,
@@ -1010,6 +1021,8 @@ pub enum MutatingUseContext<'tcx> {
10101021
/// f(&mut x.y);
10111022
///
10121023
Projection,
1024+
/// Retagging (updating the "Stacked Borrows" tag)
1025+
Retag,
10131026
}
10141027

10151028
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -1020,8 +1033,6 @@ pub enum NonUseContext {
10201033
StorageDead,
10211034
/// User type annotation assertions for NLL.
10221035
AscribeUserTy,
1023-
/// Validation command.
1024-
Validate,
10251036
}
10261037

10271038
#[derive(Copy, Clone, Debug, PartialEq, Eq)]

src/librustc/session/config.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1282,9 +1282,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
12821282
"in addition to `.mir` files, create graphviz `.dot` files"),
12831283
dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED],
12841284
"if set, exclude the pass number when dumping MIR (used in tests)"),
1285-
mir_emit_validate: usize = (0, parse_uint, [TRACKED],
1286-
"emit Validate MIR statements, interpreted e.g. by miri (0: do not emit; 1: if function \
1287-
contains unsafe block, only validate arguments; 2: always emit full validation)"),
1285+
mir_emit_retag: bool = (false, parse_bool, [TRACKED],
1286+
"emit Retagging MIR statements, interpreted e.g. by miri; implies -Zmir-opt-level=0"),
12881287
perf_stats: bool = (false, parse_bool, [UNTRACKED],
12891288
"print some performance-related statistics"),
12901289
hir_stats: bool = (false, parse_bool, [UNTRACKED],

src/librustc/ty/context.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1547,11 +1547,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
15471547
}
15481548

15491549
/// Should we emit EndRegion MIR statements? These are consumed by
1550-
/// MIR borrowck, but not when NLL is used. They are also consumed
1551-
/// by the validation stuff.
1550+
/// MIR borrowck, but not when NLL is used.
15521551
pub fn emit_end_regions(self) -> bool {
15531552
self.sess.opts.debugging_opts.emit_end_regions ||
1554-
self.sess.opts.debugging_opts.mir_emit_validate > 0 ||
15551553
self.use_mir_borrowck()
15561554
}
15571555

src/librustc_codegen_llvm/mir/analyze.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> {
219219
self.assign(local, location);
220220
}
221221

222-
PlaceContext::NonUse(_) => {}
222+
PlaceContext::NonUse(_) |
223+
PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}
223224

224225
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
225226
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => {

src/librustc_codegen_llvm/mir/statement.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
109109
}
110110
mir::StatementKind::FakeRead(..) |
111111
mir::StatementKind::EndRegion(_) |
112-
mir::StatementKind::Validate(..) |
112+
mir::StatementKind::Retag { .. } |
113113
mir::StatementKind::AscribeUserType(..) |
114114
mir::StatementKind::Nop => bx,
115115
}

src/librustc_mir/borrow_check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -600,9 +600,9 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
600600
}
601601
StatementKind::Nop
602602
| StatementKind::AscribeUserType(..)
603-
| StatementKind::Validate(..)
603+
| StatementKind::Retag { .. }
604604
| StatementKind::StorageLive(..) => {
605-
// `Nop`, `AscribeUserType`, `Validate`, and `StorageLive` are irrelevant
605+
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
606606
// to borrow check.
607607
}
608608
StatementKind::StorageDead(local) => {

src/librustc_mir/borrow_check/nll/invalidation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
136136
StatementKind::EndRegion(..) |
137137
StatementKind::Nop |
138138
StatementKind::AscribeUserType(..) |
139-
StatementKind::Validate(..) |
139+
StatementKind::Retag { .. } |
140140
StatementKind::StorageLive(..) => {
141-
// `Nop`, `AscribeUserType`, `Validate`, and `StorageLive` are irrelevant
141+
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
142142
// to borrow check.
143143
}
144144
StatementKind::StorageDead(local) => {

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1294,7 +1294,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
12941294
| StatementKind::StorageDead(_)
12951295
| StatementKind::InlineAsm { .. }
12961296
| StatementKind::EndRegion(_)
1297-
| StatementKind::Validate(..)
1297+
| StatementKind::Retag { .. }
12981298
| StatementKind::Nop => {}
12991299
}
13001300
}

src/librustc_mir/dataflow/impls/borrows.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
338338
mir::StatementKind::FakeRead(..) |
339339
mir::StatementKind::SetDiscriminant { .. } |
340340
mir::StatementKind::StorageLive(..) |
341-
mir::StatementKind::Validate(..) |
341+
mir::StatementKind::Retag { .. } |
342342
mir::StatementKind::AscribeUserType(..) |
343343
mir::StatementKind::Nop => {}
344344

src/librustc_mir/dataflow/move_paths/builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
302302
"SetDiscriminant should not exist during borrowck");
303303
}
304304
StatementKind::EndRegion(_) |
305-
StatementKind::Validate(..) |
305+
StatementKind::Retag { .. } |
306306
StatementKind::AscribeUserType(..) |
307307
StatementKind::Nop => {}
308308
}

0 commit comments

Comments
 (0)