about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-11-16 10:55:02 +0100
committerRalf Jung <post@ralfj.de>2022-11-17 11:58:14 +0100
commitf1a87014820ba13b3c2fd47749e480cc545c4d45 (patch)
treeeb926fc50d183c2ad076d1a08e0b15c6a440f36e
parentafab05b931631185270c3a2890c85645a42594bb (diff)
downloadrust-f1a87014820ba13b3c2fd47749e480cc545c4d45.tar.gz
rust-f1a87014820ba13b3c2fd47749e480cc545c4d45.zip
clean up retagging recursive traversal a bit
-rw-r--r--src/tools/miri/src/stacked_borrows/mod.rs97
1 files changed, 49 insertions, 48 deletions
diff --git a/src/tools/miri/src/stacked_borrows/mod.rs b/src/tools/miri/src/stacked_borrows/mod.rs
index 9ce02a02ec4..f2e2df5ad08 100644
--- a/src/tools/miri/src/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/stacked_borrows/mod.rs
@@ -14,7 +14,6 @@ use rustc_middle::mir::RetagKind;
 use rustc_middle::ty::{
     self,
     layout::{HasParamEnv, LayoutOf},
-    Ty,
 };
 use rustc_target::abi::Abi;
 use rustc_target::abi::Size;
@@ -983,28 +982,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
         return visitor.visit_value(place);
 
-        // Determine mutability and whether to add a protector.
-        // Cannot use `builtin_deref` because that reports *immutable* for `Box`,
-        // making it useless.
-        fn qualify(ty: Ty<'_>, kind: RetagKind) -> Option<(RefKind, bool)> {
-            match ty.kind() {
-                // References are simple.
-                ty::Ref(_, _, Mutability::Mut) =>
-                    Some((
-                        RefKind::Unique { two_phase: kind == RetagKind::TwoPhase },
-                        kind == RetagKind::FnEntry,
-                    )),
-                ty::Ref(_, _, Mutability::Not) =>
-                    Some((RefKind::Shared, kind == RetagKind::FnEntry)),
-                // Raw pointers need to be enabled.
-                ty::RawPtr(tym) if kind == RetagKind::Raw =>
-                    Some((RefKind::Raw { mutable: tym.mutbl == Mutability::Mut }, false)),
-                // Boxes are handled separately due to that allocator situation,
-                // see the visitor below.
-                _ => None,
-            }
-        }
-
         // The actual visitor.
         struct RetagVisitor<'ecx, 'mir, 'tcx> {
             ecx: &'ecx mut MiriInterpCx<'mir, 'tcx>,
@@ -1057,34 +1034,58 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     return Ok(());
                 }
 
-                let recurse_for_fields = || {
-                    match self.retag_fields {
-                        RetagFields::No => false,
-                        RetagFields::Yes => true,
-                        RetagFields::OnlyScalar => {
-                            // Matching `ArgAbi::new` at the time of writing, only fields of
-                            // `Scalar` and `ScalarPair` ABI are considered.
-                            matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
+                // Check the type of this value to see what to do with it (retag, or recurse).
+                match place.layout.ty.kind() {
+                    ty::Ref(_, _, mutbl) => {
+                        let ref_kind = match mutbl {
+                            Mutability::Mut =>
+                                RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase },
+                            Mutability::Not => RefKind::Shared,
+                        };
+                        self.retag_place(
+                            place,
+                            ref_kind,
+                            self.retag_cause,
+                            /*protector*/ self.kind == RetagKind::FnEntry,
+                        )?;
+                    }
+                    ty::RawPtr(tym) => {
+                        // We definitely do *not* want to recurse into raw pointers -- wide raw
+                        // pointers have fields, and for dyn Trait pointees those can have reference
+                        // type!
+                        if self.kind == RetagKind::Raw {
+                            // Raw pointers need to be enabled.
+                            self.retag_place(
+                                place,
+                                RefKind::Raw { mutable: tym.mutbl == Mutability::Mut },
+                                self.retag_cause,
+                                /*protector*/ false,
+                            )?;
+                        }
+                    }
+                    _ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => {
+                        // Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
+                        // (Yes this means we technically also recursively retag the allocator itself
+                        // even if field retagging is not enabled. *shrug*)
+                        self.walk_value(place)?;
+                    }
+                    _ => {
+                        // Not a reference/pointer/box. Only recurse if configured appropriately.
+                        let recurse = match self.retag_fields {
+                            RetagFields::No => false,
+                            RetagFields::Yes => true,
+                            RetagFields::OnlyScalar => {
+                                // Matching `ArgAbi::new` at the time of writing, only fields of
+                                // `Scalar` and `ScalarPair` ABI are considered.
+                                matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
+                            }
+                        };
+                        if recurse {
+                            self.walk_value(place)?;
                         }
                     }
-                };
-
-                if let Some((ref_kind, protector)) = qualify(place.layout.ty, self.kind) {
-                    self.retag_place(place, ref_kind, self.retag_cause, protector)?;
-                } else if matches!(place.layout.ty.kind(), ty::RawPtr(..)) {
-                    // Wide raw pointers *do* have fields and their types are strange.
-                    // vtables have a type like `&[*const (); 3]` or so!
-                    // Do *not* recurse into them.
-                    // (No need to worry about wide references, those always "qualify". And Boxes
-                    // are handles specially by the visitor anyway.)
-                } else if recurse_for_fields()
-                    || place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box())
-                {
-                    // Recurse deeper. Need to always recurse for `Box` to even hit `visit_box`.
-                    // (Yes this means we technically also recursively retag the allocator itself
-                    // even if field retagging is not enabled. *shrug*)
-                    self.walk_value(place)?;
                 }
+
                 Ok(())
             }
         }