about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/lib.rs11
-rw-r--r--compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs21
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs7
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs18
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs55
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs4
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs1
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs7
-rw-r--r--compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_place.rs19
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/into.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs4
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs6
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs4
-rw-r--r--compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs12
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs12
-rw-r--r--compiler/rustc_span/src/hygiene.rs4
-rw-r--r--compiler/stable_mir/src/mir/body.rs22
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs14
-rw-r--r--compiler/stable_mir/src/mir/visit.rs2
-rw-r--r--src/tools/miri/tests/pass/disjoint-array-accesses.rs35
-rw-r--r--tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir2
-rw-r--r--tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir2
-rw-r--r--tests/mir-opt/building/index_array_and_slice.rs2
-rw-r--r--tests/mir-opt/issue_91633.foo.built.after.mir2
26 files changed, 199 insertions, 89 deletions
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 91dc76f597a..decfab502bb 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -1284,15 +1284,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
                 );
             }
 
-            &Rvalue::RawPtr(mutability, place) => {
-                let access_kind = match mutability {
-                    Mutability::Mut => (
+            &Rvalue::RawPtr(kind, place) => {
+                let access_kind = match kind {
+                    RawPtrKind::Mut => (
                         Deep,
                         Write(WriteKind::MutableBorrow(BorrowKind::Mut {
                             kind: MutBorrowKind::Default,
                         })),
                     ),
-                    Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
+                    RawPtrKind::Const => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
+                    RawPtrKind::FakeForPtrMetadata => {
+                        (Shallow(Some(ArtificialField::ArrayLength)), Read(ReadKind::Copy))
+                    }
                 };
 
                 self.access_place(
diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
index cbcfab1dc3e..f79bcf5af55 100644
--- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs
@@ -3,11 +3,7 @@ use std::ops::ControlFlow;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_middle::bug;
 use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{
-    self, BasicBlock, Body, BorrowKind, FakeBorrowKind, InlineAsmOperand, Location, Mutability,
-    NonDivergingIntrinsic, Operand, Place, Rvalue, Statement, StatementKind, Terminator,
-    TerminatorKind,
-};
+use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use tracing::debug;
 
@@ -60,7 +56,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
             StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => {
                 self.consume_operand(location, op);
             }
-            StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
+            StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
                 src,
                 dst,
                 count,
@@ -273,15 +269,18 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
                 self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
             }
 
-            &Rvalue::RawPtr(mutability, place) => {
-                let access_kind = match mutability {
-                    Mutability::Mut => (
+            &Rvalue::RawPtr(kind, place) => {
+                let access_kind = match kind {
+                    RawPtrKind::Mut => (
                         Deep,
                         Write(WriteKind::MutableBorrow(BorrowKind::Mut {
-                            kind: mir::MutBorrowKind::Default,
+                            kind: MutBorrowKind::Default,
                         })),
                     ),
-                    Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
+                    RawPtrKind::Const => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
+                    RawPtrKind::FakeForPtrMetadata => {
+                        (Shallow(Some(ArtificialField::ArrayLength)), Read(ReadKind::Copy))
+                    }
                 };
 
                 self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index e775d219c7b..d7fc5e8e673 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -612,9 +612,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             mir::Rvalue::CopyForDeref(place) => {
                 self.codegen_operand(bx, &mir::Operand::Copy(place))
             }
-            mir::Rvalue::RawPtr(mutability, place) => {
-                let mk_ptr =
-                    move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| Ty::new_ptr(tcx, ty, mutability);
+            mir::Rvalue::RawPtr(kind, place) => {
+                let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| {
+                    Ty::new_ptr(tcx, ty, kind.to_mutbl_lossy())
+                };
                 self.codegen_place_to_pointer(bx, place, mk_ptr)
             }
 
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index c3b609b642d..83850aef301 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -518,7 +518,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             }
 
             Rvalue::Ref(_, BorrowKind::Mut { .. }, place)
-            | Rvalue::RawPtr(Mutability::Mut, place) => {
+            | Rvalue::RawPtr(RawPtrKind::Mut, place) => {
                 // Inside mutable statics, we allow arbitrary mutable references.
                 // We've allowed `static mut FOO = &mut [elements];` for a long time (the exact
                 // reasons why are lost to history), and there is no reason to restrict that to
@@ -536,7 +536,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             }
 
             Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Fake(_), place)
-            | Rvalue::RawPtr(Mutability::Not, place) => {
+            | Rvalue::RawPtr(RawPtrKind::Const, place) => {
                 let borrowed_place_has_mut_interior = qualifs::in_place::<HasMutInterior, _>(
                     self.ccx,
                     &mut |local| self.qualifs.has_mut_interior(self.ccx, local, location),
@@ -548,6 +548,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 }
             }
 
+            Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, place) => {
+                // These are only inserted for slice length, so the place must already be indirect.
+                // This implies we do not have to worry about whether the borrow escapes.
+                assert!(place.is_indirect(), "fake borrows are always indirect");
+            }
+
             Rvalue::Cast(
                 CastKind::PointerCoercion(
                     PointerCoercion::MutToConstPointer
@@ -600,12 +606,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         }
                     }
                     UnOp::PtrMetadata => {
-                        if !ty.is_ref() && !ty.is_unsafe_ptr() {
-                            span_bug!(
-                                self.span,
-                                "non-pointer type in `Rvalue::UnaryOp({op:?})`: {ty:?}",
-                            );
-                        }
+                        // Getting the metadata from a pointer is always const.
+                        // We already validated the type is valid in the validator.
                     }
                 }
             }
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index a26c2eca107..d9c0ff5acd1 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -9,7 +9,6 @@ use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::{bug, mir, span_bug};
 use rustc_span::source_map::Spanned;
-use rustc_span::{DesugaringKind, Span};
 use rustc_target::callconv::FnAbi;
 use tracing::{info, instrument, trace};
 
@@ -81,9 +80,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         use rustc_middle::mir::StatementKind::*;
 
         match &stmt.kind {
-            Assign(box (place, rvalue)) => {
-                self.eval_rvalue_into_place(rvalue, *place, stmt.source_info.span)?
-            }
+            Assign(box (place, rvalue)) => self.eval_rvalue_into_place(rvalue, *place)?,
 
             SetDiscriminant { place, variant_index } => {
                 let dest = self.eval_place(**place)?;
@@ -162,7 +159,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         &mut self,
         rvalue: &mir::Rvalue<'tcx>,
         place: mir::Place<'tcx>,
-        span: Span,
     ) -> InterpResult<'tcx> {
         let dest = self.eval_place(place)?;
         // FIXME: ensure some kind of non-aliasing between LHS and RHS?
@@ -241,7 +237,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 self.write_immediate(*val, &dest)?;
             }
 
-            RawPtr(_, place) => {
+            RawPtr(kind, place) => {
                 // Figure out whether this is an addr_of of an already raw place.
                 let place_base_raw = if place.is_indirect_first_projection() {
                     let ty = self.frame().body.local_decls[place.local].ty;
@@ -254,13 +250,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let src = self.eval_place(place)?;
                 let place = self.force_allocation(&src)?;
                 let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
-                if !place_base_raw
-                    && span.desugaring_kind() != Some(DesugaringKind::IndexBoundsCheckReborrow)
-                {
-                    // If this was not already raw, it needs retagging.
-                    // As a special hack, we exclude the desugared `PtrMetadata(&raw const *_n)`
-                    // from indexing. (Really we should not do any retag on `&raw` but that does not
-                    // currently work with Stacked Borrows.)
+                if !place_base_raw && !kind.is_fake() {
+                    // If this was not already raw, it needs retagging -- except for "fake"
+                    // raw borrows whose defining property is that they do not get retagged.
                     val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
                 }
                 self.write_immediate(*val, &dest)?;
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 29ae2e1bd6b..5868b64f6b5 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -182,6 +182,59 @@ pub enum BorrowKind {
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
 #[derive(Hash, HashStable)]
+pub enum RawPtrKind {
+    Mut,
+    Const,
+    /// Creates a raw pointer to a place that will only be used to access its metadata,
+    /// not the data behind the pointer. Note that this limitation is *not* enforced
+    /// by the validator.
+    ///
+    /// The borrow checker allows overlap of these raw pointers with references to the
+    /// data. This is sound even if the pointer is "misused" since any such use is anyway
+    /// unsafe. In terms of the operational semantics (i.e., Miri), this is equivalent
+    /// to `RawPtrKind::Mut`, but will never incur a retag.
+    FakeForPtrMetadata,
+}
+
+impl From<Mutability> for RawPtrKind {
+    fn from(other: Mutability) -> Self {
+        match other {
+            Mutability::Mut => RawPtrKind::Mut,
+            Mutability::Not => RawPtrKind::Const,
+        }
+    }
+}
+
+impl RawPtrKind {
+    pub fn is_fake(self) -> bool {
+        match self {
+            RawPtrKind::Mut | RawPtrKind::Const => false,
+            RawPtrKind::FakeForPtrMetadata => true,
+        }
+    }
+
+    pub fn to_mutbl_lossy(self) -> Mutability {
+        match self {
+            RawPtrKind::Mut => Mutability::Mut,
+            RawPtrKind::Const => Mutability::Not,
+
+            // We have no type corresponding to a fake borrow, so use
+            // `*const` as an approximation.
+            RawPtrKind::FakeForPtrMetadata => Mutability::Not,
+        }
+    }
+
+    pub fn ptr_str(self) -> &'static str {
+        match self {
+            RawPtrKind::Mut => "mut",
+            RawPtrKind::Const => "const",
+            RawPtrKind::FakeForPtrMetadata => "const (fake)",
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(Hash, HashStable)]
 pub enum MutBorrowKind {
     Default,
     /// This borrow arose from method-call auto-ref. (i.e., `adjustment::Adjust::Borrow`)
@@ -1356,7 +1409,7 @@ pub enum Rvalue<'tcx> {
     ///
     /// Like with references, the semantics of this operation are heavily dependent on the aliasing
     /// model.
-    RawPtr(Mutability, Place<'tcx>),
+    RawPtr(RawPtrKind, Place<'tcx>),
 
     /// Yields the length of the place, as a `usize`.
     ///
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index db77017310a..4d11492e94d 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -206,9 +206,9 @@ impl<'tcx> Rvalue<'tcx> {
                 let place_ty = place.ty(local_decls, tcx).ty;
                 Ty::new_ref(tcx, reg, place_ty, bk.to_mutbl_lossy())
             }
-            Rvalue::RawPtr(mutability, ref place) => {
+            Rvalue::RawPtr(kind, ref place) => {
                 let place_ty = place.ty(local_decls, tcx).ty;
-                Ty::new_ptr(tcx, place_ty, mutability)
+                Ty::new_ptr(tcx, place_ty, kind.to_mutbl_lossy())
             }
             Rvalue::Len(..) => tcx.types.usize,
             Rvalue::Cast(.., ty) => ty,
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index b798f078800..b59b9e55fe8 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -15,6 +15,7 @@ TrivialTypeTraversalImpls! {
     SourceScopeLocalData,
     UserTypeAnnotationIndex,
     BorrowKind,
+    RawPtrKind,
     CastKind,
     BasicBlock,
     SwitchTargets,
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 058acbd4024..95de08ce9c8 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -685,12 +685,15 @@ macro_rules! make_mir_visitor {
 
                     Rvalue::RawPtr(m, path) => {
                         let ctx = match m {
-                            Mutability::Mut => PlaceContext::MutatingUse(
+                            RawPtrKind::Mut => PlaceContext::MutatingUse(
                                 MutatingUseContext::RawBorrow
                             ),
-                            Mutability::Not => PlaceContext::NonMutatingUse(
+                            RawPtrKind::Const => PlaceContext::NonMutatingUse(
                                 NonMutatingUseContext::RawBorrow
                             ),
+                            RawPtrKind::FakeForPtrMetadata => PlaceContext::NonMutatingUse(
+                                NonMutatingUseContext::Inspect
+                            ),
                         };
                         self.visit_place(path, ctx, location);
                     }
diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
index 59f440432eb..eab414e150f 100644
--- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs
@@ -253,7 +253,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
                 Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
             ),
             ExprKind::RawBorrow { mutability, arg } => Ok(
-                Rvalue::RawPtr(*mutability, self.parse_place(*arg)?)
+                Rvalue::RawPtr((*mutability).into(), self.parse_place(*arg)?)
             ),
             ExprKind::Binary { op, lhs, rhs } =>  Ok(
                 Rvalue::BinaryOp(*op, Box::new((self.parse_operand(*lhs)?, self.parse_operand(*rhs)?)))
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
index 7634bc74fcb..0086775e9f4 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::{self, AdtDef, CanonicalUserTypeAnnotation, Ty, Variance};
 use rustc_middle::{bug, span_bug};
-use rustc_span::{DesugaringKind, Span};
+use rustc_span::Span;
 use tracing::{debug, instrument, trace};
 
 use crate::builder::ForGuard::{OutsideGuard, RefWithinGuard};
@@ -643,8 +643,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         source_info: SourceInfo,
     ) -> Operand<'tcx> {
         let place_ty = place.ty(&self.local_decls, self.tcx).ty;
-        let usize_ty = self.tcx.types.usize;
-
         match place_ty.kind() {
             ty::Array(_elem_ty, len_const) => {
                 // We know how long an array is, so just use that as a constant
@@ -668,27 +666,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     // the MIR we're building here needs to pass NLL later.
                     Operand::Copy(Place::from(place.local))
                 } else {
-                    let len_span = self.tcx.with_stable_hashing_context(|hcx| {
-                        let span = source_info.span;
-                        span.mark_with_reason(
-                            None,
-                            DesugaringKind::IndexBoundsCheckReborrow,
-                            span.edition(),
-                            hcx,
-                        )
-                    });
                     let ptr_ty = Ty::new_imm_ptr(self.tcx, place_ty);
                     let slice_ptr = self.temp(ptr_ty, span);
                     self.cfg.push_assign(
                         block,
-                        SourceInfo { span: len_span, ..source_info },
+                        source_info,
                         slice_ptr,
-                        Rvalue::RawPtr(Mutability::Not, place),
+                        Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, place),
                     );
                     Operand::Move(slice_ptr)
                 };
 
-                let len = self.temp(usize_ty, span);
+                let len = self.temp(self.tcx.types.usize, span);
                 self.cfg.push_assign(
                     block,
                     source_info,
diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs
index 88f63d4e22c..928156572d5 100644
--- a/compiler/rustc_mir_build/src/builder/expr/into.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/into.rs
@@ -303,7 +303,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     hir::Mutability::Not => this.as_read_only_place(block, arg),
                     hir::Mutability::Mut => this.as_place(block, arg),
                 };
-                let address_of = Rvalue::RawPtr(mutability, unpack!(block = place));
+                let address_of = Rvalue::RawPtr(mutability.into(), unpack!(block = place));
                 this.cfg.push_assign(block, source_info, destination, address_of);
                 block.unit()
             }
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index f8a84674947..74b0e84068c 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -700,7 +700,7 @@ where
             statements: vec![
                 self.assign(
                     ptr,
-                    Rvalue::RawPtr(Mutability::Mut, tcx.mk_place_index(self.place, cur)),
+                    Rvalue::RawPtr(RawPtrKind::Mut, tcx.mk_place_index(self.place, cur)),
                 ),
                 self.assign(
                     cur.into(),
@@ -816,7 +816,7 @@ where
 
         let mut delegate_block = BasicBlockData {
             statements: vec![
-                self.assign(Place::from(array_ptr), Rvalue::RawPtr(Mutability::Mut, self.place)),
+                self.assign(Place::from(array_ptr), Rvalue::RawPtr(RawPtrKind::Mut, self.place)),
                 self.assign(
                     Place::from(slice_ptr),
                     Rvalue::Cast(
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 1c2c82d4cd5..16e15fa12e0 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -192,7 +192,7 @@ enum AggregateTy<'tcx> {
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 enum AddressKind {
     Ref(BorrowKind),
-    Address(Mutability),
+    Address(RawPtrKind),
 }
 
 #[derive(Debug, PartialEq, Eq, Hash)]
@@ -504,7 +504,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                         mplace.layout.ty,
                         bk.to_mutbl_lossy(),
                     ),
-                    AddressKind::Address(mutbl) => Ty::new_ptr(self.tcx, mplace.layout.ty, mutbl),
+                    AddressKind::Address(mutbl) => {
+                        Ty::new_ptr(self.tcx, mplace.layout.ty, mutbl.to_mutbl_lossy())
+                    }
                 };
                 let layout = self.ecx.layout_of(ty).ok()?;
                 ImmTy::from_immediate(pointer, layout).into()
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index e201763468b..1e546bfbeb3 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -125,7 +125,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
                     source_info,
                     kind: StatementKind::Assign(Box::new((
                         dst,
-                        Rvalue::RawPtr(Mutability::Mut, *lhs),
+                        Rvalue::RawPtr(RawPtrKind::Mut, *lhs),
                     ))),
                 };
 
@@ -146,7 +146,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
                     source_info,
                     kind: StatementKind::Assign(Box::new((
                         src,
-                        Rvalue::RawPtr(Mutability::Not, *rhs),
+                        Rvalue::RawPtr(RawPtrKind::Const, *rhs),
                     ))),
                 };
 
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index f01bab75c4a..1d53440cf0b 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -2,17 +2,11 @@ use std::iter;
 
 use itertools::Itertools;
 use rustc_abi::{FieldIdx, VariantIdx};
-use rustc_ast::Mutability;
 use rustc_const_eval::interpret;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::{Idx, IndexVec};
-use rustc_middle::mir::{
-    BasicBlock, BasicBlockData, Body, CallSource, CastKind, CoercionSource, Const, ConstOperand,
-    ConstValue, Local, LocalDecl, MirSource, Operand, Place, PlaceElem, RETURN_PLACE, Rvalue,
-    SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnwindAction,
-    UnwindTerminateReason,
-};
+use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::util::{AsyncDropGlueMorphology, Discr};
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -345,7 +339,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
                 .tcx
                 .mk_place_elems(&[PlaceElem::Deref, PlaceElem::Field(field, field_ty)]),
         };
-        self.put_temp_rvalue(Rvalue::RawPtr(Mutability::Mut, place))
+        self.put_temp_rvalue(Rvalue::RawPtr(RawPtrKind::Mut, place))
     }
 
     /// If given Self is an enum puts `to_drop: *mut FieldTy` on top of
@@ -365,7 +359,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
                 PlaceElem::Field(field, field_ty),
             ]),
         };
-        self.put_temp_rvalue(Rvalue::RawPtr(Mutability::Mut, place))
+        self.put_temp_rvalue(Rvalue::RawPtr(RawPtrKind::Mut, place))
     }
 
     /// If given Self is an enum puts `to_drop: *mut FieldTy` on top of
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index a5a17b4b573..aee98d7d410 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -232,6 +232,18 @@ impl<'tcx> Stable<'tcx> for mir::Mutability {
     }
 }
 
+impl<'tcx> Stable<'tcx> for mir::RawPtrKind {
+    type T = stable_mir::mir::RawPtrKind;
+    fn stable(&self, _: &mut Tables<'_>) -> Self::T {
+        use mir::RawPtrKind::*;
+        match *self {
+            Const => stable_mir::mir::RawPtrKind::Const,
+            Mut => stable_mir::mir::RawPtrKind::Mut,
+            FakeForPtrMetadata => stable_mir::mir::RawPtrKind::FakeForPtrMetadata,
+        }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for mir::BorrowKind {
     type T = stable_mir::mir::BorrowKind;
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 3cdae437b7d..a5826137181 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1163,9 +1163,6 @@ pub enum DesugaringKind {
     WhileLoop,
     /// `async Fn()` bound modifier
     BoundModifier,
-    /// Marks a `&raw const *_1` needed as part of getting the length of a mutable
-    /// slice for the bounds check, so that MIRI's retag handling can recognize it.
-    IndexBoundsCheckReborrow,
 }
 
 impl DesugaringKind {
@@ -1182,7 +1179,6 @@ impl DesugaringKind {
             DesugaringKind::ForLoop => "`for` loop",
             DesugaringKind::WhileLoop => "`while` loop",
             DesugaringKind::BoundModifier => "trait bound modifier",
-            DesugaringKind::IndexBoundsCheckReborrow => "slice indexing",
         }
     }
 }
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index dfd090b3956..8686169c15d 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -457,7 +457,7 @@ pub enum Rvalue {
     ///
     /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like
     /// `&raw v` or `addr_of!(v)`.
-    AddressOf(Mutability, Place),
+    AddressOf(RawPtrKind, Place),
 
     /// Creates an aggregate value, like a tuple or struct.
     ///
@@ -577,7 +577,7 @@ impl Rvalue {
             }
             Rvalue::AddressOf(mutability, place) => {
                 let place_ty = place.ty(locals)?;
-                Ok(Ty::new_ptr(place_ty, *mutability))
+                Ok(Ty::new_ptr(place_ty, mutability.to_mutable_lossy()))
             }
             Rvalue::Len(..) => Ok(Ty::usize_ty()),
             Rvalue::Cast(.., ty) => Ok(*ty),
@@ -904,6 +904,24 @@ impl BorrowKind {
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
+pub enum RawPtrKind {
+    Mut,
+    Const,
+    FakeForPtrMetadata,
+}
+
+impl RawPtrKind {
+    pub fn to_mutable_lossy(self) -> Mutability {
+        match self {
+            RawPtrKind::Mut { .. } => Mutability::Mut,
+            RawPtrKind::Const => Mutability::Not,
+            // FIXME: There's no type corresponding to a shallow borrow, so use `&` as an approximation.
+            RawPtrKind::FakeForPtrMetadata => Mutability::Not,
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
 pub enum MutBorrowKind {
     Default,
     TwoPhaseBorrow,
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 93ed32e258a..81981bce202 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -6,7 +6,9 @@ use std::{fmt, io, iter};
 use fmt::{Display, Formatter};
 
 use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind};
-use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents};
+use crate::mir::{
+    Operand, Place, RawPtrKind, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents,
+};
 use crate::ty::{AdtKind, IndexedVal, MirConst, Ty, TyConst};
 use crate::{Body, CrateDef, Mutability, with};
 
@@ -325,7 +327,7 @@ fn pretty_ty_const(ct: &TyConst) -> String {
 fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
     match rval {
         Rvalue::AddressOf(mutability, place) => {
-            write!(writer, "&raw {} {:?}", pretty_mut(*mutability), place)
+            write!(writer, "&raw {} {:?}", pretty_raw_ptr_kind(*mutability), place)
         }
         Rvalue::Aggregate(aggregate_kind, operands) => {
             // FIXME: Add pretty_aggregate function that returns a pretty string
@@ -437,3 +439,11 @@ fn pretty_mut(mutability: Mutability) -> &'static str {
         Mutability::Mut => "mut ",
     }
 }
+
+fn pretty_raw_ptr_kind(kind: RawPtrKind) -> &'static str {
+    match kind {
+        RawPtrKind::Const => "const",
+        RawPtrKind::Mut => "mut",
+        RawPtrKind::FakeForPtrMetadata => "const (fake)",
+    }
+}
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index d73e79c4893..79efb83cebd 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -308,7 +308,7 @@ pub trait MirVisitor {
     fn super_rvalue(&mut self, rvalue: &Rvalue, location: Location) {
         match rvalue {
             Rvalue::AddressOf(mutability, place) => {
-                let pcx = PlaceContext { is_mut: *mutability == Mutability::Mut };
+                let pcx = PlaceContext { is_mut: *mutability == RawPtrKind::Mut };
                 self.visit_place(place, pcx, location);
             }
             Rvalue::Aggregate(_, operands) => {
diff --git a/src/tools/miri/tests/pass/disjoint-array-accesses.rs b/src/tools/miri/tests/pass/disjoint-array-accesses.rs
new file mode 100644
index 00000000000..50d0ea52ad4
--- /dev/null
+++ b/src/tools/miri/tests/pass/disjoint-array-accesses.rs
@@ -0,0 +1,35 @@
+// This is a regression test for issue #135671 where a MIR refactor about arrays and their lengths
+// unexpectedly caused borrowck errors for disjoint borrows of array elements, for which we had no
+// tests. This is a collection of a few code samples from that issue.
+
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+
+struct Test {
+    a: i32,
+    b: i32,
+}
+
+fn one() {
+    let inputs: &mut [_] = &mut [Test { a: 0, b: 0 }];
+    let a = &mut inputs[0].a;
+    let b = &mut inputs[0].b;
+
+    *a = 0;
+    *b = 1;
+}
+
+fn two() {
+    let slice = &mut [(0, 0)][..];
+    std::mem::swap(&mut slice[0].0, &mut slice[0].1);
+}
+
+fn three(a: &mut [(i32, i32)], i: usize, j: usize) -> (&mut i32, &mut i32) {
+    (&mut a[i].0, &mut a[j].1)
+}
+
+fn main() {
+    one();
+    two();
+    three(&mut [(1, 2), (3, 4)], 0, 1);
+}
diff --git a/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir
index 00f2b7e07d5..e6745ddbf29 100644
--- a/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir
+++ b/tests/mir-opt/building/index_array_and_slice.index_custom.built.after.mir
@@ -14,7 +14,7 @@ fn index_custom(_1: &WithSliceTail, _2: usize) -> &i32 {
         StorageLive(_3);
         StorageLive(_4);
         _4 = copy _2;
-        _5 = &raw const ((*_1).1: [i32]);
+        _5 = &raw const (fake) ((*_1).1: [i32]);
         _6 = PtrMetadata(move _5);
         _7 = Lt(copy _4, copy _6);
         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _4) -> [success: bb1, unwind: bb2];
diff --git a/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir b/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir
index cb0b2f600c8..c96bcdfc918 100644
--- a/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir
+++ b/tests/mir-opt/building/index_array_and_slice.index_mut_slice.built.after.mir
@@ -14,7 +14,7 @@ fn index_mut_slice(_1: &mut [i32], _2: usize) -> &i32 {
         StorageLive(_3);
         StorageLive(_4);
         _4 = copy _2;
-        _5 = &raw const (*_1);
+        _5 = &raw const (fake) (*_1);
         _6 = PtrMetadata(move _5);
         _7 = Lt(copy _4, copy _6);
         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _4) -> [success: bb1, unwind: bb2];
diff --git a/tests/mir-opt/building/index_array_and_slice.rs b/tests/mir-opt/building/index_array_and_slice.rs
index 16d0b983132..f91b37567f7 100644
--- a/tests/mir-opt/building/index_array_and_slice.rs
+++ b/tests/mir-opt/building/index_array_and_slice.rs
@@ -54,7 +54,7 @@ struct WithSliceTail(f64, [i32]);
 // EMIT_MIR index_array_and_slice.index_custom.built.after.mir
 fn index_custom(custom: &WithSliceTail, index: usize) -> &i32 {
     // CHECK: bb0:
-    // CHECK: [[PTR:_.+]] = &raw const ((*_1).1: [i32]);
+    // CHECK: [[PTR:_.+]] = &raw const (fake) ((*_1).1: [i32]);
     // CHECK: [[LEN:_.+]] = PtrMetadata(move [[PTR]]);
     // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
     // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
diff --git a/tests/mir-opt/issue_91633.foo.built.after.mir b/tests/mir-opt/issue_91633.foo.built.after.mir
index bf65b5b4a8c..53f48350596 100644
--- a/tests/mir-opt/issue_91633.foo.built.after.mir
+++ b/tests/mir-opt/issue_91633.foo.built.after.mir
@@ -18,7 +18,7 @@ fn foo(_1: Box<[T]>) -> T {
         StorageLive(_3);
         StorageLive(_4);
         _4 = const 0_usize;
-        _5 = &raw const (*_1);
+        _5 = &raw const (fake) (*_1);
         _6 = PtrMetadata(move _5);
         _7 = Lt(copy _4, copy _6);
         assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, copy _4) -> [success: bb1, unwind: bb5];