summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_transform/src/add_retag.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src/add_retag.rs')
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs53
1 files changed, 13 insertions, 40 deletions
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 036b55898..3d22035f0 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -10,16 +10,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
pub struct AddRetag;
-/// Determines whether this place is "stable": Whether, if we evaluate it again
-/// after the assignment, we can be sure to obtain the same place value.
-/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
-/// copies. Data races are UB.)
-fn is_stable(place: PlaceRef<'_>) -> bool {
- // Which place this evaluates to can change with any memory write,
- // so cannot assume deref to be stable.
- !place.has_deref()
-}
-
/// Determine whether this type may contain a reference (or box), and thus needs retagging.
/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool {
@@ -69,22 +59,10 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
let basic_blocks = body.basic_blocks.as_mut();
let local_decls = &body.local_decls;
let needs_retag = |place: &Place<'tcx>| {
- // FIXME: Instead of giving up for unstable places, we should introduce
- // a temporary and retag on that.
- is_stable(place.as_ref())
+ !place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway
&& may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
&& !local_decls[place.local].is_deref_temp()
};
- let place_base_raw = |place: &Place<'tcx>| {
- // If this is a `Deref`, get the type of what we are deref'ing.
- if place.has_deref() {
- let ty = &local_decls[place.local].ty;
- ty.is_unsafe_ptr()
- } else {
- // Not a deref, and thus not raw.
- false
- }
- };
// PART 1
// Retag arguments at the beginning of the start block.
@@ -108,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
}
// PART 2
- // Retag return values of functions. Also escape-to-raw the argument of `drop`.
+ // Retag return values of functions.
// We collect the return destinations because we cannot mutate while iterating.
let returns = basic_blocks
.iter_mut()
@@ -140,30 +118,25 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
}
// PART 3
- // Add retag after assignment.
+ // Add retag after assignments where data "enters" this function: the RHS is behind a deref and the LHS is not.
for block_data in basic_blocks {
// We want to insert statements as we iterate. To this end, we
// iterate backwards using indices.
for i in (0..block_data.statements.len()).rev() {
let (retag_kind, place) = match block_data.statements[i].kind {
- // Retag-as-raw after escaping to a raw pointer, if the referent
- // is not already a raw pointer.
- StatementKind::Assign(box (lplace, Rvalue::AddressOf(_, ref rplace)))
- if !place_base_raw(rplace) =>
- {
- (RetagKind::Raw, lplace)
- }
// Retag after assignments of reference type.
StatementKind::Assign(box (ref place, ref rvalue)) if needs_retag(place) => {
- let kind = match rvalue {
- Rvalue::Ref(_, borrow_kind, _)
- if borrow_kind.allows_two_phase_borrow() =>
- {
- RetagKind::TwoPhase
- }
- _ => RetagKind::Default,
+ let add_retag = match rvalue {
+ // Ptr-creating operations already do their own internal retagging, no
+ // need to also add a retag statement.
+ Rvalue::Ref(..) | Rvalue::AddressOf(..) => false,
+ _ => true,
};
- (kind, *place)
+ if add_retag {
+ (RetagKind::Default, *place)
+ } else {
+ continue;
+ }
}
// Do nothing for the rest
_ => continue,