about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2020-10-31 13:57:56 +0100
committerRalf Jung <post@ralfj.de>2020-10-31 15:31:27 +0100
commit289c0d8489d02c1bc5cb0b091455fe03cd9384bd (patch)
tree952366474cd9883690d57ee82adb2a69fcf6bb6c
parent3478d7c3607ffbba629af2265c01002771e48c18 (diff)
downloadrust-289c0d8489d02c1bc5cb0b091455fe03cd9384bd.tar.gz
rust-289c0d8489d02c1bc5cb0b091455fe03cd9384bd.zip
Retagging: do not retag 'raw reborrows'
-rw-r--r--compiler/rustc_mir/src/transform/add_retag.rs26
1 files changed, 20 insertions, 6 deletions
diff --git a/compiler/rustc_mir/src/transform/add_retag.rs b/compiler/rustc_mir/src/transform/add_retag.rs
index eec704e6cb7..6fe9f64be32 100644
--- a/compiler/rustc_mir/src/transform/add_retag.rs
+++ b/compiler/rustc_mir/src/transform/add_retag.rs
@@ -73,6 +73,19 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
             // a temporary and retag on that.
             is_stable(place.as_ref()) && may_be_reference(place.ty(&*local_decls, tcx).ty)
         };
+        let place_base_raw = |place: &Place<'tcx>| {
+            // If this is a `Deref`, get the type of what we are deref'ing.
+            let deref_base =
+                place.projection.iter().rposition(|p| matches!(p, ProjectionElem::Deref));
+            if let Some(deref_base) = deref_base {
+                let base_proj = &place.projection[..deref_base];
+                let ty = Place::ty_from(place.local, base_proj, &*local_decls, tcx).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.
@@ -136,13 +149,14 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
             // 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.
-                    StatementKind::Assign(box (place, Rvalue::AddressOf(..))) => {
-                        (RetagKind::Raw, place)
+                    // 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)
                     }
-                    // Assignments of reference or ptr type are the ones where we may have
-                    // to update tags.  This includes `x = &[mut] ...` and hence
-                    // we also retag after taking a reference!
+                    // 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, _)