]> git.lizzy.rs Git - rust.git/commitdiff
Retagging: do not retag 'raw reborrows'
authorRalf Jung <post@ralfj.de>
Sat, 31 Oct 2020 12:57:56 +0000 (13:57 +0100)
committerRalf Jung <post@ralfj.de>
Sat, 31 Oct 2020 14:31:27 +0000 (15:31 +0100)
compiler/rustc_mir/src/transform/add_retag.rs

index eec704e6cb775224a5eb38970470f8ec2299487d..6fe9f64be32e8257298b5d327557e8b738bc5db9 100644 (file)
@@ -73,6 +73,19 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             // 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 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             // 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, _)