diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index adc100941a39a..7e4b6901e0f0b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1108,7 +1108,7 @@ pub enum LocalInfo<'tcx> { /// A temporary created during evaluating `if` predicate, possibly for pattern matching for `let`s, /// and subject to Edition 2024 temporary lifetime rules IfThenRescopeTemp { if_then: HirId }, - /// A temporary created during the pass `Derefer` to avoid it's retagging + /// A temporary created during the pass `Derefer` to avoid its retagging DerefTemp, /// A temporary created for borrow checking. FakeBorrow, diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index e5a28d1b66c8c..621b44708674d 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -4,7 +4,6 @@ //! of MIR building, and only after this pass we think of the program has having the //! normal MIR semantics. -use rustc_hir::LangItem; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -28,7 +27,6 @@ fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> b // References and Boxes (`noalias` sources) ty::Ref(..) => true, ty::Adt(..) if ty.is_box() => true, - ty::Adt(adt, _) if tcx.is_lang_item(adt.did(), LangItem::PtrUnique) => true, // Compound types: recurse ty::Array(ty, _) | ty::Slice(ty) => { // This does not branch so we keep the depth the same. @@ -153,6 +151,13 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { } } Rvalue::Ref(..) => None, + // Also skip coercions whose source is already a local. This is crucial + // to avoid unnecessary retags in `my_array.len()` calls. + Rvalue::Cast( + CastKind::PointerCoercion(_, CoercionSource::Implicit), + Operand::Copy(p) | Operand::Move(p), + _, + ) if p.as_local().is_some() => None, _ => { if needs_retag(place) { Some(RetagKind::Default) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index d26e44687157b..cbb913ef76f0b 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -628,6 +628,7 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let passes: &[&dyn MirPass<'tcx>] = &[ &lower_intrinsics::LowerIntrinsics, + &lower_slice_len::LowerSliceLenCalls, &remove_place_mention::RemovePlaceMention, &simplify::SimplifyCfg::PreOptimizations, ]; @@ -671,9 +672,6 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' &check_null::CheckNull, // Before inlining: trim down MIR with passes to reduce inlining work. - // Has to be done before inlining, otherwise actual call will be almost always inlined. - // Also simple, so can just do first. - &lower_slice_len::LowerSliceLenCalls, // Perform instsimplify before inline to eliminate some trivial calls (like clone // shims). &instsimplify::InstSimplify::BeforeInline, diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index aca80e36e339d..30fcdb3b90e74 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -2,14 +2,18 @@ //! It should run before inlining! use rustc_hir::def_id::DefId; +use rustc_index::IndexVec; use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::adjustment::PointerCoercion; +use rustc_middle::ty::{Ty, TyCtxt}; pub(super) struct LowerSliceLenCalls; impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() > 0 + // This pass also removes some otherwise-problematic retags, so we + // always enable it when retags matter. + sess.mir_opt_level() > 0 || sess.opts.unstable_opts.mir_emit_retag } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -23,7 +27,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); for block in basic_blocks { // lower `<[_]>::len` calls - lower_slice_len_call(block, slice_len_fn_item_def_id); + lower_slice_len_call(tcx, &mut body.local_decls, block, slice_len_fn_item_def_id); } } @@ -32,7 +36,12 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { } } -fn lower_slice_len_call<'tcx>(block: &mut BasicBlockData<'tcx>, slice_len_fn_item_def_id: DefId) { +fn lower_slice_len_call<'tcx>( + tcx: TyCtxt<'tcx>, + local_decls: &mut IndexVec>, + block: &mut BasicBlockData<'tcx>, + slice_len_fn_item_def_id: DefId, +) { let terminator = block.terminator(); if let TerminatorKind::Call { func, @@ -50,11 +59,12 @@ fn lower_slice_len_call<'tcx>(block: &mut BasicBlockData<'tcx>, slice_len_fn_ite // perform modifications from something like: // _5 = core::slice::::len(move _6) -> bb1 // into: - // _5 = PtrMetadata(move _6) + // _5 = PtrMetadata(move _6); // goto bb1 // make new RValue for Len - let r_value = Rvalue::UnaryOp(UnOp::PtrMetadata, arg.node.clone()); + let arg = arg.node.clone(); + let r_value = Rvalue::UnaryOp(UnOp::PtrMetadata, arg.clone()); let len_statement_kind = StatementKind::Assign(Box::new((*destination, r_value))); let add_statement = Statement { kind: len_statement_kind, source_info: terminator.source_info }; @@ -64,5 +74,75 @@ fn lower_slice_len_call<'tcx>(block: &mut BasicBlockData<'tcx>, slice_len_fn_ite block.statements.push(add_statement); block.terminator_mut().kind = new_terminator_kind; + + if tcx.sess.opts.unstable_opts.mir_emit_retag { + // If we care about retags, we want there to be *no retag* for this `len` call. + // That means we have to clean up the MIR a little: the MIR will now often be: + // _6 = &*_4; + // _5 = PtrMetadata(move _6); + // Change that to: + // _6 = &raw const *_4; + // _5 = PtrMetadata(move _6); + let len = block.statements.len(); + if len >= 2 + && let &mut StatementKind::Assign(box (rebor_dest, ref mut rebor_r)) = + &mut block.statements[len - 2].kind + && let Some(retag_local) = rebor_dest.as_local() + && !local_decls[retag_local].is_user_variable() + // The LHS of this previous assignment is the `arg` from above. + && matches!(arg, Operand::Copy(p) | Operand::Move(p) if p.as_local() == Some(retag_local)) + // The RHS is a reference-taking operation. + && let Rvalue::Ref(_, BorrowKind::Shared, rebor_orig) = *rebor_r + { + let orig_inner_ty = rebor_orig.ty(local_decls, tcx).ty; + // Change the previous statement to use `&raw` instead of `&`. + *rebor_r = Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, rebor_orig); + // Change the type of the local to match. + local_decls[retag_local].ty = Ty::new_ptr(tcx, orig_inner_ty, Mutability::Not); + } + // There's a second pattern we need to recognize for `array.len()` calls. There, + // the MIR is: + // _4 = &*_3; + // _6 = move _4 as &[T] (PointerCoercion(Unsize, Implicit)); + // StorageDead(_4); + // _5 = PtrMetadata(move _6); + // Change that to: + // _4 = &raw const *_3; + // _6 = move _4 as *const [T] (PointerCoercion(Unsize, Implicit)); + // StorageDead(_4); + // _5 = PtrMetadata(move _6); + if len >= 4 + && let [reborrow_stmt, unsize_stmt, storage_dead_stmt] = + block.statements.get_disjoint_mut([len - 4, len - 3, len - 2]).unwrap() + // Check that the 3 statements have the right shape. + && let &mut StatementKind::Assign(box (rebor_dest, ref mut rebor_r)) = &mut reborrow_stmt.kind + && let Some(retag_local) = rebor_dest.as_local() + && !local_decls[retag_local].is_user_variable() + && let &mut StatementKind::Assign(box (unsized_dest, ref mut unsize_r)) = &mut unsize_stmt.kind + && let Some(unsized_local) = unsized_dest.as_local() + && !local_decls[unsized_local].is_user_variable() + && storage_dead_stmt.kind == StatementKind::StorageDead(retag_local) + // And check that they have the right operands. + && matches!(arg, Operand::Copy(p) | Operand::Move(p) if p.as_local() == Some(unsized_local)) + && let &mut Rvalue::Cast( + CastKind::PointerCoercion(PointerCoercion::Unsize, CoercionSource::Implicit), + ref cast_op, + ref mut cast_ty, + ) = unsize_r + && let Operand::Copy(unsize_src) | Operand::Move(unsize_src) = cast_op + && unsize_src.as_local() == Some(retag_local) + && let Rvalue::Ref(_, BorrowKind::Shared, rebor_orig) = *rebor_r + { + let orig_inner_ty = rebor_orig.ty(local_decls, tcx).ty; + let unsize_inner_ty = cast_ty.builtin_deref(true).unwrap(); + // Change the reborrow to use `&raw` instead of `&`. + *rebor_r = Rvalue::RawPtr(RawPtrKind::FakeForPtrMetadata, rebor_orig); + // Change the unsize coercion in the same vein. + *cast_ty = Ty::new_ptr(tcx, unsize_inner_ty, Mutability::Not); + // Change the type of the locals to match. + local_decls[retag_local].ty = Ty::new_ptr(tcx, orig_inner_ty, Mutability::Not); + local_decls[unsized_local].ty = *cast_ty; + } + } } } diff --git a/library/alloctests/tests/sync.rs b/library/alloctests/tests/sync.rs index 6d3ab1b1d11e1..b57b627068d0b 100644 --- a/library/alloctests/tests/sync.rs +++ b/library/alloctests/tests/sync.rs @@ -332,7 +332,7 @@ fn weak_self_cyclic() { #[test] fn drop_arc() { let mut canary = AtomicUsize::new(0); - let x = Arc::new(Canary(&mut canary as *mut AtomicUsize)); + let x = Arc::new(Canary(&raw mut canary)); drop(x); assert!(canary.load(Acquire) == 1); } @@ -340,7 +340,7 @@ fn drop_arc() { #[test] fn drop_arc_weak() { let mut canary = AtomicUsize::new(0); - let arc = Arc::new(Canary(&mut canary as *mut AtomicUsize)); + let arc = Arc::new(Canary(&raw mut canary)); let arc_weak = Arc::downgrade(&arc); assert!(canary.load(Acquire) == 0); drop(arc); diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index bc57ba697b382..0659ed879cf5d 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -86,15 +86,6 @@ impl NewPermission { } } } - ty::RawPtr(_, Mutability::Mut) => { - assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw. - // Mutable raw pointer. No access, not protected. - NewPermission::Uniform { - perm: Permission::SharedReadWrite, - access: None, - protector: None, - } - } ty::Ref(_, _pointee, Mutability::Not) => { // Shared references. If frozen, these get `noalias` and `dereferenceable`; otherwise neither. NewPermission::FreezeSensitive { @@ -110,17 +101,6 @@ impl NewPermission { // This fixes https://github.com/rust-lang/rust/issues/55005. } } - ty::RawPtr(_, Mutability::Not) => { - assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw. - // `*const T`, when freshly created, are read-only in the frozen part. - NewPermission::FreezeSensitive { - freeze_perm: Permission::SharedReadOnly, - freeze_access: Some(AccessKind::Read), - freeze_protector: None, - nonfreeze_perm: Permission::SharedReadWrite, - nonfreeze_access: None, - } - } _ => unreachable!(), } } @@ -189,32 +169,39 @@ enum ItemInvalidationCause { /// Core per-location operations: access, dealloc, reborrow. impl<'tcx> Stack { - /// Find the first write-incompatible item above the given one -- - /// i.e, find the height to which the stack will be truncated when writing to `granting`. - fn find_first_write_incompatible(&self, granting: usize) -> usize { - let perm = self.get(granting).unwrap().perm(); - match perm { - Permission::SharedReadOnly => bug!("Cannot use SharedReadOnly for writing"), - Permission::Disabled => bug!("Cannot use Disabled for anything"), - Permission::Unique => { - // On a write, everything above us is incompatible. + /// Find the first incompatible item above the given one -- + /// i.e, find the height to which the stack will be truncated when accessing `granting`. + /// `None` means the access used the unknown bottom. + fn find_first_incompatible(&self, access: AccessKind, granting: Option) -> usize { + let mut idx = match granting { + Some(granting) => { + // Start scanning above the granting item. + // The granting_idx *might* be approximate, but any lower idx would remove more + // things. Even if this is a Unique and the lower idx is an SRW (which removes + // less), there is an SRW group boundary here so strictly more would get removed. granting + 1 } - Permission::SharedReadWrite => { - // The SharedReadWrite *just* above us are compatible, to skip those. - let mut idx = granting + 1; - while let Some(item) = self.get(idx) { - if item.perm() == Permission::SharedReadWrite { - // Go on. - idx += 1; - } else { - // Found first incompatible! - break; - } - } - idx + None => { + // If the access uses the unknown bottom, scan the entire stack. + 0 + } + }; + while let Some(item) = self.get(idx) { + // SRW is compatible with everything; SRO is compatible with reads. + let compatible = match (item.perm(), access) { + (Permission::SharedReadWrite, _) => true, + (Permission::SharedReadOnly, AccessKind::Read) => true, + _ => false, + }; + if compatible { + // Go on. + idx += 1; + } else { + // Found first incompatible! + break; } } + idx } /// The given item was invalidated -- check its protectors for whether that will cause UB. @@ -276,48 +263,15 @@ impl<'tcx> Stack { self.find_granting(access, tag, exposed_tags).map_err(|()| dcx.access_error(self))?; // Step 2: Remove incompatible items above them. Make sure we do not remove protected - // items. Behavior differs for reads and writes. + // items. This ensures U2 for all accesses, and F2a on write accesses. // In case of wildcards/unknown matches, we remove everything that is *definitely* gone. - if access == AccessKind::Write { - // Remove everything above the write-compatible items, like a proper stack. This makes sure read-only and unique - // pointers become invalid on write accesses (ensures F2a, and ensures U2 for write accesses). - let first_incompatible_idx = if let Some(granting_idx) = granting_idx { - // The granting_idx *might* be approximate, but any lower idx would remove more - // things. Even if this is a Unique and the lower idx is an SRW (which removes - // less), there is an SRW group boundary here so strictly more would get removed. - self.find_first_write_incompatible(granting_idx) - } else { - // We are writing to something in the unknown part. - // There is a SRW group boundary between the unknown and the known, so everything is incompatible. - 0 - }; - self.pop_items_after(first_incompatible_idx, |item| { - Stack::item_invalidated(&item, global, dcx, ItemInvalidationCause::Conflict)?; - dcx.log_invalidation(item.tag()); - interp_ok(()) - })?; - } else { - // On a read, *disable* all `Unique` above the granting item. This ensures U2 for read accesses. - // The reason this is not following the stack discipline (by removing the first Unique and - // everything on top of it) is that in `let raw = &mut *x as *mut _; let _val = *x;`, the second statement - // would pop the `Unique` from the reborrow of the first statement, and subsequently also pop the - // `SharedReadWrite` for `raw`. - // This pattern occurs a lot in the standard library: create a raw pointer, then also create a shared - // reference and use that. - // We *disable* instead of removing `Unique` to avoid "connecting" two neighbouring blocks of SRWs. - let first_incompatible_idx = if let Some(granting_idx) = granting_idx { - // The granting_idx *might* be approximate, but any lower idx would disable more things. - granting_idx + 1 - } else { - // We are reading from something in the unknown part. That means *all* `Unique` we know about are dead now. - 0 - }; - self.disable_uniques_starting_at(first_incompatible_idx, |item| { - Stack::item_invalidated(&item, global, dcx, ItemInvalidationCause::Conflict)?; - dcx.log_invalidation(item.tag()); - interp_ok(()) - })?; - } + + let first_incompatible_idx = self.find_first_incompatible(access, granting_idx); + self.pop_items_after(first_incompatible_idx, |item| { + Stack::item_invalidated(&item, global, dcx, ItemInvalidationCause::Conflict)?; + dcx.log_invalidation(item.tag()); + interp_ok(()) + })?; // If this was an approximate action, we now collapse everything into an unknown. if granting_idx.is_none() || matches!(tag, ProvenanceExtra::Wildcard) { @@ -424,7 +378,7 @@ impl<'tcx> Stack { // access. Instead of popping the stack, we insert the item at the place the stack would // be popped to (i.e., we insert it above all the write-compatible items). // This ensures F2b by adding the new item below any potentially existing `SharedReadOnly`. - self.find_first_write_incompatible(granting_idx) + self.find_first_incompatible(AccessKind::Write, Some(granting_idx)) }; // Put the new item there. @@ -863,12 +817,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { val: &ImmTy<'tcx>, ) -> InterpResult<'tcx, ImmTy<'tcx>> { let this = self.eval_context_mut(); - let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this); let cause = match kind { RetagKind::TwoPhase => RetagCause::TwoPhase, RetagKind::FnEntry => unreachable!(), - RetagKind::Raw | RetagKind::Default => RetagCause::Normal, + RetagKind::Default => RetagCause::Normal, + RetagKind::Raw => return interp_ok(val.clone()), // no raw retags! }; + let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this); this.sb_retag_reference(val, new_perm, RetagInfo { cause, in_field: false }) } @@ -942,14 +897,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Check the type of this value to see what to do with it (retag, or recurse). match place.layout.ty.kind() { - ty::Ref(..) | ty::RawPtr(..) => { - if matches!(place.layout.ty.kind(), ty::Ref(..)) - || self.kind == RetagKind::Raw - { - let new_perm = - NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx); - self.retag_ptr_inplace(place, new_perm)?; - } + ty::Ref(..) => { + let new_perm = + NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx); + self.retag_ptr_inplace(place, new_perm)?; + } + ty::RawPtr(_, _) => { + // 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! + // We also do not want to reborrow them. } ty::Adt(adt, _) if adt.is_box() => { // Recurse for boxes, they require some tricky handling and will end up in `visit_box` above. diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.stack.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.stack.stderr index a89baa50ff397..6f3dc4e6fd32d 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut3.stack.stderr @@ -12,8 +12,8 @@ LL | pub fn safe(x: &mut i32, y: &i32) { help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> tests/fail/both_borrows/aliasing_mut3.rs:LL:CC | -LL | safe_raw(xraw, xshr); - | ^^^^ +LL | let xshr = &*xref; + | ^^^^^^ help: was later invalidated at offsets [0x0..0x4] by a Unique function-entry retag inside this call --> tests/fail/both_borrows/aliasing_mut3.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.stack.stderr index 0cffdcd21c43f..64bd08093b898 100644 --- a/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/box_exclusive_violation1.stack.stderr @@ -12,8 +12,8 @@ LL | *LEAK = 7; help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> tests/fail/both_borrows/box_exclusive_violation1.rs:LL:CC | -LL | LEAK = x as *const _ as *mut _; - | ^ +LL | fn unknown_code_1(x: &i32) { + | ^ help: was later invalidated at offsets [0x0..0x4] by a write access --> tests/fail/both_borrows/box_exclusive_violation1.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr index 3dc3f8c6619d5..5ff3c1cd251c8 100644 --- a/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/box_noalias_violation.stack.stderr @@ -6,7 +6,7 @@ LL | *y | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/both_borrows/box_noalias_violation.rs:LL:CC | LL | let ptr = &mut v as *mut i32; diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write1.stack.stderr index 9df441cb9564f..98f0d2bfe9c52 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write1.stack.stderr @@ -12,8 +12,8 @@ LL | unsafe { *x = 42 }; help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> tests/fail/both_borrows/illegal_write1.rs:LL:CC | -LL | let x: *mut u32 = xref as *const _ as *mut _; - | ^^^^ +LL | let xref = &*target; + | ^^^^^^^^ = note: BACKTRACE (of the first span): = note: inside `main` at tests/fail/both_borrows/illegal_write1.rs:LL:CC diff --git a/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr b/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr index e75334508ffd8..4d4382221fbf8 100644 --- a/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/illegal_write6.stack.stderr @@ -6,11 +6,11 @@ LL | unsafe { *y = 2 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/both_borrows/illegal_write6.rs:LL:CC | -LL | let p = x as *mut u32; - | ^ +LL | let x = &mut 0u32; + | ^^^^^^^^^ help: is this argument --> tests/fail/both_borrows/illegal_write6.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr index b5df165328909..15c6a89397f56 100644 --- a/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/invalidate_against_protector2.stack.stderr @@ -6,7 +6,7 @@ LL | unsafe { *x = 0 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/both_borrows/invalidate_against_protector2.rs:LL:CC | LL | let xraw = &mut x as *mut _; diff --git a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.stack.stderr index 92df9bcbe384f..9a76a80bfe473 100644 --- a/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/mut_exclusive_violation1.stack.stderr @@ -12,8 +12,8 @@ LL | *LEAK = 7; help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> tests/fail/both_borrows/mut_exclusive_violation1.rs:LL:CC | -LL | LEAK = x as *const _ as *mut _; - | ^ +LL | fn unknown_code_1(x: &i32) { + | ^ help: was later invalidated at offsets [0x0..0x4] by a write access --> tests/fail/both_borrows/mut_exclusive_violation1.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/both_borrows/mut_raw_mut2.rs b/src/tools/miri/tests/fail/both_borrows/mut_raw_mut2.rs new file mode 100644 index 0000000000000..36b068c2fd197 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/mut_raw_mut2.rs @@ -0,0 +1,15 @@ +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows + +// This used to accidentally be accepted by SB. +fn main() { + unsafe { + let mut root = 0; + let to = &mut root as *mut i32; + *to = 0; + let _val = root; + *to = 0; + //~[stack]^ ERROR: tag does not exist in the borrow stack + //~[tree]| ERROR: forbidden + } +} diff --git a/src/tools/miri/tests/fail/both_borrows/mut_raw_mut2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/mut_raw_mut2.stack.stderr new file mode 100644 index 0000000000000..a7ce041235bd4 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/mut_raw_mut2.stack.stderr @@ -0,0 +1,28 @@ +error: Undefined Behavior: attempting a write access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + --> tests/fail/both_borrows/mut_raw_mut2.rs:LL:CC + | +LL | *to = 0; + | ^^^^^^^ + | | + | attempting a write access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of an access at ALLOC[0x0..0x4] + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a Unique retag at offsets [0x0..0x4] + --> tests/fail/both_borrows/mut_raw_mut2.rs:LL:CC + | +LL | let to = &mut root as *mut i32; + | ^^^^^^^^^ +help: was later invalidated at offsets [0x0..0x4] by a read access + --> tests/fail/both_borrows/mut_raw_mut2.rs:LL:CC + | +LL | let _val = root; + | ^^^^ + = note: BACKTRACE (of the first span): + = note: inside `main` at tests/fail/both_borrows/mut_raw_mut2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/both_borrows/mut_raw_mut2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/mut_raw_mut2.tree.stderr new file mode 100644 index 0000000000000..856ad573573bd --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/mut_raw_mut2.tree.stderr @@ -0,0 +1,32 @@ +error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden + --> tests/fail/both_borrows/mut_raw_mut2.rs:LL:CC + | +LL | *to = 0; + | ^^^^^^^ write access through at ALLOC[0x0] is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag has state Frozen which forbids this child write access +help: the accessed tag was created here, in the initial state Reserved + --> tests/fail/both_borrows/mut_raw_mut2.rs:LL:CC + | +LL | let to = &mut root as *mut i32; + | ^^^^^^^^^ +help: the accessed tag later transitioned to Active due to a child write access at offsets [0x0..0x4] + --> tests/fail/both_borrows/mut_raw_mut2.rs:LL:CC + | +LL | *to = 0; + | ^^^^^^^ + = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference +help: the accessed tag later transitioned to Frozen due to a foreign read access at offsets [0x0..0x4] + --> tests/fail/both_borrows/mut_raw_mut2.rs:LL:CC + | +LL | let _val = root; + | ^^^^ + = help: this transition corresponds to a loss of write permissions + = note: BACKTRACE (of the first span): + = note: inside `main` at tests/fail/both_borrows/mut_raw_mut2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr index f428447230a85..c15a12e29c377 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr @@ -6,7 +6,7 @@ LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/both_borrows/newtype_pair_retagging.rs:LL:CC | LL | let ptr = Box::into_raw(Box::new(0i32)); diff --git a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr index 0410c2488db02..63d7939ce9dcb 100644 --- a/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/newtype_retagging.stack.stderr @@ -6,7 +6,7 @@ LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/both_borrows/newtype_retagging.rs:LL:CC | LL | let ptr = Box::into_raw(Box::new(0i32)); diff --git a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.stack.stderr index 22efda1efae6c..79e0e9f6d280e 100644 --- a/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/shr_frozen_violation1.stack.stderr @@ -12,8 +12,8 @@ LL | *(x as *const i32 as *mut i32) = 7; help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> tests/fail/both_borrows/shr_frozen_violation1.rs:LL:CC | -LL | *(x as *const i32 as *mut i32) = 7; - | ^ +LL | fn unknown_code(x: &i32) { + | ^ = note: BACKTRACE (of the first span): = note: inside `unknown_code` at tests/fail/both_borrows/shr_frozen_violation1.rs:LL:CC note: inside `foo` diff --git a/src/tools/miri/tests/fail/box-cell-alias.rs b/src/tools/miri/tests/fail/box-cell-alias.rs index 1a4a3b97ea3ff..e870bcc3f01f0 100644 --- a/src/tools/miri/tests/fail/box-cell-alias.rs +++ b/src/tools/miri/tests/fail/box-cell-alias.rs @@ -2,17 +2,17 @@ // Taken from . -use std::cell::Cell; +use std::cell::{Cell, UnsafeCell}; -fn helper(val: Box>, ptr: *const Cell) -> u8 { +fn helper(val: Box>, ptr: *const UnsafeCell) -> u8 { val.set(10); - unsafe { (*ptr).set(20) }; //~ ERROR: does not exist in the borrow stack + unsafe { (*ptr).get().write(20) }; //~ ERROR: protected val.get() } fn main() { let val: Box> = Box::new(Cell::new(25)); let ptr: *const Cell = &*val; - let res = helper(val, ptr); + let res = helper(val, ptr.cast()); assert_eq!(res, 20); } diff --git a/src/tools/miri/tests/fail/box-cell-alias.stderr b/src/tools/miri/tests/fail/box-cell-alias.stderr index f9cc6003dc688..85c9d4f616832 100644 --- a/src/tools/miri/tests/fail/box-cell-alias.stderr +++ b/src/tools/miri/tests/fail/box-cell-alias.stderr @@ -1,31 +1,28 @@ -error: Undefined Behavior: trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location +error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is weakly protected --> tests/fail/box-cell-alias.rs:LL:CC | -LL | unsafe { (*ptr).set(20) }; - | ^^^^^^ - | | - | trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of retag at ALLOC[0x0..0x1] +LL | unsafe { (*ptr).get().write(20) }; + | ^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag because that would remove [Unique for ] which is weakly protected | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information help: was created by a SharedReadWrite retag at offsets [0x0..0x1] --> tests/fail/box-cell-alias.rs:LL:CC | -LL | let ptr: *const Cell = &*val; - | ^^^^^ -help: was later invalidated at offsets [0x0..0x1] by a Unique retag +LL | unsafe { (*ptr).get().write(20) }; + | ^^^^^^^^^^^^ +help: is this argument --> tests/fail/box-cell-alias.rs:LL:CC | -LL | let res = helper(val, ptr); - | ^^^ +LL | fn helper(val: Box>, ptr: *const UnsafeCell) -> u8 { + | ^^^ = note: BACKTRACE (of the first span): = note: inside `helper` at tests/fail/box-cell-alias.rs:LL:CC note: inside `main` --> tests/fail/box-cell-alias.rs:LL:CC | -LL | let res = helper(val, ptr); - | ^^^^^^^^^^^^^^^^ +LL | let res = helper(val, ptr.cast()); + | ^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr index 2875a5be28544..4546f029a29b0 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr @@ -6,7 +6,7 @@ LL | unsafe { ptr.write(S(0)) }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created here, as the root tag for ALLOC --> tests/fail/function_calls/arg_inplace_mutate.rs:LL:CC | LL | / mir! { diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr index f20ec00f97bdb..923e289fb2310 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr @@ -6,7 +6,7 @@ LL | unsafe { ptr.read() }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created here, as the root tag for ALLOC --> tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC | LL | / mir! { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr index 47e5ee48292f7..5b8c65d3bd5b0 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.stack.stderr @@ -6,7 +6,7 @@ LL | unsafe { ptr.read() }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created here, as the root tag for ALLOC --> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC | LL | / mir! { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr index 813042f06a6ca..9572876d8902d 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write.stack.stderr @@ -6,7 +6,7 @@ LL | unsafe { ptr.write(0) }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created here, as the root tag for ALLOC --> tests/fail/function_calls/return_pointer_aliasing_write.rs:LL:CC | LL | / mir! { diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr index a6a0362a22666..4b7afe6be30f2 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_write_tail_call.stack.stderr @@ -6,7 +6,7 @@ LL | unsafe { ptr.write(0) }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created here, as the root tag for ALLOC --> tests/fail/function_calls/return_pointer_aliasing_write_tail_call.rs:LL:CC | LL | / mir! { diff --git a/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr b/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr index 2d0209d1a2a2b..439ee7c057b4b 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.stderr @@ -9,16 +9,16 @@ LL | let _val = *raw; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.rs:LL:CC | -LL | mutref as *mut i32 - | ^^^^^^ -help: was later invalidated at offsets [0x0..0x4] by a write access +LL | let mutref = &mut *base; + | ^^^^^^^^^^ +help: was later invalidated at offsets [0x0..0x4] by a read access --> tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.rs:LL:CC | -LL | *base = 1; - | ^^^^^^^^^ +LL | let _val = *base; + | ^^^^^ = note: BACKTRACE (of the first span): = note: inside `main` at tests/fail/stacked_borrows/disable_mut_does_not_merge_srw.rs:LL:CC diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr index f107ea2023dce..9526be301baf4 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr @@ -6,11 +6,11 @@ LL | let _val = *P; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x1] +help: was created here, as the root tag for ALLOC --> tests/fail/stacked_borrows/drop_in_place_protector.rs:LL:CC | -LL | let x = core::ptr::addr_of_mut!(x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let mut x = (HasDrop, 0u8); + | ^^^^^^^^^^^^^^ help: is this argument --> tests/fail/stacked_borrows/drop_in_place_protector.rs:LL:CC | @@ -25,7 +25,6 @@ note: inside `main` | LL | core::ptr::drop_in_place(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `core::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs index 9126b7e8575b0..00bae8cbe11c4 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.rs @@ -6,7 +6,7 @@ fn main() { unsafe { let x = 0u8; - let x = core::ptr::addr_of!(x); + let x = &x as *const u8; core::ptr::drop_in_place(x.cast_mut()); } } diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr index eebedf842ef5e..a752f7b69ad7a 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_retag.stderr @@ -12,8 +12,8 @@ LL | pub unsafe fn drop_in_place(to_drop: *mut T) { help: was created by a SharedReadOnly retag at offsets [0x0..0x1] --> tests/fail/stacked_borrows/drop_in_place_retag.rs:LL:CC | -LL | let x = core::ptr::addr_of!(x); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = &x as *const u8; + | ^^ = note: BACKTRACE (of the first span): = note: inside `std::ptr::drop_in_place:: - shim(None)` at RUSTLIB/core/src/ptr/mod.rs:LL:CC note: inside `main` @@ -21,7 +21,6 @@ note: inside `main` | LL | core::ptr::drop_in_place(x.cast_mut()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `core::ptr::addr_of` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr index 1a71feee7a182..bd42998a524c9 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/fnentry_invalidation.stderr @@ -9,7 +9,7 @@ LL | let _oof = *z; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/stacked_borrows/fnentry_invalidation.rs:LL:CC | LL | let z = &mut x as *mut i32; diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr index ddf8dbea31f59..6033d9ef2a57d 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr @@ -6,7 +6,7 @@ LL | dealloc(ptr2, Layout::from_size_align_unchecked(1, 1)); | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x1] +help: was created by a Unique retag at offsets [0x0..0x1] --> tests/fail/stacked_borrows/illegal_deALLOC.rs:LL:CC | LL | let ptr2 = (&mut *ptr1) as *mut u8; diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.rs b/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.rs deleted file mode 100644 index 4af22580ab64f..0000000000000 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Creating a shared reference does not leak the data to raw pointers. -fn main() { - unsafe { - let x = &mut 0; - let raw = x as *mut _; - let x = &mut *x; // kill `raw` - let _y = &*x; // this should not activate `raw` again - let _val = *raw; //~ ERROR: /read access .* tag does not exist in the borrow stack/ - } -} diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr deleted file mode 100644 index 31c5ad160a9d6..0000000000000 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read6.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: Undefined Behavior: attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - --> tests/fail/stacked_borrows/illegal_read6.rs:LL:CC - | -LL | let _val = *raw; - | ^^^^ - | | - | attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of an access at ALLOC[0x0..0x4] - | - = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental - = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] - --> tests/fail/stacked_borrows/illegal_read6.rs:LL:CC - | -LL | let raw = x as *mut _; - | ^ -help: was later invalidated at offsets [0x0..0x4] by a Unique retag - --> tests/fail/stacked_borrows/illegal_read6.rs:LL:CC - | -LL | let x = &mut *x; // kill `raw` - | ^^^^^^^ - = note: BACKTRACE (of the first span): - = note: inside `main` at tests/fail/stacked_borrows/illegal_read6.rs:LL:CC - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to 1 previous error - diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.rs b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.rs index 76516b7d924be..a1e19486c0bb7 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_read_despite_exposed1.rs @@ -8,7 +8,7 @@ fn main() { // From the exposed ptr, we get a new unique ptr. let root2 = &mut *exposed_ptr; let _fool = root2 as *mut _; // this would have fooled the old untagged pointer logic - // Stack: Unknown( was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/stacked_borrows/illegal_write2.rs:LL:CC | -LL | let target2 = target as *mut _; - | ^^^^^^ +LL | let target2 = &mut *target as *mut _; + | ^^^^^^^^^^^^ help: was later invalidated at offsets [0x0..0x4] by a Unique retag --> tests/fail/stacked_borrows/illegal_write2.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr index 6805b359367e1..78da2ef48c146 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write3.stderr @@ -12,8 +12,8 @@ LL | unsafe { *ptr = 42 }; help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> tests/fail/stacked_borrows/illegal_write3.rs:LL:CC | -LL | let ptr = r#ref as *const _ as *mut _; // raw ptr, with raw tag - | ^^^^^ +LL | let r#ref = ⌖ // freeze + | ^^^^^^^ = note: BACKTRACE (of the first span): = note: inside `main` at tests/fail/stacked_borrows/illegal_write3.rs:LL:CC diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.rs b/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.rs index 0e34c5c98fc1f..aa137d6305eee 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write_despite_exposed1.rs @@ -7,7 +7,7 @@ fn main() { let exposed_ptr = addr as *mut i32; // From the exposed ptr, we get a new SRO ptr. let root2 = &*exposed_ptr; - // Stack: Unknown( for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location --> tests/fail/stacked_borrows/interior_mut2.rs:LL:CC | -LL | let _val = *inner_shr.get(); - | ^^^^^^^^^ - | | - | trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location - | this error occurs as part of retag at ALLOC[0x0..0x4] +LL | let _val = *unsafe_cell_get(inner_shr); + | ^^^^^^^^^ + | | + | trying to retag from for SharedReadWrite permission at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of retag at ALLOC[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information @@ -14,11 +14,11 @@ help: was created by a SharedReadWrite retag at offsets [0x0..0x4] | LL | let inner_shr = &*inner_uniq; | ^^^^^^^^^^^^ -help: was later invalidated at offsets [0x0..0x4] by a write access +help: was later invalidated at offsets [0x0..0x4] by a read access --> tests/fail/stacked_borrows/interior_mut2.rs:LL:CC | -LL | *c.get() = UnsafeCell::new(0); // now inner_shr gets invalidated - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _val = c.get().read(); // invalidates inner_uniq + | ^^^^^^^^^^^^^^ = note: BACKTRACE (of the first span): = note: inside `main` at tests/fail/stacked_borrows/interior_mut2.rs:LL:CC diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr index 5956a3f675314..96419695c95e6 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr @@ -6,7 +6,7 @@ LL | let _val = unsafe { *x }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/stacked_borrows/invalidate_against_protector1.rs:LL:CC | LL | let xraw = &mut x as *mut _; diff --git a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr index 58c6cd4c31811..554513b0b9fae 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr @@ -9,11 +9,11 @@ LL | let _x = unsafe { *PTR }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x1] +help: was created by a Unique retag at offsets [0x0..0x1] --> tests/fail/stacked_borrows/pointer_smuggling.rs:LL:CC | -LL | PTR = x; - | ^ +LL | fn fun1(x: &mut u8) { + | ^ help: was later invalidated at offsets [0x0..0x1] by a write access --> tests/fail/stacked_borrows/pointer_smuggling.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr b/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr index aa320ea908c01..75603a9ed42bd 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/raw_tracking.stderr @@ -9,7 +9,7 @@ LL | unsafe { *raw1 = 13 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x0..0x4] +help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/stacked_borrows/raw_tracking.rs:LL:CC | LL | let raw1 = &mut l as *mut _; diff --git a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr index becd6681eca4b..d2a2c556f0036 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/transmute-is-no-escape.stderr @@ -9,7 +9,7 @@ LL | unsafe { *raw = 13 }; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information -help: was created by a SharedReadWrite retag at offsets [0x4..0x8] +help: was created by a Unique retag at offsets [0x4..0x8] --> tests/fail/stacked_borrows/transmute-is-no-escape.rs:LL:CC | LL | let raw = (&mut x[1] as *mut i32).wrapping_offset(-1); diff --git a/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs b/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs index b57386000404f..9b1649e9a0c8c 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs @@ -38,8 +38,7 @@ unsafe extern "C" fn dtor(ptr: *mut u64) { assert!(CANARY != ptr::null_mut()); // make sure we do not get run too often let val = *ptr; - let which_key = - GLOBALS.iter().position(|global| global as *const _ == ptr).expect("Should find my global"); + let which_key = ptr.offset_from_unsigned(&raw mut GLOBALS as *mut u64); record(which_key); if val > 0 { diff --git a/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs b/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs index 6a625e597df18..717c2629b2d4a 100644 --- a/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs +++ b/src/tools/miri/tests/pass/both_borrows/basic_aliasing_model.rs @@ -23,7 +23,9 @@ fn main() { not_unpin_not_protected(); write_does_not_invalidate_all_aliases(); box_into_raw_allows_interior_mutable_alias(); - cell_inside_struct() + cell_inside_struct(); + direct_mut_to_const_raw(); + local_addr_of_mut(); } // Make sure that reading from an `&mut` does, like reborrowing to `&`, @@ -54,7 +56,7 @@ fn read_does_not_invalidate2() { fn mut_raw_then_mut_shr() { let mut x = 2; let xref = &mut x; - let xraw = &mut *xref as *mut _; + let xraw = xref as *mut _; let xshr = &*xref; assert_eq!(*xshr, 2); unsafe { @@ -287,3 +289,22 @@ fn cell_inside_struct() { // Writing to `field1`, which is reserved, should also be allowed. (*a).field1 = 88; } + +// Casting an `&mut` to a `*const` produces a writeable pointer. +fn direct_mut_to_const_raw() { + let x = &mut 0; + let y: *const i32 = x; + unsafe { *(y as *mut i32) = 1 }; + assert_eq!(*x, 1); +} + +// A local variable and a raw pointer to it may be interleaved. +#[allow(unused_assignments)] +fn local_addr_of_mut() { + let mut local = 0; + let ptr = ptr::addr_of_mut!(local); + local = 1; + unsafe { *ptr = 2 }; + local = 3; + unsafe { *ptr = 4 }; +} diff --git a/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout b/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout index 296339e738455..05e29de0d1097 100644 --- a/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout +++ b/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout @@ -2,5 +2,5 @@ 0..1: [ SharedReadWrite ] 0..1: [ SharedReadWrite ] 0..1: [ SharedReadWrite Unique Unique Unique Unique Unique Unique Unique ] -0..1: [ SharedReadWrite Disabled Disabled Disabled Disabled Disabled Disabled Disabled SharedReadOnly ] +0..1: [ SharedReadWrite SharedReadOnly ] 0..1: [ unknown-bottom(..) ] diff --git a/src/tools/miri/tests/pass/stacked_borrows/stacked-borrows.rs b/src/tools/miri/tests/pass/stacked_borrows/stacked-borrows.rs index e68a5d8ffe740..40c10f02aebcf 100644 --- a/src/tools/miri/tests/pass/stacked_borrows/stacked-borrows.rs +++ b/src/tools/miri/tests/pass/stacked_borrows/stacked-borrows.rs @@ -4,32 +4,9 @@ // Test various stacked-borrows-specific things // (i.e., these do not work the same under TB). fn main() { - mut_raw_mut2(); - // direct_mut_to_const_raw(); two_phase_aliasing_violation(); } -// A variant of `mut_raw_mut` that does *not* get accepted by Tree Borrows. -// It's kind of an accident that we accept it in Stacked Borrows... -fn mut_raw_mut2() { - unsafe { - let mut root = 0; - let to = &mut root as *mut i32; - *to = 0; - let _val = root; - *to = 0; - } -} - -// Make sure that coercing &mut T to *const T produces a writeable pointer. -// TODO: This is currently disabled, waiting on a decision on -/*fn direct_mut_to_const_raw() { - let x = &mut 0; - let y: *const i32 = x; - unsafe { *(y as *mut i32) = 1; } - assert_eq!(*x, 1); -}*/ - // This one really shouldn't be accepted, but since we treat 2phase as raw, we do accept it. // Tree Borrows rejects it. fn two_phase_aliasing_violation() { diff --git a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs index 87eb447049d61..307d77faf1d15 100644 --- a/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs +++ b/src/tools/miri/tests/pass/tree_borrows/tree-borrows.rs @@ -1,7 +1,7 @@ //@compile-flags: -Zmiri-tree-borrows #![feature(allocator_api)] -use std::{mem, ptr}; +use std::mem; // Test various tree-borrows-specific things // (i.e., these do not work the same under SB). @@ -9,22 +9,9 @@ fn main() { aliasing_read_only_mutable_refs(); string_as_mut_ptr(); two_mut_protected_same_alloc(); - direct_mut_to_const_raw(); - local_addr_of_mut(); returned_mut_is_usable(); } -#[allow(unused_assignments)] -fn local_addr_of_mut() { - let mut local = 0; - let ptr = ptr::addr_of_mut!(local); - // In SB, `local` and `*ptr` would have different tags, but in TB they have the same tag. - local = 1; - unsafe { *ptr = 2 }; - local = 3; - unsafe { *ptr = 4 }; -} - // Tree Borrows has no issue with several mutable references existing // at the same time, as long as they are used only immutably. // I.e. multiple Reserved can coexist. @@ -92,13 +79,3 @@ fn returned_mut_is_usable() { let y = reborrow(x); *y = 1; } - -// Make sure that coercing &mut T to *const T produces a writeable pointer. -fn direct_mut_to_const_raw() { - let x = &mut 0; - let y: *const i32 = x; - unsafe { - *(y as *mut i32) = 1; - } - assert_eq!(*x, 1); -} diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff index 98c5e868046b5..1fc32464e90b3 100644 --- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-abort.diff @@ -26,43 +26,39 @@ StorageDead(_7); - _5 = PtrMetadata(move _6); + _5 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_6); - _3 = Lt(move _4, move _5); -- switchInt(move _3) -> [0: bb4, otherwise: bb2]; +- switchInt(move _3) -> [0: bb3, otherwise: bb1]; + _3 = Lt(copy _1, const N); -+ switchInt(copy _3) -> [0: bb4, otherwise: bb2]; ++ switchInt(copy _3) -> [0: bb3, otherwise: bb1]; } - bb2: { + bb1: { StorageDead(_5); StorageDead(_4); StorageLive(_8); _8 = copy _1; - _9 = Lt(copy _8, const N); -- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind unreachable]; +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb2, unwind unreachable]; + _9 = copy _3; -+ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind unreachable]; ++ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb2, unwind unreachable]; } - bb3: { + bb2: { - _0 = copy (*_2)[_8]; + _0 = copy (*_2)[_1]; StorageDead(_8); - goto -> bb5; + goto -> bb4; } - bb4: { + bb3: { StorageDead(_5); StorageDead(_4); _0 = const 42_u8; - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { - StorageDead(_3); + nop; return; diff --git a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff index 72c7313786996..7e8c8925f82a3 100644 --- a/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound.GVN.panic-unwind.diff @@ -26,43 +26,39 @@ StorageDead(_7); - _5 = PtrMetadata(move _6); + _5 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_6); - _3 = Lt(move _4, move _5); -- switchInt(move _3) -> [0: bb4, otherwise: bb2]; +- switchInt(move _3) -> [0: bb3, otherwise: bb1]; + _3 = Lt(copy _1, const N); -+ switchInt(copy _3) -> [0: bb4, otherwise: bb2]; ++ switchInt(copy _3) -> [0: bb3, otherwise: bb1]; } - bb2: { + bb1: { StorageDead(_5); StorageDead(_4); StorageLive(_8); _8 = copy _1; - _9 = Lt(copy _8, const N); -- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind continue]; +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb2, unwind continue]; + _9 = copy _3; -+ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind continue]; ++ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb2, unwind continue]; } - bb3: { + bb2: { - _0 = copy (*_2)[_8]; + _0 = copy (*_2)[_1]; StorageDead(_8); - goto -> bb5; + goto -> bb4; } - bb4: { + bb3: { StorageDead(_5); StorageDead(_4); _0 = const 42_u8; - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { - StorageDead(_3); + nop; return; diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff index 9ffaf44c02bd2..70ed16e1287d3 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-abort.diff @@ -28,55 +28,51 @@ StorageDead(_7); - _5 = PtrMetadata(move _6); + _5 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_6); - _3 = Lt(move _4, move _5); -- switchInt(move _3) -> [0: bb4, otherwise: bb2]; +- switchInt(move _3) -> [0: bb3, otherwise: bb1]; + _3 = Lt(copy _1, const N); -+ switchInt(copy _3) -> [0: bb4, otherwise: bb2]; ++ switchInt(copy _3) -> [0: bb3, otherwise: bb1]; } - bb2: { + bb1: { StorageDead(_5); StorageDead(_4); StorageLive(_8); _8 = copy _1; - _9 = Lt(copy _8, const N); -- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind unreachable]; +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb2, unwind unreachable]; + _9 = copy _3; -+ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind unreachable]; ++ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb2, unwind unreachable]; } - bb3: { + bb2: { - _0 = copy (*_2)[_8]; + _0 = copy (*_2)[_1]; StorageDead(_8); - goto -> bb6; + goto -> bb5; } - bb4: { + bb3: { StorageDead(_5); StorageDead(_4); StorageLive(_10); _10 = const 0_usize; - _11 = Lt(copy _10, const N); -- assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, copy _10) -> [success: bb5, unwind unreachable]; +- assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, copy _10) -> [success: bb4, unwind unreachable]; + _11 = Lt(const 0_usize, const N); -+ assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind unreachable]; ++ assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb4, unwind unreachable]; } - bb5: { + bb4: { - (*_2)[_10] = const 42_u8; + (*_2)[0 of 1] = const 42_u8; StorageDead(_10); _0 = const 42_u8; - goto -> bb6; + goto -> bb5; } - bb6: { + bb5: { - StorageDead(_3); + nop; return; diff --git a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff index 08008e463357f..57b8101406ebf 100644 --- a/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_bound_mut.GVN.panic-unwind.diff @@ -28,55 +28,51 @@ StorageDead(_7); - _5 = PtrMetadata(move _6); + _5 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_6); - _3 = Lt(move _4, move _5); -- switchInt(move _3) -> [0: bb4, otherwise: bb2]; +- switchInt(move _3) -> [0: bb3, otherwise: bb1]; + _3 = Lt(copy _1, const N); -+ switchInt(copy _3) -> [0: bb4, otherwise: bb2]; ++ switchInt(copy _3) -> [0: bb3, otherwise: bb1]; } - bb2: { + bb1: { StorageDead(_5); StorageDead(_4); StorageLive(_8); _8 = copy _1; - _9 = Lt(copy _8, const N); -- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb3, unwind continue]; +- assert(move _9, "index out of bounds: the length is {} but the index is {}", const N, copy _8) -> [success: bb2, unwind continue]; + _9 = copy _3; -+ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb3, unwind continue]; ++ assert(copy _3, "index out of bounds: the length is {} but the index is {}", const N, copy _1) -> [success: bb2, unwind continue]; } - bb3: { + bb2: { - _0 = copy (*_2)[_8]; + _0 = copy (*_2)[_1]; StorageDead(_8); - goto -> bb6; + goto -> bb5; } - bb4: { + bb3: { StorageDead(_5); StorageDead(_4); StorageLive(_10); _10 = const 0_usize; - _11 = Lt(copy _10, const N); -- assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, copy _10) -> [success: bb5, unwind continue]; +- assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, copy _10) -> [success: bb4, unwind continue]; + _11 = Lt(const 0_usize, const N); -+ assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb5, unwind continue]; ++ assert(move _11, "index out of bounds: the length is {} but the index is {}", const N, const 0_usize) -> [success: bb4, unwind continue]; } - bb5: { + bb4: { - (*_2)[_10] = const 42_u8; + (*_2)[0 of 1] = const 42_u8; StorageDead(_10); _0 = const 42_u8; - goto -> bb6; + goto -> bb5; } - bb6: { + bb5: { - StorageDead(_3); + nop; return; diff --git a/tests/mir-opt/lower_array_len.array_len.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len.GVN.panic-abort.diff index 369bd2f473297..f914f58588a1e 100644 --- a/tests/mir-opt/lower_array_len.array_len.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len.GVN.panic-abort.diff @@ -15,10 +15,6 @@ StorageDead(_3); - _0 = PtrMetadata(move _2); + _0 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_2); return; } diff --git a/tests/mir-opt/lower_array_len.array_len.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len.GVN.panic-unwind.diff index 369bd2f473297..f914f58588a1e 100644 --- a/tests/mir-opt/lower_array_len.array_len.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len.GVN.panic-unwind.diff @@ -15,10 +15,6 @@ StorageDead(_3); - _0 = PtrMetadata(move _2); + _0 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_2); return; } diff --git a/tests/mir-opt/lower_array_len.array_len_by_value.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_by_value.GVN.panic-abort.diff index d9c289bf58aee..1341b9c9c524a 100644 --- a/tests/mir-opt/lower_array_len.array_len_by_value.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len_by_value.GVN.panic-abort.diff @@ -15,10 +15,6 @@ StorageDead(_3); - _0 = PtrMetadata(move _2); + _0 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_2); return; } diff --git a/tests/mir-opt/lower_array_len.array_len_by_value.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_by_value.GVN.panic-unwind.diff index d9c289bf58aee..1341b9c9c524a 100644 --- a/tests/mir-opt/lower_array_len.array_len_by_value.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len_by_value.GVN.panic-unwind.diff @@ -15,10 +15,6 @@ StorageDead(_3); - _0 = PtrMetadata(move _2); + _0 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_2); return; } diff --git a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff index 180a7db029794..6239f89de0ebb 100644 --- a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-abort.diff @@ -35,10 +35,6 @@ _6 = &(*_7); - _0 = PtrMetadata(move _6); + _0 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_6); StorageDead(_5); - StorageDead(_2); diff --git a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff index 180a7db029794..6239f89de0ebb 100644 --- a/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len_raw.GVN.panic-unwind.diff @@ -35,10 +35,6 @@ _6 = &(*_7); - _0 = PtrMetadata(move _6); + _0 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_6); StorageDead(_5); - StorageDead(_2); diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff index 49964f8b49e26..9eb4480d32d75 100644 --- a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff +++ b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-abort.diff @@ -32,10 +32,6 @@ _6 = &(*_5); - _0 = PtrMetadata(move _6); + _0 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_6); StorageDead(_5); - StorageDead(_2); diff --git a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff index 49964f8b49e26..9eb4480d32d75 100644 --- a/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff +++ b/tests/mir-opt/lower_array_len.array_len_reborrow.GVN.panic-unwind.diff @@ -32,10 +32,6 @@ _6 = &(*_5); - _0 = PtrMetadata(move _6); + _0 = const N; - goto -> bb1; - } - - bb1: { StorageDead(_6); StorageDead(_5); - StorageDead(_2);