Skip to content

Commit aafcf2c

Browse files
committed
Emit Retag statements, kill Validate statements
Also "rename" -Zmir-emit-validate to -Zmir-emit-retag, which is just a boolean (yes or no).
1 parent 4e88b73 commit aafcf2c

File tree

26 files changed

+233
-543
lines changed

26 files changed

+233
-543
lines changed

src/bootstrap/bin/rustc.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,12 @@ fn main() {
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") {
256256
cmd.arg("-Zalways-encode-mir");
257-
cmd.arg("-Zmir-emit-validate=1");
257+
// These options are preferred by miri, to be able to perform better validation,
258+
// but the bootstrap compiler might not understand them.
259+
if stage != "0" {
260+
cmd.arg("-Zmir-emit-retag");
261+
cmd.arg("-Zmir-opt-level=0");
262+
}
258263
}
259264

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

src/librustc/ich/impls_mir.rs

Lines changed: 3 additions & 20 deletions
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

Lines changed: 10 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,10 +1754,13 @@ 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. `fn_entry` indicates whether this
1759+
/// is the initial retag that happens in the function prolog. These statements are
1760+
/// currently only interpreted by miri and only generated when "-Z mir-emit-retag" is passed.
1761+
/// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
1762+
/// for more details.
1763+
Retag { fn_entry: bool, place: Place<'tcx> },
17611764

17621765
/// Mark one terminating point of a region scope (i.e. static region).
17631766
/// (The starting point(s) arise implicitly from borrows.)
@@ -1810,57 +1813,6 @@ pub enum FakeReadCause {
18101813
ForLet,
18111814
}
18121815

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-
18641816
impl<'tcx> Debug for Statement<'tcx> {
18651817
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
18661818
use self::StatementKind::*;
@@ -1869,7 +1821,8 @@ impl<'tcx> Debug for Statement<'tcx> {
18691821
FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
18701822
// (reuse lifetime rendering policy from ppaux.)
18711823
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
1872-
Validate(ref op, ref places) => write!(fmt, "Validate({:?}, {:?})", op, places),
1824+
Retag { fn_entry, ref place } =>
1825+
write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry]: " } else { "" }, place),
18731826
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
18741827
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
18751828
SetDiscriminant {
@@ -2944,7 +2897,6 @@ CloneTypeFoldableAndLiftImpls! {
29442897
SourceInfo,
29452898
UpvarDecl,
29462899
FakeReadCause,
2947-
ValidationOp,
29482900
SourceScope,
29492901
SourceScopeData,
29502902
SourceScopeLocalData,
@@ -2997,12 +2949,6 @@ BraceStructTypeFoldableImpl! {
29972949
}
29982950
}
29992951

3000-
BraceStructTypeFoldableImpl! {
3001-
impl<'tcx> TypeFoldable<'tcx> for ValidationOperand<'tcx, Place<'tcx>> {
3002-
place, ty, re, mutbl
3003-
}
3004-
}
3005-
30062952
BraceStructTypeFoldableImpl! {
30072953
impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
30082954
source_info, kind
@@ -3017,7 +2963,7 @@ EnumTypeFoldableImpl! {
30172963
(StatementKind::StorageLive)(a),
30182964
(StatementKind::StorageDead)(a),
30192965
(StatementKind::InlineAsm) { asm, outputs, inputs },
3020-
(StatementKind::Validate)(a, b),
2966+
(StatementKind::Retag) { fn_entry, place },
30212967
(StatementKind::EndRegion)(a),
30222968
(StatementKind::AscribeUserType)(a, v, b),
30232969
(StatementKind::Nop),

src/librustc/mir/visit.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -371,16 +371,12 @@ macro_rules! make_mir_visitor {
371371
);
372372
}
373373
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-
}
374+
StatementKind::Retag { fn_entry: _, ref $($mutability)* place } => {
375+
self.visit_place(
376+
place,
377+
PlaceContext::MutatingUse(MutatingUseContext::Retag),
378+
location,
379+
);
384380
}
385381
StatementKind::SetDiscriminant{ ref $($mutability)* place, .. } => {
386382
self.visit_place(
@@ -1010,6 +1006,8 @@ pub enum MutatingUseContext<'tcx> {
10101006
/// f(&mut x.y);
10111007
///
10121008
Projection,
1009+
/// Retagging (updating the "Stacked Borrows" tag)
1010+
Retag,
10131011
}
10141012

10151013
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -1020,8 +1018,6 @@ pub enum NonUseContext {
10201018
StorageDead,
10211019
/// User type annotation assertions for NLL.
10221020
AscribeUserTy,
1023-
/// Validation command.
1024-
Validate,
10251021
}
10261022

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

src/librustc/session/config.rs

Lines changed: 2 additions & 3 deletions
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

Lines changed: 1 addition & 3 deletions
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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,9 +574,9 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
574574
}
575575
StatementKind::Nop
576576
| StatementKind::AscribeUserType(..)
577-
| StatementKind::Validate(..)
577+
| StatementKind::Retag { .. }
578578
| StatementKind::StorageLive(..) => {
579-
// `Nop`, `AscribeUserType`, `Validate`, and `StorageLive` are irrelevant
579+
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
580580
// to borrow check.
581581
}
582582
StatementKind::StorageDead(local) => {

src/librustc_mir/borrow_check/nll/invalidation.rs

Lines changed: 2 additions & 2 deletions
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1264,7 +1264,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
12641264
| StatementKind::StorageDead(_)
12651265
| StatementKind::InlineAsm { .. }
12661266
| StatementKind::EndRegion(_)
1267-
| StatementKind::Validate(..)
1267+
| StatementKind::Retag { .. }
12681268
| StatementKind::Nop => {}
12691269
}
12701270
}

src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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
}

src/librustc_mir/interpret/machine.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,10 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
242242

243243
/// Execute a validation operation
244244
#[inline]
245-
fn validation_op(
245+
fn retag(
246246
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
247-
_op: ::rustc::mir::ValidationOp,
248-
_operand: &::rustc::mir::ValidationOperand<'tcx, ::rustc::mir::Place<'tcx>>,
247+
_fn_entry: bool,
248+
_place: PlaceTy<'tcx, Self::PointerTag>,
249249
) -> EvalResult<'tcx> {
250250
Ok(())
251251
}

src/librustc_mir/interpret/step.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,10 @@ 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-
// Validity checks.
122-
Validate(op, ref places) => {
123-
for operand in places {
124-
M::validation_op(self, op, operand)?;
125-
}
121+
// Retagging.
122+
Retag { fn_entry, ref place } => {
123+
let dest = self.eval_place(place)?;
124+
M::retag(self, fn_entry, dest)?;
126125
}
127126

128127
EndRegion(..) => {}

0 commit comments

Comments
 (0)