diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 91dc76f597ad7..decfab502bb59 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 cbcfab1dc3e11..f79bcf5af5564 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 cb4862663fda7..d3b0fac0cf07e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -623,9 +623,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 c3b609b642df0..ae073bed8be9f 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::( self.ccx, &mut |local| self.qualifs.has_mut_interior(self.ccx, local, location), @@ -548,6 +548,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } + Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, place) => { + assert!( + !self.place_may_escape(place), + "fake borrows may not escape the body of the const" + ); + } + Rvalue::Cast( CastKind::PointerCoercion( PointerCoercion::MutToConstPointer @@ -600,12 +607,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 a26c2eca107c5..d9c0ff5acd116 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 0c17a2e0fe5a1..62b4a4b725109 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -180,6 +180,59 @@ pub enum BorrowKind { Mut { kind: MutBorrowKind }, } +#[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 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 { @@ -1349,7 +1402,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 db77017310af3..4d11492e94d31 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 b798f0788007f..b59b9e55fe8a0 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 058acbd4024d1..95de08ce9c874 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 59f440432ebc1..eab414e150fa3 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 2c88a48424fe2..909530847cdd9 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 @@ -653,7 +651,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // though. FIXME: Do we really *need* to count this as a use? // Could partial array tracking work off something else instead? self.cfg.push_fake_read(block, source_info, FakeReadCause::ForIndex, place); - let const_ = Const::from_ty_const(*len_const, usize_ty, self.tcx); + let const_ = Const::from_ty_const(*len_const, self.tcx.types.usize, self.tcx); Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_ })) } ty::Slice(_elem_ty) => { @@ -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 88f63d4e22cbd..928156572d50a 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 f8a8467494753..74b0e84068c67 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 cb03b422d9e38..5f983858aa987 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -188,7 +188,7 @@ enum AggregateTy<'tcx> { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] enum AddressKind { Ref(BorrowKind), - Address(Mutability), + Address(RawPtrKind), } #[derive(Debug, PartialEq, Eq, Hash)] @@ -500,7 +500,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 490e7dd8f7e07..a0ed352759781 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 f01bab75c4a1d..1d53440cf0bad 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 a5a17b4b5730e..aee98d7d410ea 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 3cdae437b7d46..a5826137181db 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 dfd090b39563f..8686169c15d66 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), @@ -903,6 +903,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, diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 93ed32e258a8b..81981bce2026f 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(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 d73e79c48937e..79efb83cebdec 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 0000000000000..50d0ea52ad4a1 --- /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 00f2b7e07d551..e6745ddbf298a 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 cb0b2f600c81a..c96bcdfc918ad 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 16d0b983132df..f91b37567f79b 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 bf65b5b4a8ccb..53f48350596ee 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];