Retag needs to know whether this is a 2-phase-reborrow
This commit is contained in:
parent
7139e1c3ab
commit
d2c19e0bcc
7 changed files with 52 additions and 58 deletions
|
@ -193,51 +193,18 @@ for mir::TerminatorKind<'gcx> {
|
||||||
|
|
||||||
impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });
|
impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });
|
||||||
|
|
||||||
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
|
impl_stable_hash_for!(impl<'gcx> for enum mir::StatementKind<'gcx> [ mir::StatementKind ] {
|
||||||
for mir::StatementKind<'gcx> {
|
Assign(place, rvalue),
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
FakeRead(cause, place),
|
||||||
hcx: &mut StableHashingContext<'a>,
|
SetDiscriminant { place, variant_index },
|
||||||
hasher: &mut StableHasher<W>) {
|
StorageLive(place),
|
||||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
StorageDead(place),
|
||||||
|
EscapeToRaw(place),
|
||||||
match *self {
|
Retag { fn_entry, two_phase, place },
|
||||||
mir::StatementKind::Assign(ref place, ref rvalue) => {
|
AscribeUserType(place, variance, c_ty),
|
||||||
place.hash_stable(hcx, hasher);
|
Nop,
|
||||||
rvalue.hash_stable(hcx, hasher);
|
InlineAsm { asm, outputs, inputs },
|
||||||
}
|
});
|
||||||
mir::StatementKind::FakeRead(ref cause, ref place) => {
|
|
||||||
cause.hash_stable(hcx, hasher);
|
|
||||||
place.hash_stable(hcx, hasher);
|
|
||||||
}
|
|
||||||
mir::StatementKind::SetDiscriminant { ref place, variant_index } => {
|
|
||||||
place.hash_stable(hcx, hasher);
|
|
||||||
variant_index.hash_stable(hcx, hasher);
|
|
||||||
}
|
|
||||||
mir::StatementKind::StorageLive(ref place) |
|
|
||||||
mir::StatementKind::StorageDead(ref place) => {
|
|
||||||
place.hash_stable(hcx, hasher);
|
|
||||||
}
|
|
||||||
mir::StatementKind::EscapeToRaw(ref place) => {
|
|
||||||
place.hash_stable(hcx, hasher);
|
|
||||||
}
|
|
||||||
mir::StatementKind::Retag { fn_entry, ref place } => {
|
|
||||||
fn_entry.hash_stable(hcx, hasher);
|
|
||||||
place.hash_stable(hcx, hasher);
|
|
||||||
}
|
|
||||||
mir::StatementKind::AscribeUserType(ref place, ref variance, ref c_ty) => {
|
|
||||||
place.hash_stable(hcx, hasher);
|
|
||||||
variance.hash_stable(hcx, hasher);
|
|
||||||
c_ty.hash_stable(hcx, hasher);
|
|
||||||
}
|
|
||||||
mir::StatementKind::Nop => {}
|
|
||||||
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
|
||||||
asm.hash_stable(hcx, hasher);
|
|
||||||
outputs.hash_stable(hcx, hasher);
|
|
||||||
inputs.hash_stable(hcx, hasher);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_stable_hash_for!(enum mir::FakeReadCause { ForMatchGuard, ForMatchedPlace, ForLet });
|
impl_stable_hash_for!(enum mir::FakeReadCause { ForMatchGuard, ForMatchedPlace, ForLet });
|
||||||
|
|
||||||
|
|
|
@ -1778,6 +1778,10 @@ pub enum StatementKind<'tcx> {
|
||||||
/// `fn_entry` indicates whether this is the initial retag that happens in the
|
/// `fn_entry` indicates whether this is the initial retag that happens in the
|
||||||
/// function prolog.
|
/// function prolog.
|
||||||
fn_entry: bool,
|
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>,
|
place: Place<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1841,8 +1845,12 @@ impl<'tcx> Debug for Statement<'tcx> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
|
Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
|
||||||
FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
|
FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
|
||||||
Retag { fn_entry, ref place } =>
|
Retag { fn_entry, two_phase, ref place } =>
|
||||||
write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place),
|
write!(fmt, "Retag({}{}{:?})",
|
||||||
|
if fn_entry { "[fn entry] " } else { "" },
|
||||||
|
if two_phase { "[2phase] " } else { "" },
|
||||||
|
place,
|
||||||
|
),
|
||||||
EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place),
|
EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place),
|
||||||
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
|
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
|
||||||
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
|
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
|
||||||
|
@ -3019,7 +3027,7 @@ EnumTypeFoldableImpl! {
|
||||||
(StatementKind::StorageLive)(a),
|
(StatementKind::StorageLive)(a),
|
||||||
(StatementKind::StorageDead)(a),
|
(StatementKind::StorageDead)(a),
|
||||||
(StatementKind::InlineAsm) { asm, outputs, inputs },
|
(StatementKind::InlineAsm) { asm, outputs, inputs },
|
||||||
(StatementKind::Retag) { fn_entry, place },
|
(StatementKind::Retag) { fn_entry, two_phase, place },
|
||||||
(StatementKind::EscapeToRaw)(place),
|
(StatementKind::EscapeToRaw)(place),
|
||||||
(StatementKind::AscribeUserType)(a, v, b),
|
(StatementKind::AscribeUserType)(a, v, b),
|
||||||
(StatementKind::Nop),
|
(StatementKind::Nop),
|
||||||
|
|
|
@ -154,9 +154,10 @@ macro_rules! make_mir_visitor {
|
||||||
|
|
||||||
fn visit_retag(&mut self,
|
fn visit_retag(&mut self,
|
||||||
fn_entry: & $($mutability)* bool,
|
fn_entry: & $($mutability)* bool,
|
||||||
|
two_phase: & $($mutability)* bool,
|
||||||
place: & $($mutability)* Place<'tcx>,
|
place: & $($mutability)* Place<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.super_retag(fn_entry, place, location);
|
self.super_retag(fn_entry, two_phase, place, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_place(&mut self,
|
fn visit_place(&mut self,
|
||||||
|
@ -417,8 +418,9 @@ macro_rules! make_mir_visitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatementKind::Retag { ref $($mutability)* fn_entry,
|
StatementKind::Retag { ref $($mutability)* fn_entry,
|
||||||
|
ref $($mutability)* two_phase,
|
||||||
ref $($mutability)* place } => {
|
ref $($mutability)* place } => {
|
||||||
self.visit_retag(fn_entry, place, location);
|
self.visit_retag(fn_entry, two_phase, place, location);
|
||||||
}
|
}
|
||||||
StatementKind::AscribeUserType(
|
StatementKind::AscribeUserType(
|
||||||
ref $($mutability)* place,
|
ref $($mutability)* place,
|
||||||
|
@ -724,6 +726,7 @@ macro_rules! make_mir_visitor {
|
||||||
|
|
||||||
fn super_retag(&mut self,
|
fn super_retag(&mut self,
|
||||||
_fn_entry: & $($mutability)* bool,
|
_fn_entry: & $($mutability)* bool,
|
||||||
|
_two_phase: & $($mutability)* bool,
|
||||||
place: & $($mutability)* Place<'tcx>,
|
place: & $($mutability)* Place<'tcx>,
|
||||||
location: Location) {
|
location: Location) {
|
||||||
self.visit_place(
|
self.visit_place(
|
||||||
|
|
|
@ -204,6 +204,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
||||||
fn retag(
|
fn retag(
|
||||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||||
_fn_entry: bool,
|
_fn_entry: bool,
|
||||||
|
_two_phase: bool,
|
||||||
_place: PlaceTy<'tcx, Self::PointerTag>,
|
_place: PlaceTy<'tcx, Self::PointerTag>,
|
||||||
) -> EvalResult<'tcx> {
|
) -> EvalResult<'tcx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -119,9 +119,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||||
FakeRead(..) => {}
|
FakeRead(..) => {}
|
||||||
|
|
||||||
// Stacked Borrows.
|
// Stacked Borrows.
|
||||||
Retag { fn_entry, ref place } => {
|
Retag { fn_entry, two_phase, ref place } => {
|
||||||
let dest = self.eval_place(place)?;
|
let dest = self.eval_place(place)?;
|
||||||
M::retag(self, fn_entry, dest)?;
|
M::retag(self, fn_entry, two_phase, dest)?;
|
||||||
}
|
}
|
||||||
EscapeToRaw(ref op) => {
|
EscapeToRaw(ref op) => {
|
||||||
let op = self.eval_operand(op, None)?;
|
let op = self.eval_operand(op, None)?;
|
||||||
|
|
|
@ -118,7 +118,7 @@ impl MirPass for AddRetag {
|
||||||
basic_blocks[START_BLOCK].statements.splice(0..0,
|
basic_blocks[START_BLOCK].statements.splice(0..0,
|
||||||
places.into_iter().map(|place| Statement {
|
places.into_iter().map(|place| Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Retag { fn_entry: true, place },
|
kind: StatementKind::Retag { fn_entry: true, two_phase: false, place },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ impl MirPass for AddRetag {
|
||||||
for (source_info, dest_place, dest_block) in returns {
|
for (source_info, dest_place, dest_block) in returns {
|
||||||
basic_blocks[dest_block].statements.insert(0, Statement {
|
basic_blocks[dest_block].statements.insert(0, Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Retag { fn_entry: false, place: dest_place },
|
kind: StatementKind::Retag { fn_entry: false, two_phase: false, place: dest_place },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,12 +191,21 @@ impl MirPass for AddRetag {
|
||||||
// Assignments of reference or ptr type are the ones where we may have
|
// Assignments of reference or ptr type are the ones where we may have
|
||||||
// to update tags. This includes `x = &[mut] ...` and hence
|
// to update tags. This includes `x = &[mut] ...` and hence
|
||||||
// we also retag after taking a reference!
|
// we also retag after taking a reference!
|
||||||
StatementKind::Assign(ref place, _) if needs_retag(place) => {
|
StatementKind::Assign(ref place, box ref rvalue) if needs_retag(place) => {
|
||||||
|
let two_phase = match rvalue {
|
||||||
|
Rvalue::Ref(_, borrow_kind, _) =>
|
||||||
|
borrow_kind.allows_two_phase_borrow(),
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
// Insert a retag after the assignment.
|
// Insert a retag after the assignment.
|
||||||
let source_info = block_data.statements[i].source_info;
|
let source_info = block_data.statements[i].source_info;
|
||||||
block_data.statements.insert(i+1, Statement {
|
block_data.statements.insert(i+1, Statement {
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Retag { fn_entry: false, place: place.clone() },
|
kind: StatementKind::Retag {
|
||||||
|
fn_entry: false,
|
||||||
|
two_phase,
|
||||||
|
place: place.clone(),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Do nothing for the rest
|
// Do nothing for the rest
|
||||||
|
|
|
@ -707,8 +707,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
|
||||||
self.in_cleanup_block = false;
|
self.in_cleanup_block = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_retag(&mut self, fn_entry: &mut bool, place: &mut Place<'tcx>, loc: Location) {
|
fn visit_retag(
|
||||||
self.super_retag(fn_entry, place, loc);
|
&mut self,
|
||||||
|
fn_entry: &mut bool,
|
||||||
|
two_phase: &mut bool,
|
||||||
|
place: &mut Place<'tcx>,
|
||||||
|
loc: Location,
|
||||||
|
) {
|
||||||
|
self.super_retag(fn_entry, two_phase, place, loc);
|
||||||
|
|
||||||
// We have to patch all inlined retags to be aware that they are no longer
|
// We have to patch all inlined retags to be aware that they are no longer
|
||||||
// happening on function entry.
|
// happening on function entry.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue