Skip to content
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

treat ref-to-raw cast like a reborrow: do a special kind of retag #56741

Merged
merged 1 commit into from
Dec 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,13 @@ impl_stable_hash_for!(impl<'gcx> for enum mir::StatementKind<'gcx> [ mir::Statem
SetDiscriminant { place, variant_index },
StorageLive(place),
StorageDead(place),
EscapeToRaw(place),
Retag { fn_entry, two_phase, place },
Retag(retag_kind, place),
AscribeUserType(place, variance, c_ty),
Nop,
InlineAsm { asm, outputs, inputs },
});

impl_stable_hash_for!(enum mir::RetagKind { FnEntry, TwoPhase, Raw, Default });
impl_stable_hash_for!(enum mir::FakeReadCause { ForMatchGuard, ForMatchedPlace, ForLet });

impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Place<'gcx> {
Expand Down
48 changes: 24 additions & 24 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1774,23 +1774,7 @@ pub enum StatementKind<'tcx> {
/// by miri and only generated when "-Z mir-emit-retag" is passed.
/// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
/// for more details.
Retag {
/// `fn_entry` indicates whether this is the initial retag that happens in the
/// function prolog.
fn_entry: bool,
/// `two_phase` indicates whether this is just the reservation action of
/// a two-phase borrow.
two_phase: bool,
/// The place to retag
place: Place<'tcx>,
},

/// Escape the given reference to a raw pointer, so that it can be accessed
/// without precise provenance tracking. These statements are currently only interpreted
/// by miri and only generated when "-Z mir-emit-retag" is passed.
/// See <https://internals.rust-lang.org/t/stacked-borrows-an-aliasing-model-for-rust/8153/>
/// for more details.
EscapeToRaw(Operand<'tcx>),
Retag(RetagKind, Place<'tcx>),

/// Encodes a user's type ascription. These need to be preserved
/// intact so that NLL can respect them. For example:
Expand All @@ -1810,6 +1794,19 @@ pub enum StatementKind<'tcx> {
Nop,
}

/// `RetagKind` describes what kind of retag is to be performed.
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq)]
pub enum RetagKind {
/// The initial retag when entering a function
FnEntry,
/// Retag preparing for a two-phase borrow
TwoPhase,
/// Retagging raw pointers
Raw,
/// A "normal" retag
Default,
}

/// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists.
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
pub enum FakeReadCause {
Expand Down Expand Up @@ -1845,13 +1842,16 @@ impl<'tcx> Debug for Statement<'tcx> {
match self.kind {
Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
Retag { fn_entry, two_phase, ref place } =>
write!(fmt, "Retag({}{}{:?})",
if fn_entry { "[fn entry] " } else { "" },
if two_phase { "[2phase] " } else { "" },
Retag(ref kind, ref place) =>
write!(fmt, "Retag({}{:?})",
match kind {
RetagKind::FnEntry => "[fn entry] ",
RetagKind::TwoPhase => "[2phase] ",
RetagKind::Raw => "[raw] ",
RetagKind::Default => "",
},
place,
),
EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place),
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
SetDiscriminant {
Expand Down Expand Up @@ -2965,6 +2965,7 @@ CloneTypeFoldableAndLiftImpls! {
SourceInfo,
UpvarDecl,
FakeReadCause,
RetagKind,
SourceScope,
SourceScopeData,
SourceScopeLocalData,
Expand Down Expand Up @@ -3031,8 +3032,7 @@ EnumTypeFoldableImpl! {
(StatementKind::StorageLive)(a),
(StatementKind::StorageDead)(a),
(StatementKind::InlineAsm) { asm, outputs, inputs },
(StatementKind::Retag) { fn_entry, two_phase, place },
(StatementKind::EscapeToRaw)(place),
(StatementKind::Retag)(kind, place),
(StatementKind::AscribeUserType)(a, v, b),
(StatementKind::Nop),
}
Expand Down
18 changes: 6 additions & 12 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,10 @@ macro_rules! make_mir_visitor {
}

fn visit_retag(&mut self,
fn_entry: & $($mutability)* bool,
two_phase: & $($mutability)* bool,
kind: & $($mutability)* RetagKind,
place: & $($mutability)* Place<'tcx>,
location: Location) {
self.super_retag(fn_entry, two_phase, place, location);
self.super_retag(kind, place, location);
}

fn visit_place(&mut self,
Expand Down Expand Up @@ -385,9 +384,6 @@ macro_rules! make_mir_visitor {
location
);
}
StatementKind::EscapeToRaw(ref $($mutability)* op) => {
self.visit_operand(op, location);
}
StatementKind::StorageLive(ref $($mutability)* local) => {
self.visit_local(
local,
Expand Down Expand Up @@ -417,10 +413,9 @@ macro_rules! make_mir_visitor {
self.visit_operand(input, location);
}
}
StatementKind::Retag { ref $($mutability)* fn_entry,
ref $($mutability)* two_phase,
ref $($mutability)* place } => {
self.visit_retag(fn_entry, two_phase, place, location);
StatementKind::Retag ( ref $($mutability)* kind,
ref $($mutability)* place ) => {
self.visit_retag(kind, place, location);
}
StatementKind::AscribeUserType(
ref $($mutability)* place,
Expand Down Expand Up @@ -725,8 +720,7 @@ macro_rules! make_mir_visitor {
}

fn super_retag(&mut self,
_fn_entry: & $($mutability)* bool,
_two_phase: & $($mutability)* bool,
_kind: & $($mutability)* RetagKind,
place: & $($mutability)* Place<'tcx>,
location: Location) {
self.visit_place(
Expand Down
1 change: 0 additions & 1 deletion src/librustc_codegen_ssa/mir/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
mir::StatementKind::FakeRead(..) |
mir::StatementKind::Retag { .. } |
mir::StatementKind::EscapeToRaw { .. } |
mir::StatementKind::AscribeUserType(..) |
mir::StatementKind::Nop => bx,
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,6 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
StatementKind::Nop
| StatementKind::AscribeUserType(..)
| StatementKind::Retag { .. }
| StatementKind::EscapeToRaw { .. }
| StatementKind::StorageLive(..) => {
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
// to borrow check.
Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/borrow_check/nll/invalidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
StatementKind::Nop |
StatementKind::AscribeUserType(..) |
StatementKind::Retag { .. } |
StatementKind::EscapeToRaw { .. } |
StatementKind::StorageLive(..) => {
// `Nop`, `AscribeUserType`, `Retag`, and `StorageLive` are irrelevant
// to borrow check.
Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/borrow_check/nll/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1316,7 +1316,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
| StatementKind::StorageDead(..)
| StatementKind::InlineAsm { .. }
| StatementKind::Retag { .. }
| StatementKind::EscapeToRaw { .. }
| StatementKind::Nop => {}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/dataflow/impls/borrows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
mir::StatementKind::SetDiscriminant { .. } |
mir::StatementKind::StorageLive(..) |
mir::StatementKind::Retag { .. } |
mir::StatementKind::EscapeToRaw { .. } |
mir::StatementKind::AscribeUserType(..) |
mir::StatementKind::Nop => {}

Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/dataflow/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,6 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
"SetDiscriminant should not exist during borrowck");
}
StatementKind::Retag { .. } |
StatementKind::EscapeToRaw { .. } |
StatementKind::AscribeUserType(..) |
StatementKind::Nop => {}
}
Expand Down
20 changes: 7 additions & 13 deletions src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,28 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
}

Misc => {
let src_layout = src.layout;
let src = self.read_immediate(src)?;

// There are no casts to references
assert!(!dest.layout.ty.is_region_ptr());
// Hence we make all casts erase the tag
let src = src.erase_tag().with_default_tag();

if self.type_is_fat_ptr(src_layout.ty) {
match (src, self.type_is_fat_ptr(dest.layout.ty)) {
if self.type_is_fat_ptr(src.layout.ty) {
match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
// pointers to extern types
(Immediate::Scalar(_),_) |
// slices and trait objects to other slices/trait objects
(Immediate::ScalarPair(..), true) => {
// No change to immediate
self.write_immediate(src, dest)?;
self.write_immediate(*src, dest)?;
}
// slices and trait objects to thin pointers (dropping the metadata)
(Immediate::ScalarPair(data, _), false) => {
self.write_scalar(data, dest)?;
}
}
} else {
match src_layout.variants {
match src.layout.variants {
layout::Variants::Single { index } => {
if let Some(def) = src_layout.ty.ty_adt_def() {
if let Some(def) = src.layout.ty.ty_adt_def() {
// Cast from a univariant enum
assert!(src_layout.is_zst());
assert!(src.layout.is_zst());
let discr_val = def
.discriminant_for_variant(*self.tcx, index)
.val;
Expand All @@ -84,7 +78,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
layout::Variants::NicheFilling { .. } => {},
}

let dest_val = self.cast_scalar(src.to_scalar()?, src_layout, dest.layout)?;
let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
self.write_scalar(dest_val, dest)?;
}
}
Expand Down
12 changes: 1 addition & 11 deletions src/librustc_mir/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,22 +203,12 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
#[inline]
fn retag(
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
_fn_entry: bool,
_two_phase: bool,
_kind: mir::RetagKind,
_place: PlaceTy<'tcx, Self::PointerTag>,
) -> EvalResult<'tcx> {
Ok(())
}

/// Execute an escape-to-raw operation
#[inline]
fn escape_to_raw(
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
_ptr: OpTy<'tcx, Self::PointerTag>,
) -> EvalResult<'tcx> {
Ok(())
}

/// Called immediately before a new stack frame got pushed
fn stack_push(
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
Expand Down
8 changes: 2 additions & 6 deletions src/librustc_mir/interpret/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
FakeRead(..) => {}

// Stacked Borrows.
Retag { fn_entry, two_phase, ref place } => {
Retag(kind, ref place) => {
let dest = self.eval_place(place)?;
M::retag(self, fn_entry, two_phase, dest)?;
}
EscapeToRaw(ref op) => {
let op = self.eval_operand(op, None)?;
M::escape_to_raw(self, op)?;
M::retag(self, kind, dest)?;
}

// Statements we do not track.
Expand Down
13 changes: 2 additions & 11 deletions src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,20 +226,11 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// The first argument (index 0), but add 1 for the return value.
let dropee_ptr = Place::Local(Local::new(1+0));
if tcx.sess.opts.debugging_opts.mir_emit_retag {
// Function arguments should be retagged
// Function arguments should be retagged, and we make this one raw.
mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
source_info,
kind: StatementKind::Retag {
fn_entry: true,
two_phase: false,
place: dropee_ptr.clone(),
},
kind: StatementKind::Retag(RetagKind::Raw, dropee_ptr.clone()),
});
// We use raw ptr operations, better prepare the alias tracking for that
mir.basic_blocks_mut()[START_BLOCK].statements.insert(1, Statement {
source_info,
kind: StatementKind::EscapeToRaw(Operand::Copy(dropee_ptr.clone())),
})
}
let patch = {
let param_env = tcx.param_env(def_id).with_reveal_all();
Expand Down
Loading