From d298feb31009882b4cf22b59e0159a6e05615e4f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 24 Mar 2026 23:00:10 +0100 Subject: [PATCH] miri: remove retag statements, make typed copies retag implicitly instead --- compiler/rustc_borrowck/src/dataflow.rs | 1 - .../src/diagnostics/conflict_errors.rs | 2 +- .../src/diagnostics/explain_borrow.rs | 2 +- .../rustc_borrowck/src/diagnostics/mod.rs | 2 +- .../src/diagnostics/move_errors.rs | 2 +- .../src/diagnostics/mutability_errors.rs | 5 +- compiler/rustc_borrowck/src/lib.rs | 5 +- .../src/polonius/legacy/loan_invalidations.rs | 3 +- compiler/rustc_borrowck/src/type_check/mod.rs | 7 +- compiler/rustc_codegen_cranelift/src/base.rs | 3 +- .../rustc_codegen_cranelift/src/constant.rs | 3 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 9 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 4 +- .../rustc_codegen_ssa/src/mir/statement.rs | 1 - .../src/check_consts/check.rs | 3 +- .../src/check_consts/qualifs.rs | 2 +- .../src/const_eval/machine.rs | 32 ++- .../rustc_const_eval/src/interpret/call.rs | 163 ++++++++------- .../rustc_const_eval/src/interpret/machine.rs | 46 +++-- .../rustc_const_eval/src/interpret/mod.rs | 4 +- .../rustc_const_eval/src/interpret/place.rs | 13 +- .../rustc_const_eval/src/interpret/step.rs | 53 ++--- .../src/interpret/validity.rs | 149 +++++++++----- .../rustc_const_eval/src/interpret/visitor.rs | 2 +- compiler/rustc_interface/src/tests.rs | 1 - .../rustc_middle/src/mir/interpret/error.rs | 5 +- compiler/rustc_middle/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 16 +- compiler/rustc_middle/src/mir/statement.rs | 5 +- compiler/rustc_middle/src/mir/syntax.rs | 52 ++--- compiler/rustc_middle/src/mir/visit.rs | 27 +-- .../rustc_middle/src/ty/structural_impls.rs | 2 +- compiler/rustc_mir_build/src/builder/cfg.rs | 15 +- .../src/builder/custom/parse/instruction.rs | 5 +- .../src/builder/expr/as_rvalue.rs | 21 +- .../rustc_mir_build/src/builder/expr/into.rs | 10 +- .../src/builder/matches/mod.rs | 4 +- .../src/builder/matches/test.rs | 7 +- compiler/rustc_mir_build/src/builder/mod.rs | 2 +- compiler/rustc_mir_build/src/builder/scope.rs | 2 +- .../rustc_mir_dataflow/src/impls/liveness.rs | 1 - .../src/impls/storage_liveness.rs | 1 - .../src/move_paths/builder.rs | 5 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 2 +- .../rustc_mir_dataflow/src/value_analysis.rs | 2 +- .../src/add_moves_for_packed_drops.rs | 2 +- compiler/rustc_mir_transform/src/add_retag.rs | 186 ------------------ .../rustc_mir_transform/src/check_enums.rs | 13 +- compiler/rustc_mir_transform/src/copy_prop.rs | 2 +- compiler/rustc_mir_transform/src/coroutine.rs | 69 ++++--- .../rustc_mir_transform/src/coroutine/drop.rs | 2 +- .../src/coverage/from_mir.rs | 1 - .../src/dataflow_const_prop.rs | 15 +- .../src/deref_separator.rs | 6 +- compiler/rustc_mir_transform/src/dest_prop.rs | 6 +- .../rustc_mir_transform/src/elaborate_drop.rs | 11 +- .../src/elaborate_drops.rs | 13 +- .../src/erase_deref_temps.rs | 4 +- compiler/rustc_mir_transform/src/gvn.rs | 13 +- compiler/rustc_mir_transform/src/inline.rs | 14 +- .../rustc_mir_transform/src/instsimplify.rs | 44 +++-- .../rustc_mir_transform/src/jump_threading.rs | 3 +- .../src/known_panics_lint.rs | 2 +- .../rustc_mir_transform/src/large_enums.rs | 16 +- compiler/rustc_mir_transform/src/lib.rs | 8 +- compiler/rustc_mir_transform/src/liveness.rs | 5 +- .../src/lower_intrinsics.rs | 17 +- .../rustc_mir_transform/src/match_branches.rs | 24 ++- .../rustc_mir_transform/src/promote_consts.rs | 28 ++- compiler/rustc_mir_transform/src/ref_prop.rs | 2 +- .../src/remove_noop_landing_pads.rs | 5 +- .../rustc_mir_transform/src/remove_zsts.rs | 1 - compiler/rustc_mir_transform/src/shim.rs | 37 +--- .../src/shim/async_destructor_ctor.rs | 13 +- compiler/rustc_mir_transform/src/simplify.rs | 1 - .../src/simplify_branches.rs | 2 +- .../src/single_use_consts.rs | 4 +- compiler/rustc_mir_transform/src/sroa.rs | 12 +- compiler/rustc_mir_transform/src/ssa.rs | 2 +- .../rustc_mir_transform/src/trivial_const.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 18 +- compiler/rustc_public/src/mir/body.rs | 15 +- compiler/rustc_public/src/mir/pretty.rs | 8 +- compiler/rustc_public/src/mir/visit.rs | 5 +- .../src/unstable/convert/stable/mir.rs | 19 +- compiler/rustc_session/src/options.rs | 3 - compiler/rustc_span/src/symbol.rs | 1 - compiler/rustc_ty_utils/src/abi.rs | 5 + library/alloc/src/boxed.rs | 8 +- library/core/src/intrinsics/mir.rs | 3 +- .../clippy_lints/src/redundant_clone.rs | 2 +- .../clippy_utils/src/mir/possible_borrower.rs | 2 +- .../clippy_utils/src/mir/possible_origin.rs | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 3 +- src/tools/miri/README.md | 26 +-- src/tools/miri/src/bin/miri.rs | 5 + src/tools/miri/src/borrow_tracker/mod.rs | 56 +++--- .../stacked_borrows/diagnostics.rs | 14 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 172 ++++------------ .../src/borrow_tracker/tree_borrows/mod.rs | 146 +++----------- src/tools/miri/src/diagnostics.rs | 12 +- src/tools/miri/src/lib.rs | 8 +- src/tools/miri/src/machine.rs | 21 +- .../alias_through_mutation.stack.stderr | 2 +- .../alias_through_mutation.tree.stderr | 2 +- .../both_borrows/aliasing_mut1.stack.stderr | 2 +- .../buggy_split_at_mut.stack.stderr | 4 +- .../drop_in_place_protector.rs | 10 +- .../drop_in_place_protector.stack.stderr} | 14 +- .../drop_in_place_protector.tree.stderr | 35 ++++ .../fail/both_borrows/issue-miri-1050-1.rs | 12 -- .../issue-miri-1050-1.stack.stderr | 25 --- .../issue-miri-1050-1.tree.stderr | 25 --- .../fail/both_borrows/issue-miri-1050-2.rs | 13 -- .../issue-miri-1050-2.stack.stderr | 20 -- .../issue-miri-1050-2.tree.stderr | 20 -- .../fail/both_borrows/load_invalid_shr.rs | 2 - .../pass_invalid_shr_option.stack.stderr | 4 +- .../pass_invalid_shr_tuple.stack.stderr | 4 +- .../return_invalid_shr_option.stack.stderr | 4 +- .../return_invalid_shr_tuple.stack.stderr | 4 +- .../dangling_pointer_to_raw_pointer.rs | 2 +- .../dangling_pointer_to_raw_pointer.stderr | 2 +- .../dangling_pointers/deref-invalid-ptr.rs | 2 +- .../deref-invalid-ptr.stderr | 6 +- .../storage_dead_dangling.rs | 3 +- .../storage_dead_dangling.stderr | 6 +- .../miri/tests/fail/erroneous_const2.stderr | 8 + .../arg_inplace_locals_alias.rs | 2 - .../arg_inplace_locals_alias_ret.rs | 2 - .../tests/fail/provenance/mix-ptrs1.stderr | 2 +- .../tests/fail/provenance/mix-ptrs2.stderr | 2 +- src/tools/miri/tests/fail/rc_as_ptr.stderr | 2 +- .../drop_in_place_retag.stderr | 2 +- .../fail/stacked_borrows/load_invalid_mut.rs | 3 - .../return_invalid_mut_option.stderr | 4 +- .../return_invalid_mut_tuple.stderr | 4 +- .../static_memory_modification.rs | 2 +- .../static_memory_modification.stderr | 2 +- ...it_alloc_diagnostic_with_provenance.stderr | 4 +- .../validity/recursive-validity-box-bool.rs | 4 +- src/tools/miri/tests/pass/adjacent-allocs.rs | 3 +- .../pass/both_borrows/basic_aliasing_model.rs | 11 ++ .../pass/both_borrows/interior_mutability.rs | 11 ++ .../tests/pass/issues/issue-miri-1050-1.rs | 11 ++ .../tests/pass/issues/issue-miri-1050-2.rs | 12 ++ .../references.immut_ref.built.after.mir | 1 - .../custom/references.mut_ref.built.after.mir | 1 - tests/mir-opt/building/custom/references.rs | 2 - .../struct.main.DataflowConstProp.32bit.diff | 16 +- .../struct.main.DataflowConstProp.64bit.diff | 16 +- ...s.retags.DeadStoreElimination-initial.diff | 14 -- .../provenance_soundness.rs | 8 - ...ef.tuple.DeadStoreElimination-initial.diff | 4 +- ...g_operand.test.GVN.32bit.panic-unwind.diff | 2 +- ...g_operand.test.GVN.64bit.panic-unwind.diff | 2 +- ...ch_68867.try_sum.EarlyOtherwiseBranch.diff | 26 +-- ...ness.no_downcast.EarlyOtherwiseBranch.diff | 2 +- .../enum_opt.cand.EnumSizeOpt.32bit.diff | 8 +- .../enum_opt.cand.EnumSizeOpt.64bit.diff | 8 +- .../enum_opt.unin.EnumSizeOpt.32bit.diff | 8 +- .../enum_opt.unin.EnumSizeOpt.64bit.diff | 8 +- ...nential_common.GVN.32bit.panic-unwind.diff | 4 +- ...nential_common.GVN.64bit.panic-unwind.diff | 4 +- .../gvn_copy_aggregate.all_copy_2.GVN.diff | 6 +- ...ic_rust_call.call.Inline.panic-unwind.diff | 2 +- ...nline_box_fn.call.Inline.panic-unwind.diff | 2 +- ...line_closure_captures.foo.Inline.after.mir | 4 +- .../inline/inline_retag.bar.Inline.after.mir | 59 ------ tests/mir-opt/inline/inline_retag.rs | 29 --- ...67_inline_as_ref_as_mut.a.Inline.after.mir | 2 +- ...67_inline_as_ref_as_mut.b.Inline.after.mir | 4 +- ...67_inline_as_ref_as_mut.d.Inline.after.mir | 2 +- ....run2-{closure#0}.Inline.panic-unwind.diff | 4 +- ...conditions.JumpThreading.panic-unwind.diff | 8 +- ...ranches.bar.MatchBranchSimplification.diff | 8 +- ...ranches.foo.MatchBranchSimplification.diff | 2 +- ...tch_eq_bool.MatchBranchSimplification.diff | 2 +- ...h_i128_u128.MatchBranchSimplification.diff | 2 +- ...h_nested_if.MatchBranchSimplification.diff | 8 +- ...atch_option.MatchBranchSimplification.diff | 3 +- ...sext_i8_i16.MatchBranchSimplification.diff | 2 +- ...sext_i8_u16.MatchBranchSimplification.diff | 2 +- ...runc_i16_i8.MatchBranchSimplification.diff | 2 +- ...runc_i16_u8.MatchBranchSimplification.diff | 2 +- ...runc_u16_i8.MatchBranchSimplification.diff | 2 +- ...runc_u16_u8.MatchBranchSimplification.diff | 2 +- ...match_u8_i8.MatchBranchSimplification.diff | 2 +- ...tch_u8_i8_2.MatchBranchSimplification.diff | 2 +- ...zext_u8_i16.MatchBranchSimplification.diff | 2 +- ...zext_u8_u16.MatchBranchSimplification.diff | 2 +- ....my_is_some.MatchBranchSimplification.diff | 2 +- tests/mir-opt/matches_reduce_branches.rs | 2 +- ...stive_match.MatchBranchSimplification.diff | 2 +- ...ve_match_i8.MatchBranchSimplification.diff | 2 +- .../pre-codegen/deref_nested_borrows.rs | 2 +- ...f_nested_borrows.src.GVN.panic-unwind.diff | 4 +- ...rows.src.PreCodegen.after.panic-unwind.mir | 4 +- ...variant_a-{closure#0}.PreCodegen.after.mir | 8 +- ...variant_b-{closure#0}.PreCodegen.after.mir | 8 +- ...fg-pre-optimizations.after.panic-abort.mir | 169 ---------------- ...g-pre-optimizations.after.panic-unwind.mir | 169 ---------------- ...fg-pre-optimizations.after.panic-abort.mir | 17 -- ...g-pre-optimizations.after.panic-unwind.mir | 17 -- ...implifyCfg-make_shim.after.panic-abort.mir | 23 --- ...mplifyCfg-make_shim.after.panic-unwind.mir | 19 -- ...fg-pre-optimizations.after.panic-abort.mir | 21 -- ...g-pre-optimizations.after.panic-unwind.mir | 21 -- ...fg-pre-optimizations.after.panic-abort.mir | 168 ---------------- ...g-pre-optimizations.after.panic-unwind.mir | 180 ----------------- tests/mir-opt/retag.rs | 74 ------- ...fg-pre-optimizations.after.panic-abort.mir | 18 -- ...g-pre-optimizations.after.panic-unwind.mir | 18 -- ...fg-pre-optimizations.after.panic-abort.mir | 15 -- ...g-pre-optimizations.after.panic-unwind.mir | 15 -- ...mes.foo.ScalarReplacementOfAggregates.diff | 8 +- .../rustc_public/check_allocation.rs | 2 +- .../rustc_public/check_transform.rs | 2 +- tests/ui-fulldeps/rustc_public/projections.rs | 2 +- .../async-closure.stdout | 6 +- 220 files changed, 1039 insertions(+), 2416 deletions(-) delete mode 100644 compiler/rustc_mir_transform/src/add_retag.rs rename src/tools/miri/tests/fail/{stacked_borrows => both_borrows}/drop_in_place_protector.rs (57%) rename src/tools/miri/tests/fail/{stacked_borrows/drop_in_place_protector.stderr => both_borrows/drop_in_place_protector.stack.stderr} (74%) create mode 100644 src/tools/miri/tests/fail/both_borrows/drop_in_place_protector.tree.stderr delete mode 100644 src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs delete mode 100644 src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr delete mode 100644 src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr delete mode 100644 src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs delete mode 100644 src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr delete mode 100644 src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr create mode 100644 src/tools/miri/tests/pass/issues/issue-miri-1050-1.rs create mode 100644 src/tools/miri/tests/pass/issues/issue-miri-1050-2.rs delete mode 100644 tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff delete mode 100644 tests/mir-opt/inline/inline_retag.bar.Inline.after.mir delete mode 100644 tests/mir-opt/inline/inline_retag.rs delete mode 100644 tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir delete mode 100644 tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir delete mode 100644 tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-abort.mir delete mode 100644 tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-unwind.mir delete mode 100644 tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir delete mode 100644 tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir delete mode 100644 tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-abort.mir delete mode 100644 tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-unwind.mir delete mode 100644 tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir delete mode 100644 tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir delete mode 100644 tests/mir-opt/retag.rs delete mode 100644 tests/mir-opt/retag.{impl#0}-foo.SimplifyCfg-pre-optimizations.after.panic-abort.mir delete mode 100644 tests/mir-opt/retag.{impl#0}-foo.SimplifyCfg-pre-optimizations.after.panic-unwind.mir delete mode 100644 tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-abort.mir delete mode 100644 tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-unwind.mir diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 813ceaeb8da9f..8ddfa4b61edde 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -578,7 +578,6 @@ impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> { mir::StatementKind::FakeRead(..) | mir::StatementKind::SetDiscriminant { .. } | mir::StatementKind::StorageLive(..) - | mir::StatementKind::Retag { .. } | mir::StatementKind::PlaceMention(..) | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::Coverage(..) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 7bbce730c1658..61ee56a69127a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -4238,7 +4238,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // Otherwise, look at other types of assignment. let assigned_from = match rvalue { Rvalue::Ref(_, _, assigned_from) => assigned_from, - Rvalue::Use(operand) => match operand { + Rvalue::Use(operand, _) => match operand { Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { assigned_from } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 8ed62c92aa8bc..6a4f0038ba5d6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -875,7 +875,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { match rvalue { // If we see a use, we should check whether it is our data, and if so // update the place that we're looking for to that new place. - Rvalue::Use(operand) => match operand { + Rvalue::Use(operand, _) => match operand { Operand::Copy(place) | Operand::Move(place) => { if let Some(from) = place.as_local() { if from == target { diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 8b4bda8f7fefc..3c6ff0919f98a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -243,7 +243,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut target = place.local_or_deref_local(); for stmt in &self.body[location.block].statements[location.statement_index..] { debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target); - if let StatementKind::Assign(box (into, Rvalue::Use(from))) = &stmt.kind { + if let StatementKind::Assign(box (into, Rvalue::Use(from, _))) = &stmt.kind { debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); match from { Operand::Copy(place) | Operand::Move(place) diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 89e008f06ebc8..105756f518897 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -120,7 +120,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // to a user variable is when initializing it. // If that ever stops being the case, then the ever initialized // flow could be used. - if let Some(StatementKind::Assign(box (place, Rvalue::Use(Operand::Move(move_from))))) = + if let Some(StatementKind::Assign(box (place, Rvalue::Use(Operand::Move(move_from), _)))) = self.body.basic_blocks[location.block] .statements .get(location.statement_index) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index a0e53248c9047..db4942e812630 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1282,7 +1282,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(mir::Statement { source_info: _, kind: - mir::StatementKind::Assign(box (_, mir::Rvalue::Use(mir::Operand::Copy(place)))), + mir::StatementKind::Assign(box ( + _, + mir::Rvalue::Use(mir::Operand::Copy(place), _), + )), .. }) = first_assignment_stmt { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 114f9d864e735..877de757ccaa7 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -853,7 +853,6 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, ); } StatementKind::Nop - | StatementKind::Retag { .. } | StatementKind::SetDiscriminant { .. } => { bug!("Statement not allowed in this MIR phase") } @@ -1540,7 +1539,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { Rvalue::ThreadLocalRef(_) => {} - Rvalue::Use(operand) + Rvalue::Use(operand, _) | Rvalue::Repeat(operand, _) | Rvalue::UnaryOp(_ /*un_op*/, operand) | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/) => { @@ -1693,7 +1692,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { StatementKind::Assign(box ( _, Rvalue::Ref(_, _, source) - | Rvalue::Use(Operand::Copy(source) | Operand::Move(source)), + | Rvalue::Use(Operand::Copy(source) | Operand::Move(source), _), )) => { propagate_closure_used_mut_place(self, source); } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index 439aa1a91e068..136719a323ce1 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -83,7 +83,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { } StatementKind::ConstEvalCounter | StatementKind::Nop - | StatementKind::Retag { .. } | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::SetDiscriminant { .. } => { bug!("Statement not allowed in this MIR phase") @@ -294,7 +293,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { Rvalue::ThreadLocalRef(_) => {} - Rvalue::Use(operand) + Rvalue::Use(operand, _) | Rvalue::Repeat(operand, _) | Rvalue::UnaryOp(_ /*un_op*/, operand) | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/) => { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 47f14dc3df62e..94f4e8afeed5a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -694,7 +694,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { | StatementKind::FakeRead(..) | StatementKind::StorageLive(..) | StatementKind::StorageDead(..) - | StatementKind::Retag { .. } | StatementKind::Coverage(..) | StatementKind::ConstEvalCounter | StatementKind::PlaceMention(..) @@ -1649,7 +1648,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { .unwrap(); } - Rvalue::Use(_) + Rvalue::Use(_, _) | Rvalue::UnaryOp(_, _) | Rvalue::CopyForDeref(_) | Rvalue::BinaryOp(..) @@ -2210,8 +2209,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { /// rvalue and will be unified with the inferred type. fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option { match rvalue { - Rvalue::Use(_) - | Rvalue::ThreadLocalRef(_) + Rvalue::Use(..) + | Rvalue::ThreadLocalRef(..) | Rvalue::Repeat(..) | Rvalue::Ref(..) | Rvalue::RawPtr(..) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 4f483cdc5d6c7..3d15ad819310d 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -620,7 +620,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: let lval = codegen_place(fx, to_place_and_rval.0); let dest_layout = lval.layout(); match to_place_and_rval.1 { - Rvalue::Use(ref operand) => { + Rvalue::Use(ref operand, _) => { let val = codegen_operand(fx, operand); lval.write_cvalue(fx, val); } @@ -909,7 +909,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt: | StatementKind::ConstEvalCounter | StatementKind::Nop | StatementKind::FakeRead(..) - | StatementKind::Retag { .. } | StatementKind::PlaceMention(..) | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::AscribeUserType(..) => {} diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index ff8e6744bd32c..f85d21db11fb2 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -592,7 +592,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( }; computed_scalar_int = Some(scalar_int); } - Rvalue::Use(operand) => { + Rvalue::Use(operand, _) => { computed_scalar_int = mir_operand_get_const_val(fx, operand) } _ => return None, @@ -613,7 +613,6 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( | StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) - | StatementKind::Retag(_, _) | StatementKind::AscribeUserType(_, _) | StatementKind::PlaceMention(..) | StatementKind::Coverage(_) diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 5c14d6f2c0930..84013a00d79df 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -366,9 +366,12 @@ fn optimize_use_clone<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bb.terminator().source_info, mir::StatementKind::Assign(Box::new(( *destination, - mir::Rvalue::Use(mir::Operand::Copy( - arg_place.project_deeper(&[mir::ProjectionElem::Deref], tcx), - )), + mir::Rvalue::Use( + mir::Operand::Copy( + arg_place.project_deeper(&[mir::ProjectionElem::Deref], tcx), + ), + mir::WithRetag::Yes, + ), ))), )); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 2cb96c4ec0f59..571a8d5138a63 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -23,7 +23,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { rvalue: &mir::Rvalue<'tcx>, ) { match *rvalue { - mir::Rvalue::Use(ref operand) => { + mir::Rvalue::Use(ref operand, _) => { if let mir::Operand::Constant(const_op) = operand { let val = self.eval_mir_constant(&const_op); if val.all_bytes_uninit(self.cx.tcx()) { @@ -650,7 +650,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; OperandRef { val: OperandValue::Immediate(static_), layout, move_annotation: None } } - mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand), + mir::Rvalue::Use(ref operand, _) => self.codegen_operand(bx, operand), mir::Rvalue::Repeat(ref elem, len_const) => { // All arrays have `BackendRepr::Memory`, so only the ZST cases // end up here. Anything else forces the destination local to be diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index bc3ffa24d5289..1821710fbcc36 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -95,7 +95,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.memcpy(dst, align, src, align, bytes, crate::MemFlags::empty(), None); } mir::StatementKind::FakeRead(..) - | mir::StatementKind::Retag { .. } | mir::StatementKind::AscribeUserType(..) | mir::StatementKind::ConstEvalCounter | mir::StatementKind::PlaceMention(..) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index a45f1124f0af4..c7292ed0630f2 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -569,7 +569,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { match rvalue { Rvalue::ThreadLocalRef(_) => self.check_op(ops::ThreadLocalAccess), - Rvalue::Use(_) + Rvalue::Use(..) | Rvalue::CopyForDeref(..) | Rvalue::Repeat(..) | Rvalue::Discriminant(..) => {} @@ -724,7 +724,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { | StatementKind::FakeRead(..) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) - | StatementKind::Retag { .. } | StatementKind::PlaceMention(..) | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 1fbd0cd234057..b97510b773353 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -234,7 +234,7 @@ where Rvalue::CopyForDeref(place) => in_place::(cx, in_local, place.as_ref()), - Rvalue::Use(operand) + Rvalue::Use(operand, _) | Rvalue::Repeat(operand, _) | Rvalue::UnaryOp(_, operand) | Rvalue::Cast(_, operand, _) => in_operand::(cx, in_local, operand), diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index a19bf0b4da8be..32e8ac5335d9d 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -1,6 +1,6 @@ use std::borrow::{Borrow, Cow}; -use std::fmt; use std::hash::Hash; +use std::{fmt, mem}; use rustc_abi::{Align, FIRST_VARIANT, Size}; use rustc_ast::Mutability; @@ -21,8 +21,8 @@ use super::error::*; use crate::errors::{LongRunning, LongRunningWarn}; use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, - GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, Scalar, - compile_time_machine, ensure_monomorphic_enough, err_inval, interp_ok, throw_exhaust, + GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, RetagMode, + Scalar, compile_time_machine, ensure_monomorphic_enough, err_inval, interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_format, throw_unsup, throw_unsup_format, type_implements_dyn_trait, }; @@ -67,6 +67,9 @@ pub struct CompileTimeMachine<'tcx> { /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes). union_data_ranges: FxHashMap, RangeSet>, + + /// The current retag mode. + retag_mode: RetagMode, } #[derive(Copy, Clone)] @@ -102,6 +105,7 @@ impl<'tcx> CompileTimeMachine<'tcx> { check_alignment, static_root_ids: None, union_data_ranges: FxHashMap::default(), + retag_mode: RetagMode::Default, } } } @@ -824,9 +828,12 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { fn retag_ptr_value( ecx: &mut InterpCx<'tcx, Self>, - _kind: mir::RetagKind, val: &ImmTy<'tcx, CtfeProvenance>, - ) -> InterpResult<'tcx, ImmTy<'tcx, CtfeProvenance>> { + _ty: Ty<'tcx>, + ) -> InterpResult<'tcx, Option>> { + if matches!(ecx.machine.retag_mode, RetagMode::None | RetagMode::Raw) { + return interp_ok(None); + } // If it's a frozen shared reference that's not already immutable, potentially make it immutable. // (Do nothing on `None` provenance, that cannot store immutability anyway.) if let ty::Ref(_, ty, mutbl) = val.layout.ty.kind() @@ -850,12 +857,23 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { // even when there is interior mutability.) place.map_provenance(CtfeProvenance::as_shared_ref) }; - interp_ok(ImmTy::from_immediate(new_place.to_ref(ecx), val.layout)) + interp_ok(Some(ImmTy::from_immediate(new_place.to_ref(ecx), val.layout))) } else { - interp_ok(val.clone()) + interp_ok(None) } } + fn with_retag_mode( + ecx: &mut InterpCx<'tcx, Self>, + mode: RetagMode, + f: impl FnOnce(&mut InterpCx<'tcx, Self>) -> InterpResult<'tcx, T>, + ) -> InterpResult<'tcx, T> { + let old_mode = mem::replace(&mut ecx.machine.retag_mode, mode); + let ret = f(ecx); + ecx.machine.retag_mode = old_mode; + ret + } + fn before_memory_write( _tcx: TyCtxtAt<'tcx>, _machine: &mut Self, diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 802aa9ef4645a..9c554b24c6bc6 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -7,7 +7,7 @@ use std::borrow::Cow; use either::{Left, Right}; use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; use rustc_hir::def_id::DefId; -use rustc_hir::find_attr; +use rustc_hir::{LangItem, find_attr}; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; use rustc_middle::{bug, mir, span_bug}; @@ -16,12 +16,11 @@ use tracing::field::Empty; use tracing::{info, instrument, trace}; use super::{ - CtfeProvenance, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, - Projectable, Provenance, ReturnAction, ReturnContinuation, Scalar, interp_ok, throw_ub, - throw_ub_format, + CtfeProvenance, EnteredTraceSpan, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, + OpTy, PlaceTy, Projectable, Provenance, RetagMode, ReturnAction, ReturnContinuation, Scalar, + interp_ok, throw_ub, throw_ub_format, }; use crate::enter_trace_span; -use crate::interpret::EnteredTraceSpan; /// An argument passed to a function. #[derive(Clone, Debug)] @@ -277,6 +276,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { callee_arg: &mir::Place<'tcx>, callee_ty: Ty<'tcx>, already_live: bool, + is_drop_in_place: bool, ) -> InterpResult<'tcx> where 'tcx: 'x, @@ -321,7 +321,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.storage_live_dyn(local, meta)?; } // Now we can finally actually evaluate the callee place. - let callee_arg = self.eval_place(*callee_arg)?; + let mut callee_arg = self.eval_place(*callee_arg)?; + // drop_in_place has a signature which says that the first argument is `*mut T` + // but really it's `&mut T`. This is where we handle that terrible hack in + // the MIR semantics. + // FIXME(#154274): remove this hack. + if is_drop_in_place && callee_arg_idx == 0 { + let pointee_ty = callee_arg.layout.ty.builtin_deref(true).unwrap(); + let mutref_ty = Ty::new_mut_ref(*self.tcx, self.tcx.lifetimes.re_erased, pointee_ty); + callee_arg = callee_arg.transmute(self.layout_of(mutref_ty)?, self)?; + } // We allow some transmutes here. // FIXME: Depending on the PassMode, this should reset some padding to uninitialized. (This // is true for all `copy_op`, but there are a lot of special cases for argument passing @@ -453,77 +462,93 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Determine whether there is a special VaList argument. This is always the // last argument, and since arguments start at index 1 that's `arg_count`. let va_list_arg = callee_fn_abi.c_variadic.then(|| mir::Local::from_usize(body.arg_count)); - for local in body.args_iter() { - // Update the span that we show in case of an error to point to this argument. - self.frame_mut().loc = Right(body.local_decls[local].source_info.span); - // Construct the destination place for this argument. At this point all - // locals are still dead, so we cannot construct a `PlaceTy`. - let dest = mir::Place::from(local); - // `layout_of_local` does more than just the instantiation we need to get the - // type, but the result gets cached so this avoids calling the instantiation - // query *again* the next time this local is accessed. - let ty = self.layout_of_local(self.frame(), local, None)?.ty; - if Some(local) == va_list_arg { - // This is the last callee-side argument of a variadic function. - // This argument is a VaList holding the remaining caller-side arguments. - self.storage_live(local)?; - - let place = self.eval_place(dest)?; - let mplace = self.force_allocation(&place)?; - - // Consume the remaining arguments by putting them into the variable argument - // list. - let varargs = self.allocate_varargs( - &mut caller_args, - // "Ignored" arguments aren't actually passed, so the callee should also - // ignore them. (`pass_argument` does this for regular arguments.) - (&mut callee_args_abis).filter(|(_, abi)| !abi.is_ignore()), - )?; - // When the frame is dropped, these variable arguments are deallocated. - self.frame_mut().va_list = varargs.clone(); - let key = self.va_list_ptr(varargs.into()); - - // Zero the VaList, so it is fully initialized. - self.write_bytes_ptr(mplace.ptr(), (0..mplace.layout.size.bytes()).map(|_| 0u8))?; - - // Store the "key" pointer in the right field. - let key_mplace = self.va_list_key_field(&mplace)?; - self.write_pointer(key, &key_mplace)?; - } else if Some(local) == body.spread_arg { - // Make the local live once, then fill in the value field by field. - self.storage_live(local)?; - // Must be a tuple - let ty::Tuple(fields) = ty.kind() else { - span_bug!(self.cur_span(), "non-tuple type for `spread_arg`: {ty}") - }; - for (i, field_ty) in fields.iter().enumerate() { - let dest = dest.project_deeper( - &[mir::ProjectionElem::Field(FieldIdx::from_usize(i), field_ty)], - *self.tcx, - ); + // Part of the hack for #154274, see `pass_argument`. + let is_drop_in_place = { + let def_id = body.source.def_id(); + self.tcx.is_lang_item(def_id, LangItem::DropInPlace) + || self.tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace) + }; + + // During argument passing, we want retagging with protectors. + M::with_retag_mode(self, RetagMode::FnEntry, |ecx| { + for local in body.args_iter() { + // Update the span that we show in case of an error to point to this argument. + ecx.frame_mut().loc = Right(body.local_decls[local].source_info.span); + // Construct the destination place for this argument. At this point all + // locals are still dead, so we cannot construct a `PlaceTy`. + let dest = mir::Place::from(local); + // `layout_of_local` does more than just the instantiation we need to get the + // type, but the result gets cached so this avoids calling the instantiation + // query *again* the next time this local is accessed. + let ty = ecx.layout_of_local(ecx.frame(), local, None)?.ty; + if Some(local) == va_list_arg { + // This is the last callee-side argument of a variadic function. + // This argument is a VaList holding the remaining caller-side arguments. + ecx.storage_live(local)?; + + let place = ecx.eval_place(dest)?; + let mplace = ecx.force_allocation(&place)?; + + // Consume the remaining arguments by putting them into the variable argument + // list. + let varargs = ecx.allocate_varargs( + &mut caller_args, + // "Ignored" arguments aren't actually passed, so the callee should also + // ignore them. (`pass_argument` does this for regular arguments.) + (&mut callee_args_abis).filter(|(_, abi)| !abi.is_ignore()), + )?; + // When the frame is dropped, these variable arguments are deallocated. + ecx.frame_mut().va_list = varargs.clone(); + let key = ecx.va_list_ptr(varargs.into()); + + // Zero the VaList, so it is fully initialized. + ecx.write_bytes_ptr( + mplace.ptr(), + (0..mplace.layout.size.bytes()).map(|_| 0u8), + )?; + + // Store the "key" pointer in the right field. + let key_mplace = ecx.va_list_key_field(&mplace)?; + ecx.write_pointer(key, &key_mplace)?; + } else if Some(local) == body.spread_arg { + // Make the local live once, then fill in the value field by field. + ecx.storage_live(local)?; + // Must be a tuple + let ty::Tuple(fields) = ty.kind() else { + span_bug!(ecx.cur_span(), "non-tuple type for `spread_arg`: {ty}") + }; + for (i, field_ty) in fields.iter().enumerate() { + let dest = dest.project_deeper( + &[mir::ProjectionElem::Field(FieldIdx::from_usize(i), field_ty)], + *ecx.tcx, + ); + let (idx, callee_abi) = callee_args_abis.next().unwrap(); + ecx.pass_argument( + &mut caller_args, + callee_abi, + idx, + &dest, + field_ty, + /* already_live */ true, + is_drop_in_place, + )?; + } + } else { + // Normal argument. Cannot mark it as live yet, it might be unsized! let (idx, callee_abi) = callee_args_abis.next().unwrap(); - self.pass_argument( + ecx.pass_argument( &mut caller_args, callee_abi, idx, &dest, - field_ty, - /* already_live */ true, + ty, + /* already_live */ false, + is_drop_in_place, )?; } - } else { - // Normal argument. Cannot mark it as live yet, it might be unsized! - let (idx, callee_abi) = callee_args_abis.next().unwrap(); - self.pass_argument( - &mut caller_args, - callee_abi, - idx, - &dest, - ty, - /* already_live */ false, - )?; } - } + interp_ok(()) + })?; // Don't forget to check the return type! self.frame_mut().loc = Right(body.local_decls[mir::RETURN_PLACE].source_info.span); diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 62ca47d23b4ce..debcc2ac338b5 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -40,6 +40,21 @@ pub enum ReturnAction { NoCleanup, } +/// The currently active retagging mode. +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum RetagMode { + /// A regular retag. + Default, + /// Retag preparing for a two-phase borrow. + TwoPhase, + /// The initial retag of arguments when entering a function. + FnEntry, + /// Retagging for reference-to-raw-pointer cast. + Raw, + /// No retagging. + None, +} + /// Whether this kind of memory is allowed to leak pub trait MayLeak: Copy { fn may_leak(self) -> bool; @@ -481,25 +496,28 @@ pub trait Machine<'tcx>: Sized { } /// Executes a retagging operation for a single pointer. - /// Returns the possibly adjusted pointer. + /// Returns the possibly adjusted pointer. Return `None` if the pointer + /// was left unchanged. + /// + /// `ty` is the full type of the pointer. This is not the same as `val.layout.ty` for boxes + /// where `val` is just the inner raw pointer, but `ty` is the entire `Box` type. #[inline] fn retag_ptr_value( _ecx: &mut InterpCx<'tcx, Self>, - _kind: mir::RetagKind, - val: &ImmTy<'tcx, Self::Provenance>, - ) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> { - interp_ok(val.clone()) + _val: &ImmTy<'tcx, Self::Provenance>, + _ty: Ty<'tcx>, + ) -> InterpResult<'tcx, Option>> { + interp_ok(None) } - /// Executes a retagging operation on a compound value. - /// Replaces all pointers stored in the given place. - #[inline] - fn retag_place_contents( - _ecx: &mut InterpCx<'tcx, Self>, - _kind: mir::RetagKind, - _place: &PlaceTy<'tcx, Self::Provenance>, - ) -> InterpResult<'tcx> { - interp_ok(()) + /// Invoke `f` in a state where calls to `retag_ptr_value` will use the given retag mode. + #[inline(always)] + fn with_retag_mode( + ecx: &mut InterpCx<'tcx, Self>, + _mode: RetagMode, + f: impl FnOnce(&mut InterpCx<'tcx, Self>) -> InterpResult<'tcx, T>, + ) -> InterpResult<'tcx, T> { + f(ecx) } /// Called on places used for in-place function argument and return value handling. diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index c1d32e0f7bfbe..d52c1f9306444 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -29,7 +29,9 @@ pub use self::intern::{ HasStaticRootDefId, InternError, InternKind, intern_const_alloc_for_constprop, intern_const_alloc_recursive, }; -pub use self::machine::{AllocMap, Machine, MayLeak, ReturnAction, compile_time_machine}; +pub use self::machine::{ + AllocMap, Machine, MayLeak, RetagMode, ReturnAction, compile_time_machine, +}; pub use self::memory::{AllocInfo, AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; use self::operand::Operand; pub use self::operand::{ImmTy, Immediate, OpTy}; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index b410e8f6c57ea..95a92200501bd 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -834,17 +834,20 @@ where ) -> InterpResult<'tcx> { // These are technically *two* typed copies: `src` is a not-yet-loaded value, // so we're doing a typed copy at `src` type from there to some intermediate storage. - // And then we're doing a second typed copy from that intermediate storage to `dest`. - // But as an optimization, we only make a single direct copy here. + // And then we're doing a second typed copy at `dest` type from that intermediate storage to + // `dest`. But as an optimization, we only make a single direct copy here. // Do the actual copy. self.copy_op_no_validate(src, dest, allow_transmute)?; if M::enforce_validity(self, dest.layout()) { let dest = dest.to_place(); - // Given that there were two typed copies, we have to ensure this is valid at both types, - // and we have to ensure this loses provenance and padding according to both types. - // But if the types are identical, we only do one pass. + // Given that there were two typed copies, we have to ensure this is valid at both + // types, and we have to ensure this loses provenance and padding according to both + // types. We also transmute both ways: when transmuting `*ptr` from `&T` to `*const T`, + // it seems nice to ensure that the resulting pointer value indeed is derived from a + // shared reference. + // But if the types are identical, that is strictly redundant so we only do one pass. if src.layout().ty != dest.layout().ty { self.validate_operand( &dest.transmute(src.layout(), self)?, diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 2dee1157e2a12..98abfc11dd408 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -16,10 +16,9 @@ use tracing::field::Empty; use tracing::{info, instrument, trace}; use super::{ - FnArg, FnVal, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemPlaceMeta, PlaceTy, - Projectable, interp_ok, throw_ub, throw_unsup_format, + EnteredTraceSpan, FnArg, FnVal, ImmTy, Immediate, InterpCx, InterpResult, Machine, + MemPlaceMeta, PlaceTy, Projectable, RetagMode, interp_ok, throw_ub, throw_unsup_format, }; -use crate::interpret::EnteredTraceSpan; use crate::{enter_trace_span, util}; struct EvaluatedCalleeAndArgs<'tcx, M: Machine<'tcx>> { @@ -112,12 +111,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // interpreter is solely intended for borrowck'ed code. FakeRead(..) => {} - // Stacked Borrows. - Retag(kind, place) => { - let dest = self.eval_place(**place)?; - M::retag_place_contents(self, *kind, &dest)?; - } - Intrinsic(box intrinsic) => self.eval_nondiverging_intrinsic(intrinsic)?, // Evaluate the place expression, without reading from it. @@ -177,10 +170,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_pointer(ptr, &dest)?; } - Use(ref operand) => { + Use(ref operand, with_retag) => { // Avoid recomputing the layout let op = self.eval_operand(operand, Some(dest.layout))?; - self.copy_op(&op, &dest)?; + let mode = if with_retag.yes() { RetagMode::Default } else { RetagMode::None }; + M::with_retag_mode(self, mode, |ecx| ecx.copy_op(&op, &dest))?; } CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"), @@ -214,18 +208,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ref(_, borrow_kind, place) => { let src = self.eval_place(place)?; let place = self.force_allocation(&src)?; - let val = ImmTy::from_immediate(place.to_ref(self), dest.layout); - // A fresh reference was created, make sure it gets retagged. - let val = M::retag_ptr_value( - self, - if borrow_kind.is_two_phase_borrow() { - mir::RetagKind::TwoPhase - } else { - mir::RetagKind::Default - }, - &val, - )?; - self.write_immediate(*val, &dest)?; + let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout); + // A fresh reference was created, make sure it gets retagged with the right mode. + let mode = if borrow_kind.is_two_phase_borrow() { + RetagMode::TwoPhase + } else { + RetagMode::Default + }; + M::with_retag_mode(self, mode, |ecx| { + // If validation is disabled, we still want to do this retag. This is because + // const-eval disables validation for performance reasons but wants to retag + // shared references. So we add a bit of a hack here to do the retag manually + // if the write would not incur validation. + if !M::enforce_validity(ecx, val.layout) { + if let Some(new_val) = M::retag_ptr_value(ecx, &val, val.layout.ty)? { + val = new_val; + } + } + // Now do the actual write. + ecx.write_immediate(*val, &dest) + })?; } RawPtr(kind, place) => { @@ -244,8 +246,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { 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)?; + val = M::with_retag_mode(self, RetagMode::Raw, |ecx| { + interp_ok(M::retag_ptr_value(ecx, &val, val.layout.ty)?.unwrap_or(val)) + })?; } + // This writes a raw pointer so it will not do any retags. self.write_immediate(*val, &dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index de340057d0e81..a1f82692516dd 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -21,8 +21,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_middle::bug; use rustc_middle::mir::interpret::{ - InterpErrorKind, InvalidMetaKind, Misalignment, Provenance, UnsupportedOpInfo, alloc_range, - interp_ok, + InterpErrorKind, InvalidMetaKind, Misalignment, Provenance, alloc_range, interp_ok, }; use rustc_middle::ty::layout::{LayoutCx, TyAndLayout}; use rustc_middle::ty::{self, Ty}; @@ -108,17 +107,17 @@ macro_rules! try_validation { }}; } -#[derive(Debug, Clone, Copy)] -enum PointerKind { +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum PtrKind { Ref(Mutability), Box, } -impl fmt::Display for PointerKind { +impl fmt::Display for PtrKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let str = match self { - PointerKind::Ref(_) => "reference", - PointerKind::Box => "box", + PtrKind::Ref(_) => "reference", + PtrKind::Box => "box", }; write!(f, "{str}") } @@ -154,11 +153,11 @@ impl fmt::Display for ExpectedKind { } } -impl From for ExpectedKind { - fn from(x: PointerKind) -> ExpectedKind { +impl From for ExpectedKind { + fn from(x: PtrKind) -> ExpectedKind { match x { - PointerKind::Box => ExpectedKind::Box, - PointerKind::Ref(_) => ExpectedKind::Reference, + PtrKind::Box => ExpectedKind::Box, + PtrKind::Ref(_) => ExpectedKind::Reference, } } } @@ -545,34 +544,30 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { interp_ok(self.read_immediate(val, expected)?.to_scalar()) } - fn deref_pointer( + /// Given a place and a pointer loaded from that place, ensure that the place does + /// not store any more provenance than the pointer does. IOW, if any provenance + /// was discarded when loading the pointer, it will also get discarded in-memory. + fn reset_pointer_provenance( &mut self, - val: &PlaceTy<'tcx, M::Provenance>, - expected: ExpectedKind, - ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { - // Not using `ecx.deref_pointer` since we want to use our `read_immediate` wrapper. - let imm = self.read_immediate(val, expected)?; - // Reset provenance: ensure slice tail metadata does not preserve provenance, - // and ensure all pointers do not preserve partial provenance. - if self.reset_provenance_and_padding { - if matches!(imm.layout.backend_repr, BackendRepr::Scalar(..)) { - // A thin pointer. If it has provenance, we don't have to do anything. - // If it does not, ensure we clear the provenance in memory. - if matches!(imm.to_scalar(), Scalar::Int(..)) { - self.ecx.clear_provenance(val)?; - } - } else { - // A wide pointer. This means we have to worry both about the pointer itself and the - // metadata. We do the lazy thing and just write back the value we got. Just - // clearing provenance in a targeted manner would be more efficient, but unless this - // is a perf hotspot it's just not worth the effort. - self.ecx.write_immediate_no_validate(*imm, val)?; + place: &PlaceTy<'tcx, M::Provenance>, + ptr: &ImmTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx> { + if matches!(ptr.layout.backend_repr, BackendRepr::Scalar(..)) { + // A thin pointer. If it has provenance, we don't have to do anything. + // If it does not, ensure we clear the provenance in memory. + if !matches!(ptr.to_scalar(), Scalar::Ptr(..)) { + // The loaded pointer has no provenance. Some bytes of its representation still + // might have provenance, which we have to clear. + self.ecx.clear_provenance(place)?; } - // The entire thing is data, not padding. - self.add_data_range_place(val); + } else { + // A wide pointer. This means we have to worry both about the pointer itself and the + // metadata. We do the lazy thing and just write back the value we got. Just + // clearing provenance in a targeted manner would be more efficient, but unless this + // is a perf hotspot it's just not worth the effort. + self.ecx.write_immediate_no_validate(**ptr, place)?; } - // Now turn it into a place. - self.ecx.ref_to_mplace(&imm) + interp_ok(()) } fn check_wide_ptr_meta( @@ -610,12 +605,22 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { } /// Check a reference or `Box`. + /// + /// `ty` is the actual type of `value`; for a Box, `value` will be just the inner raw pointer. fn check_safe_pointer( &mut self, value: &PlaceTy<'tcx, M::Provenance>, - ptr_kind: PointerKind, + ty: Ty<'tcx>, + ptr_kind: PtrKind, ) -> InterpResult<'tcx> { - let place = self.deref_pointer(value, ptr_kind.into())?; + let ptr = self.read_immediate(value, ptr_kind.into())?; + if self.reset_provenance_and_padding { + // There's no padding in a pointer. + self.add_data_range_place(value); + // Resetting provenance is done below, together with retagging, to avoid + // redundant writes. + } + let place = self.ecx.ref_to_mplace(&ptr)?; // Handle wide pointers. // Check metadata early, for better diagnostics if place.layout.is_unsized() { @@ -640,8 +645,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // alignment should take attributes into account). .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); - // If we're not allow to dangle, make sure this is dereferenceable. - if !self.may_dangle { + // If we're not allow to dangle, make sure this is dereferenceable and retag it for + // the aliasing model. + let adjusted_ptr = if !self.may_dangle { try_validation!( self.ecx.check_ptr_access( place.ptr(), @@ -661,7 +667,44 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { Ub(PointerUseAfterFree(..)) => format!("encountered a dangling {ptr_kind} (use-after-free)"), ); + if self.reset_provenance_and_padding { + M::retag_ptr_value(self.ecx, &ptr, ty).map_err_kind(|e| match e { + Ub(WriteToReadOnly(_)) => { + err_validation_failure!( + self.path, + format!( + "encountered {} pointing to read-only memory", + if ptr_kind == PtrKind::Box { "box" } else { "mutable reference" }, + ) + ) + } + InterpErrorKind::MachineStop(mut machine_err) => { + // Enhance the aliasing model error with the current path. + if !self.path.projs.is_empty() { + let mut path = String::new(); + write_path(&mut path, &self.path.projs); + machine_err.with_validation_path(path); + } + InterpErrorKind::MachineStop(machine_err) + } + e => e, + })? + } else { + // We can't retag if we're not resetting provenance. + None + } + } else { + // Pointer remains unchanged. + None + }; + // If the pointer needs adjusting, write back adjusted pointer. This automatically + // also clears any excess provenance. Otherwise, just clear the provenance. + if let Some(ptr) = adjusted_ptr { + self.ecx.write_immediate_no_validate(*ptr, value)?; + } else if self.reset_provenance_and_padding { + self.reset_pointer_provenance(value, &ptr)?; } + // Check alignment after dereferenceable (if both are violated, trigger the error above). try_validation!( self.ecx.check_ptr_align( @@ -779,8 +822,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if size != Size::ZERO { // Determine whether this pointer expects to be pointing to something mutable. let ptr_expected_mutbl = match ptr_kind { - PointerKind::Box => Mutability::Mut, - PointerKind::Ref(mutbl) => { + PtrKind::Box => Mutability::Mut, + PtrKind::Ref(mutbl) => { // We do not take into account interior mutability here since we cannot know if // there really is an `UnsafeCell` inside `Option` -- so we check // that in the recursive descent behind this reference (controlled by @@ -883,14 +926,21 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { interp_ok(true) } ty::RawPtr(..) => { - let place = self.deref_pointer(value, ExpectedKind::RawPtr)?; + let ptr = self.read_immediate(value, ExpectedKind::RawPtr)?; + if self.reset_provenance_and_padding { + self.reset_pointer_provenance(value, &ptr)?; + // There's no padding in a pointer. + self.add_data_range_place(value); + } + + let place = self.ecx.ref_to_mplace(&ptr)?; if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta(), place.layout)?; } interp_ok(true) } ty::Ref(_, _ty, mutbl) => { - self.check_safe_pointer(value, PointerKind::Ref(*mutbl))?; + self.check_safe_pointer(value, ty, PtrKind::Ref(*mutbl))?; interp_ok(true) } ty::FnPtr(..) => { @@ -1296,10 +1346,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, #[inline] fn visit_box( &mut self, - _box_ty: Ty<'tcx>, + box_ty: Ty<'tcx>, val: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - self.check_safe_pointer(val, PointerKind::Box)?; + self.check_safe_pointer(&val, box_ty, PtrKind::Box)?; interp_ok(()) } @@ -1567,9 +1617,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .map_err_info(|err| { if !matches!( err.kind(), - err_ub!(ValidationError { .. }) + InterpErrorKind::UndefinedBehavior(ValidationError { .. }) | InterpErrorKind::InvalidProgram(_) - | InterpErrorKind::Unsupported(UnsupportedOpInfo::ExternTypeField) + | InterpErrorKind::Unsupported(_) + // We have to also ignore machine-specific errors since we do retagging + // during validation. + | InterpErrorKind::MachineStop(_) ) { bug!("Unexpected error during validation: {}", format_interp_error(err)); } diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index a8d472bc2ea23..49d57a11ae16d 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -124,7 +124,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { // ... that contains a `NonNull`... (gladly, only a single field here) assert_eq!(nonnull_ptr.layout().fields.count(), 1); - let raw_ptr = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // the actual raw ptr + let raw_ptr = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // ... whose only field finally is a raw ptr we can dereference. self.visit_box(ty, &raw_ptr)?; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index f9d583bdf18c7..d1a9d9e925cf0 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -822,7 +822,6 @@ fn test_unstable_options_tracking_hash() { tracked!(merge_functions, Some(MergeFunctions::Disabled)); tracked!(min_function_alignment, Some(Align::EIGHT)); tracked!(min_recursion_limit, Some(256)); - tracked!(mir_emit_retag, true); tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]); tracked!(mir_opt_level, Some(4)); tracked!(mir_preserve_ub, true); diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 6c7505a7cbbb0..6a6dc2e061beb 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -772,7 +772,10 @@ impl fmt::Display for ResourceExhaustionInfo { } /// A trait for machine-specific errors (or other "machine stop" conditions). -pub trait MachineStopType: Any + fmt::Display + fmt::Debug + Send {} +pub trait MachineStopType: Any + fmt::Display + fmt::Debug + Send { + /// This error occurred during validation, inside a value at the given path. + fn with_validation_path(&mut self, _path: String) {} +} impl dyn MachineStopType { #[inline(always)] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index a3746db653559..c4c23e0670141 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -652,7 +652,7 @@ impl<'tcx> Body<'tcx> { } match rvalue { - Rvalue::Use(Operand::Constant(constant)) => { + Rvalue::Use(Operand::Constant(constant), _) => { let bits = eval_mono_const(constant)?; Some((bits, targets)) } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index bf3d595e99436..0cb632d715bb1 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -810,17 +810,6 @@ impl Debug for StatementKind<'_> { FakeRead(box (ref cause, ref place)) => { write!(fmt, "FakeRead({cause:?}, {place:?})") } - Retag(ref kind, ref place) => write!( - fmt, - "Retag({}{:?})", - match kind { - RetagKind::FnEntry => "[fn entry] ", - RetagKind::TwoPhase => "[2phase] ", - RetagKind::Raw => "[raw] ", - RetagKind::Default => "", - }, - place, - ), StorageLive(ref place) => write!(fmt, "StorageLive({place:?})"), StorageDead(ref place) => write!(fmt, "StorageDead({place:?})"), SetDiscriminant { ref place, variant_index } => { @@ -1095,7 +1084,10 @@ impl<'tcx> Debug for Rvalue<'tcx> { use self::Rvalue::*; match *self { - Use(ref place) => write!(fmt, "{place:?}"), + Use(ref operand, with_retag) => { + // With retag is more common so we only print when it's without. + write!(fmt, "{}{operand:?}", if with_retag.no() { "no_retag " } else { "" }) + } Repeat(ref a, b) => { write!(fmt, "[{a:?}; ")?; pretty_print_const(b, fmt, false)?; diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index f66c4755de4dd..daa4207b0b6ef 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -52,7 +52,6 @@ impl<'tcx> StatementKind<'tcx> { StatementKind::SetDiscriminant { .. } => "SetDiscriminant", StatementKind::StorageLive(..) => "StorageLive", StatementKind::StorageDead(..) => "StorageDead", - StatementKind::Retag(..) => "Retag", StatementKind::PlaceMention(..) => "PlaceMention", StatementKind::AscribeUserType(..) => "AscribeUserType", StatementKind::Coverage(..) => "Coverage", @@ -757,7 +756,7 @@ impl<'tcx> Rvalue<'tcx> { // Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => false, - Rvalue::Use(_) + Rvalue::Use(_, _) | Rvalue::CopyForDeref(_) | Rvalue::Repeat(_, _) | Rvalue::Ref(_, _, _) @@ -790,7 +789,7 @@ impl<'tcx> Rvalue<'tcx> { D: ?Sized + HasLocalDecls<'tcx>, { match *self { - Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), + Rvalue::Use(ref operand, _) => operand.ty(local_decls, tcx), Rvalue::Repeat(ref operand, count) => { Ty::new_array_with_const_len(tcx, operand.ty(local_decls, tcx), count) } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 455089f285d17..e96ca668c6dc1 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -80,10 +80,6 @@ pub enum MirPhase { /// StateTransform pass will expand those async drops or reset to sync. /// - Unwinding: in analysis MIR, unwinding from a function which may not unwind aborts. In /// runtime MIR, this is UB. - /// - Retags: If `-Zmir-emit-retag` is enabled, analysis MIR has "implicit" retags in the same - /// way that Rust itself has them. Where exactly these are is generally subject to change, - /// and so we don't document this here. Runtime MIR has most retags explicit (though implicit - /// retags can still occur at `Rvalue::{Ref,AddrOf}`). /// - Coroutine bodies: In analysis MIR, locals may actually be behind a pointer that user code /// has access to. This occurs in coroutine bodies. Such locals do not behave like other /// locals, because they e.g. may be aliased in surprising ways. Runtime MIR has no such @@ -134,7 +130,6 @@ pub enum RuntimePhase { /// * [`LocalInfo::DerefTemp`](super::LocalInfo::DerefTemp) /// /// And the following variants are allowed: - /// * [`StatementKind::Retag`] /// * [`StatementKind::SetDiscriminant`] /// * [`PlaceElem::ConstantIndex`] / [`PlaceElem::Subslice`] after [`PlaceElem::Subslice`] /// @@ -313,7 +308,10 @@ pub enum StatementKind<'tcx> { /// all). The *exact* way this works is undecided. It probably does something like evaluating /// the LHS to a place and the RHS to a value, and then storing the value to the place. Various /// parts of this may do type specific things that are more complicated than simply copying - /// bytes. + /// bytes. In particular, the assignment will typically erase the contents of padding, + /// erase provenance from non-pointer types, and implicitly "retag" all references and boxes + /// that it copies, meaning that the resulting value is not an exact duplicate for all intents + /// and purposes of the original value. /// /// **Needs clarification**: The implication of the above idea would be that assignment implies /// that the resulting value is initialized. I believe we could commit to this separately from @@ -386,19 +384,6 @@ pub enum StatementKind<'tcx> { /// See `StorageLive` above. StorageDead(Local), - /// Retag references in the given place, ensuring they got fresh tags. - /// - /// This is part of the Stacked Borrows model. These statements are currently only interpreted - /// by miri and only generated when `-Z mir-emit-retag` is passed. See - /// for - /// more details. - /// - /// For code that is not specific to stacked borrows, you should consider retags to read and - /// modify the place in an opaque way. - /// - /// Only `RetagKind::Default` and `RetagKind::FnEntry` are permitted. - Retag(RetagKind, Box>), - /// This statement exists to preserve a trace of a scrutinee matched against a wildcard binding. /// This is especially useful for `let _ = PLACE;` bindings that desugar to a single /// `PlaceMention(PLACE)`. @@ -506,18 +491,23 @@ pub enum NonDivergingIntrinsic<'tcx> { CopyNonOverlapping(CopyNonOverlapping<'tcx>), } -/// Describes what kind of retag is to be performed. +/// Describes whether this operand use performs a retag. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] -pub enum RetagKind { - /// The initial retag of arguments when entering a function. - FnEntry, - /// Retag preparing for a two-phase borrow. - TwoPhase, - /// Retagging raw pointers. - Raw, - /// A "normal" retag. - Default, +pub enum WithRetag { + Yes, + No, +} + +impl WithRetag { + #[inline] + pub fn yes(self) -> bool { + matches!(self, Self::Yes) + } + #[inline] + pub fn no(self) -> bool { + matches!(self, Self::No) + } } /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. @@ -1366,8 +1356,8 @@ pub struct ConstOperand<'tcx> { /// value that an [`Operand`] produces. #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)] pub enum Rvalue<'tcx> { - /// Yields the operand unchanged - Use(Operand<'tcx>), + /// Yields the operand unchanged, except for a potential retag. + Use(Operand<'tcx>, WithRetag), /// Creates an array where each element is the value of the operand. /// diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 16a8743a6d67b..c660c77cd84a7 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -170,15 +170,6 @@ macro_rules! make_mir_visitor { self.super_coverage(kind, location); } - fn visit_retag( - &mut self, - kind: $(& $mutability)? RetagKind, - place: & $($mutability)? Place<'tcx>, - location: Location, - ) { - self.super_retag(kind, place, location); - } - fn visit_place( &mut self, place: & $($mutability)? Place<'tcx>, @@ -459,9 +450,6 @@ macro_rules! make_mir_visitor { location ); } - StatementKind::Retag(kind, place) => { - self.visit_retag($(& $mutability)? *kind, place, location); - } StatementKind::PlaceMention(place) => { self.visit_place( place, @@ -704,7 +692,7 @@ macro_rules! make_mir_visitor { location: Location ) { match rvalue { - Rvalue::Use(operand) => { + Rvalue::Use(operand, _with_retag) => { self.visit_operand(operand, location); } @@ -868,19 +856,6 @@ macro_rules! make_mir_visitor { ) { } - fn super_retag( - &mut self, - _kind: $(& $mutability)? RetagKind, - place: & $($mutability)? Place<'tcx>, - location: Location - ) { - self.visit_place( - place, - PlaceContext::MutatingUse(MutatingUseContext::Retag), - location, - ); - } - fn super_local_decl( &mut self, local: Local, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 68e43bbbea205..c81a69b2f316a 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -220,11 +220,11 @@ TrivialTypeTraversalImpls! { crate::mir::MirPhase, crate::mir::Promoted, crate::mir::RawPtrKind, - crate::mir::RetagKind, crate::mir::SourceInfo, crate::mir::SourceScope, crate::mir::SourceScopeLocalData, crate::mir::SwitchTargets, + crate::mir::WithRetag, crate::traits::IsConstable, crate::traits::OverflowError, crate::ty::AdtKind, diff --git a/compiler/rustc_mir_build/src/builder/cfg.rs b/compiler/rustc_mir_build/src/builder/cfg.rs index 2faccc43247c5..bb97d006734e9 100644 --- a/compiler/rustc_mir_build/src/builder/cfg.rs +++ b/compiler/rustc_mir_build/src/builder/cfg.rs @@ -57,7 +57,7 @@ impl<'tcx> CFG<'tcx> { block, source_info, temp, - Rvalue::Use(Operand::Constant(Box::new(constant))), + Rvalue::Use(Operand::Constant(Box::new(constant)), WithRetag::Yes), ); } @@ -72,11 +72,14 @@ impl<'tcx> CFG<'tcx> { block, source_info, place, - Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - user_ty: None, - const_: Const::zero_sized(tcx.types.unit), - }))), + Rvalue::Use( + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + user_ty: None, + const_: Const::zero_sized(tcx.types.unit), + })), + WithRetag::Yes, + ), ); } 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 a47a2e08c9f4b..64fd8881f9c76 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -23,9 +23,6 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { let op = self.parse_operand(args[0])?; Ok(StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(op)))) }, - @call(mir_retag, args) => { - Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?))) - }, @call(mir_set_discriminant, args) => { let place = self.parse_place(args[0])?; let var = self.parse_integer_literal(args[1])? as u32; @@ -287,7 +284,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { fields.iter().map(|f| self.parse_operand(f.expr)).collect::>()? )) }, - _ => self.parse_operand(expr_id).map(Rvalue::Use), + _ => self.parse_operand(expr_id).map(|op| Rvalue::Use(op, WithRetag::Yes)), ) } diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index a1b41510f1e1c..3cf4e43160e5d 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -346,11 +346,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => { block = this.stmt_expr(block, expr_id, None).into_block(); - block.and(Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span: expr_span, - user_ty: None, - const_: Const::zero_sized(this.tcx.types.unit), - })))) + block.and(Rvalue::Use( + Operand::Constant(Box::new(ConstOperand { + span: expr_span, + user_ty: None, + const_: Const::zero_sized(this.tcx.types.unit), + })), + WithRetag::Yes, + )) } ExprKind::Literal { .. } @@ -361,7 +364,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::ConstBlock { .. } | ExprKind::StaticRef { .. } => { let constant = this.as_constant(expr); - block.and(Rvalue::Use(Operand::Constant(Box::new(constant)))) + block.and(Rvalue::Use(Operand::Constant(Box::new(constant)), WithRetag::Yes)) } ExprKind::WrapUnsafeBinder { source } => { @@ -421,7 +424,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { NeedsTemporary::No, ) ); - block.and(Rvalue::Use(operand)) + block.and(Rvalue::Use(operand, WithRetag::Yes)) } ExprKind::ByUse { expr, span: _ } => { @@ -429,7 +432,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block = this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No) ); - block.and(Rvalue::Use(operand)) + block.and(Rvalue::Use(operand, WithRetag::Yes)) } } } @@ -468,7 +471,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let err = AssertKind::Overflow(op, lhs, rhs); block = self.assert(block, Operand::Move(of), false, err, span); - Rvalue::Use(Operand::Move(val)) + Rvalue::Use(Operand::Move(val), WithRetag::Yes) } BinOp::Shl | BinOp::Shr if self.check_overflow && ty.is_integral() => { // For an unsigned RHS, the shift is in-range for `rhs < bits`. diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 446b2939e3705..fd77e48420df6 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -440,7 +440,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, destination, // Move from `b` so that does not get dropped any more. - Rvalue::Use(Operand::Move(b)), + Rvalue::Use(Operand::Move(b), WithRetag::Yes), ); block.unit() } @@ -493,7 +493,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, destination, - Rvalue::Use(Operand::Copy(place)), + Rvalue::Use(Operand::Copy(place), WithRetag::Yes), ); block.unit() } else if this.infcx.type_is_use_cloned_modulo_regions(this.param_env, ty) { @@ -530,7 +530,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, destination, - Rvalue::Use(Operand::Move(place)), + Rvalue::Use(Operand::Move(place), WithRetag::Yes), ); block.unit() } @@ -812,7 +812,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug_assert!(Category::of(&expr.kind) == Some(Category::Place)); let place = unpack!(block = this.as_place(block, expr_id)); - let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); + let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place), WithRetag::Yes); this.cfg.push_assign(block, source_info, destination, rvalue); block.unit() } @@ -827,7 +827,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let place = unpack!(block = this.as_place(block, expr_id)); - let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); + let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place), WithRetag::Yes); this.cfg.push_assign(block, source_info, destination, rvalue); block.unit() } diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index d4f5fe84e0ff9..d4a7f4c027444 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -2739,7 +2739,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard); } let rvalue = match binding.binding_mode.0 { - ByRef::No => Rvalue::Use(self.consume_by_copy_or_move(binding.source)), + ByRef::No => { + Rvalue::Use(self.consume_by_copy_or_move(binding.source), WithRetag::Yes) + } ByRef::Yes(pinnedness, mutbl) => { let rvalue = Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source); diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index d8911870d3ad4..7d05b38272f69 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -281,7 +281,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // actual = len(place) let length_op = self.len_of_slice_or_array(block, place, test.span, source_info); - self.cfg.push_assign(block, source_info, actual, Rvalue::Use(length_op)); + self.cfg.push_assign( + block, + source_info, + actual, + Rvalue::Use(length_op, WithRetag::Yes), + ); // expected = let expected = self.push_usize(block, source_info, len); diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 01c1e2e79b501..ac1cc377df8ed 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -885,7 +885,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { for stmt in &bb.statements { match &stmt.kind { // Ignore the implicit `()` return place assignment for unit functions/blocks - StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(const_)))) + StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(const_), _))) if const_.ty().is_unit() => { continue; diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 91610e768d012..8a7bd303b3032 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -957,7 +957,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { (state_ty.discriminant_ty(self.tcx), Rvalue::Discriminant(scope.state_place)) } ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Bool | ty::Char => { - (state_ty, Rvalue::Use(Operand::Copy(scope.state_place))) + (state_ty, Rvalue::Use(Operand::Copy(scope.state_place), WithRetag::Yes)) } _ => span_bug!(state_decl.source_info.span, "unsupported #[loop_match] state"), }; diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index e439f2e052fe8..be18e42f6088c 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -243,7 +243,6 @@ impl<'a> MaybeTransitiveLiveLocals<'a> { StatementKind::FakeRead(_) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) - | StatementKind::Retag(..) | StatementKind::AscribeUserType(..) | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index 3702f7c55a431..4a52e468eb5b5 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -169,7 +169,6 @@ impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> { | StatementKind::FakeRead(..) | StatementKind::ConstEvalCounter | StatementKind::Nop - | StatementKind::Retag(..) | StatementKind::Intrinsic(..) | StatementKind::BackwardIncompatibleDropHint { .. } | StatementKind::StorageLive(..) => {} diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 224abf6901b33..06d89c646e454 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -410,8 +410,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { "SetDiscriminant/Deinit should not exist during borrowck" ); } - StatementKind::Retag { .. } - | StatementKind::AscribeUserType(..) + StatementKind::AscribeUserType(..) | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) | StatementKind::Intrinsic(..) @@ -424,7 +423,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { match *rvalue { Rvalue::ThreadLocalRef(_) => {} // not-a-move - Rvalue::Use(ref operand) + Rvalue::Use(ref operand, _) | Rvalue::Repeat(ref operand, _) | Rvalue::Cast(_, ref operand, _) | Rvalue::UnaryOp(_, ref operand) diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 5b5afd7ecc7db..fc59ece18879c 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -97,7 +97,7 @@ where (PeekCallKind::ByRef, mir::Rvalue::Ref(_, _, place)) | ( PeekCallKind::ByVal, - mir::Rvalue::Use(mir::Operand::Move(place) | mir::Operand::Copy(place)), + mir::Rvalue::Use(mir::Operand::Move(place) | mir::Operand::Copy(place), _), ) => { let loc = Location { block: bb, statement_index }; cursor.seek_before_primary_effect(loc); diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 055d124386cf9..6cef4c96cb170 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -441,7 +441,7 @@ impl<'tcx> Map<'tcx> { for stmt in bbdata.statements.iter() { let Some((lhs, rhs)) = stmt.kind.as_assign() else { continue }; match rhs { - Rvalue::Use(Operand::Move(rhs) | Operand::Copy(rhs)) + Rvalue::Use(Operand::Move(rhs) | Operand::Copy(rhs), _) | Rvalue::CopyForDeref(rhs) => { let Some(lhs) = self.register_place_and_discr(tcx, body, *lhs) else { continue; diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 9950a94d722eb..2216669499feb 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -100,7 +100,7 @@ fn add_move_for_packed_drop<'tcx>( )); patch.add_statement(loc, StatementKind::StorageLive(temp)); - patch.add_assign(loc, Place::from(temp), Rvalue::Use(Operand::Move(*place))); + patch.add_assign(loc, Place::from(temp), Rvalue::Use(Operand::Move(*place), WithRetag::Yes)); patch.patch_terminator( loc.block, TerminatorKind::Drop { diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs deleted file mode 100644 index fc08c1df8703a..0000000000000 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ /dev/null @@ -1,186 +0,0 @@ -//! This pass adds validation calls (AcquireValid, ReleaseValid) where appropriate. -//! It has to be run really early, before transformations like inlining, because -//! introducing these calls *adds* UB -- so, conceptually, this pass is actually part -//! of MIR building, and only after this pass we think of the program has having the -//! normal MIR semantics. - -use rustc_middle::mir::*; -use rustc_middle::ty::{self, Ty, TyCtxt}; - -pub(super) struct AddRetag; - -/// Determine whether this type may contain a reference (or box), and thus needs retagging. -/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this. -fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool { - match ty.kind() { - // Primitive types that are not references - ty::Bool - | ty::Char - | ty::Float(_) - | ty::Int(_) - | ty::Uint(_) - | ty::RawPtr(..) - | ty::FnPtr(..) - | ty::Str - | ty::FnDef(..) - | ty::Never => false, - // References and Boxes (`noalias` sources) - ty::Ref(..) => true, - ty::Adt(..) if ty.is_box() => true, - // Compound types: recurse - ty::Array(ty, _) | ty::Slice(ty) => { - // This does not branch so we keep the depth the same. - may_contain_reference(*ty, depth, tcx) - } - ty::Tuple(tys) => { - depth == 0 || tys.iter().any(|ty| may_contain_reference(ty, depth - 1, tcx)) - } - ty::Adt(adt, args) => { - depth == 0 - || adt.variants().iter().any(|v| { - v.fields.iter().any(|f| may_contain_reference(f.ty(tcx, args), depth - 1, tcx)) - }) - } - // Conservative fallback - _ => true, - } -} - -impl<'tcx> crate::MirPass<'tcx> for AddRetag { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.opts.unstable_opts.mir_emit_retag - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // We need an `AllCallEdges` pass before we can do any work. - super::add_call_guards::AllCallEdges.run_pass(tcx, body); - - let basic_blocks = body.basic_blocks.as_mut(); - let local_decls = &body.local_decls; - let needs_retag = |place: &Place<'tcx>| { - // We're not really interested in stores to "outside" locations, they are hard to keep - // track of anyway. - !place.is_indirect_first_projection() - && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx) - && !local_decls[place.local].is_deref_temp() - }; - - // PART 1 - // Retag arguments at the beginning of the start block. - { - // Gather all arguments, skip return value. - let places = local_decls.iter_enumerated().skip(1).take(body.arg_count).filter_map( - |(local, decl)| { - let place = Place::from(local); - needs_retag(&place).then_some((place, decl.source_info)) - }, - ); - - // Emit their retags. - basic_blocks[START_BLOCK].statements.splice( - 0..0, - places.map(|(place, source_info)| { - Statement::new( - source_info, - StatementKind::Retag(RetagKind::FnEntry, Box::new(place)), - ) - }), - ); - } - - // PART 2 - // Retag return values of functions. - // We collect the return destinations because we cannot mutate while iterating. - let returns = basic_blocks - .iter_mut() - .filter_map(|block_data| { - match block_data.terminator().kind { - TerminatorKind::Call { target: Some(target), destination, .. } - if needs_retag(&destination) => - { - // Remember the return destination for later - Some((block_data.terminator().source_info, destination, target)) - } - - // `Drop` is also a call, but it doesn't return anything so we are good. - TerminatorKind::Drop { .. } => None, - // Not a block ending in a Call -> ignore. - _ => None, - } - }) - .collect::>(); - // Now we go over the returns we collected to retag the return values. - for (source_info, dest_place, dest_block) in returns { - basic_blocks[dest_block].statements.insert( - 0, - Statement::new( - source_info, - StatementKind::Retag(RetagKind::Default, Box::new(dest_place)), - ), - ); - } - - // PART 3 - // Add retag after assignments. - for block_data in basic_blocks { - // We want to insert statements as we iterate. To this end, we - // iterate backwards using indices. - for i in (0..block_data.statements.len()).rev() { - let (retag_kind, place) = match block_data.statements[i].kind { - // Retag after assignments of reference type. - StatementKind::Assign(box (ref place, ref rvalue)) => { - let add_retag = match rvalue { - // Ptr-creating operations already do their own internal retagging, no - // need to also add a retag statement. *Except* if we are deref'ing a - // Box, because those get desugared to directly working with the inner - // raw pointer! That's relevant for `RawPtr` as Miri otherwise makes it - // a NOP when the original pointer is already raw. - Rvalue::RawPtr(_mutbl, place) => { - // Using `is_box_global` here is a bit sketchy: if this code is - // generic over the allocator, we'll not add a retag! This is a hack - // to make Stacked Borrows compatible with custom allocator code. - // It means the raw pointer inherits the tag of the box, which mostly works - // but can sometimes lead to unexpected aliasing errors. - // Long-term, we'll want to move to an aliasing model where "cast to - // raw pointer" is a complete NOP, and then this will no longer be - // an issue. - if place.is_indirect_first_projection() - && body.local_decls[place.local].ty.is_box_global(tcx) - { - Some(RetagKind::Raw) - } else { - None - } - } - Rvalue::Ref(..) => None, - _ => { - if needs_retag(place) { - Some(RetagKind::Default) - } else { - None - } - } - }; - if let Some(kind) = add_retag { - (kind, *place) - } else { - continue; - } - } - // Do nothing for the rest - _ => continue, - }; - // Insert a retag after the statement. - let source_info = block_data.statements[i].source_info; - block_data.statements.insert( - i + 1, - Statement::new(source_info, StatementKind::Retag(retag_kind, Box::new(place))), - ); - } - } - } - - fn is_required(&self) -> bool { - true - } -} diff --git a/compiler/rustc_mir_transform/src/check_enums.rs b/compiler/rustc_mir_transform/src/check_enums.rs index 12447dc7cbb0c..56f3ddc962528 100644 --- a/compiler/rustc_mir_transform/src/check_enums.rs +++ b/compiler/rustc_mir_transform/src/check_enums.rs @@ -430,11 +430,14 @@ fn insert_uninhabited_enum_check<'tcx>( source_info, StatementKind::Assign(Box::new(( is_ok, - Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - user_ty: None, - const_: Const::Val(ConstValue::from_bool(false), tcx.types.bool), - }))), + Rvalue::Use( + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + user_ty: None, + const_: Const::Val(ConstValue::from_bool(false), tcx.types.bool), + })), + WithRetag::Yes, // it's a bool, retag doesn't matter + ), ))), )); diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index e04cb26e89902..14e0545032a5d 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -102,7 +102,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { // Do not leave tautological assignments around. if let StatementKind::Assign(box (lhs, ref rhs)) = stmt.kind - && let Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)) = *rhs + && let Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _) = *rhs && lhs == rhs { stmt.make_nop(true); diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 332196e3afee7..3391555f8803e 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -237,17 +237,20 @@ impl<'tcx> TransformVisitor<'tcx> { let ty::Adt(_poll_adt, args) = *self.old_yield_ty.kind() else { bug!() }; let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() }; let yield_ty = args.type_at(0); - Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - const_: Const::Unevaluated( - UnevaluatedConst::new( - self.tcx.require_lang_item(LangItem::AsyncGenFinished, body.span), - self.tcx.mk_args(&[yield_ty.into()]), + Rvalue::Use( + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + const_: Const::Unevaluated( + UnevaluatedConst::new( + self.tcx.require_lang_item(LangItem::AsyncGenFinished, body.span), + self.tcx.mk_args(&[yield_ty.into()]), + ), + self.old_yield_ty, ), - self.old_yield_ty, - ), - user_ty: None, - }))) + user_ty: None, + })), + WithRetag::Yes, + ) } }; @@ -306,22 +309,25 @@ impl<'tcx> TransformVisitor<'tcx> { let ty::Adt(_poll_adt, args) = *self.old_yield_ty.kind() else { bug!() }; let ty::Adt(_option_adt, args) = *args.type_at(0).kind() else { bug!() }; let yield_ty = args.type_at(0); - Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span: source_info.span, - const_: Const::Unevaluated( - UnevaluatedConst::new( - self.tcx.require_lang_item( - LangItem::AsyncGenFinished, - source_info.span, + Rvalue::Use( + Operand::Constant(Box::new(ConstOperand { + span: source_info.span, + const_: Const::Unevaluated( + UnevaluatedConst::new( + self.tcx.require_lang_item( + LangItem::AsyncGenFinished, + source_info.span, + ), + self.tcx.mk_args(&[yield_ty.into()]), ), - self.tcx.mk_args(&[yield_ty.into()]), + self.old_yield_ty, ), - self.old_yield_ty, - ), - user_ty: None, - }))) + user_ty: None, + })), + WithRetag::Yes, + ) } else { - Rvalue::Use(val) + Rvalue::Use(val, WithRetag::Yes) } } CoroutineKind::Coroutine(_) => { @@ -545,19 +551,13 @@ fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body let pin_field = tcx.mk_place_field(SELF_ARG.into(), FieldIdx::ZERO, ref_coroutine_ty); let statements = &mut body.basic_blocks.as_mut_preserves_cfg()[START_BLOCK].statements; - // Miri requires retags to be the very first thing in the body. - // We insert this assignment just after. - let insert_point = statements - .iter() - .position(|stmt| !matches!(stmt.kind, StatementKind::Retag(..))) - .unwrap_or(statements.len()); statements.insert( - insert_point, + 0, Statement::new( source_info, StatementKind::Assign(Box::new(( unpinned_local.into(), - Rvalue::Use(Operand::Copy(pin_field)), + Rvalue::Use(Operand::Copy(pin_field), WithRetag::Yes), ))), ), ); @@ -626,7 +626,7 @@ fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local let [arg] = *Box::try_from(args).unwrap(); let local = arg.node.place().unwrap().local; - let arg = Rvalue::Use(arg.node); + let arg = Rvalue::Use(arg.node, WithRetag::Yes); let assign = Statement::new(terminator.source_info, StatementKind::Assign(Box::new((destination, arg)))); bb_data.statements.push(assign); @@ -1369,7 +1369,7 @@ fn create_cases<'tcx>( source_info, StatementKind::Assign(Box::new(( point.resume_arg, - Rvalue::Use(Operand::Move(CTX_ARG.into())), + Rvalue::Use(Operand::Move(CTX_ARG.into()), WithRetag::Yes), ))), )); } @@ -1599,7 +1599,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { args_iter.filter_map(|local| { let (ty, variant_index, idx) = transform.remap[local]?; let lhs = transform.make_field(variant_index, idx, ty); - let rhs = Rvalue::Use(Operand::Move(local.into())); + let rhs = Rvalue::Use(Operand::Move(local.into()), WithRetag::Yes); let assign = StatementKind::Assign(Box::new((lhs, rhs))); Some(Statement::new(source_info, assign)) }), @@ -1755,7 +1755,6 @@ impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> { | StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) - | StatementKind::Retag(..) | StatementKind::AscribeUserType(..) | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index 2699a051a8fea..da2f6719dbdbf 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -328,7 +328,7 @@ pub(super) fn expand_async_drops<'tcx>( // First state-loop yield for mainline let context_ref_place = Place::from(body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span))); - let arg = Rvalue::Use(Operand::Move(Place::from(CTX_ARG))); + let arg = Rvalue::Use(Operand::Move(Place::from(CTX_ARG)), WithRetag::Yes); body[bb].statements.push(Statement::new( source_info, StatementKind::Assign(Box::new((context_ref_place, arg))), diff --git a/compiler/rustc_mir_transform/src/coverage/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/from_mir.rs index e1623f590a8eb..0ed6e455884d9 100644 --- a/compiler/rustc_mir_transform/src/coverage/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/from_mir.rs @@ -91,7 +91,6 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option { ) | StatementKind::Assign(_) | StatementKind::SetDiscriminant { .. } - | StatementKind::Retag(_, _) | StatementKind::PlaceMention(..) | StatementKind::AscribeUserType(_, _) => Some(statement.source_info.span), diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 122429276e3c5..db65820b1ade4 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -177,9 +177,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { FlatSet::::BOTTOM, ); } - StatementKind::Retag(..) => { - // We don't track references. - } StatementKind::ConstEvalCounter | StatementKind::Nop | StatementKind::FakeRead(..) @@ -299,7 +296,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { state: &mut State>, ) { match rvalue { - Rvalue::Use(operand) => { + Rvalue::Use(operand, _) => { state.flood(target.as_ref(), &self.map); if let Some(target) = self.map.find(target.as_ref()) { self.assign_operand(state, target, operand); @@ -465,7 +462,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), &self.map), - Rvalue::Use(operand) => return self.handle_operand(operand, state), + Rvalue::Use(operand, _) => return self.handle_operand(operand, state), Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"), Rvalue::Ref(..) | Rvalue::RawPtr(..) => { // We don't track such places. @@ -976,7 +973,7 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> location: Location, ) { match statement.kind { - StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(_)))) => { + StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(_), _))) => { // Don't overwrite the assignment if it already uses a constant (to keep the span). } StatementKind::Assign(box (place, _)) => { @@ -1019,7 +1016,11 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> { if let Some(value) = self.assignments.get(&location) { match &mut statement.kind { StatementKind::Assign(box (_, rvalue)) => { - *rvalue = Rvalue::Use(self.make_operand(*value)); + let old_retag = match rvalue { + Rvalue::Use(_, retag) => *retag, + _ => WithRetag::Yes, + }; + *rvalue = Rvalue::Use(self.make_operand(*value), old_retag); } _ => bug!("found assignment info for non-assign statement"), } diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index 1f380302804b9..4631c8ff680ca 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -58,7 +58,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> { if self.add_deref_metadata { Rvalue::CopyForDeref(deref_place) } else { - Rvalue::Use(Operand::Copy(deref_place)) + // FIXME: Unfortunately, `add_deref_metadata` is not documented. So who + // knows what is supposed to happen here -- retag or not? `CopyForDeref` + // later turns into a no-retag assignment so probably maybe that's also + // what we need here. + Rvalue::Use(Operand::Copy(deref_place), WithRetag::No) }, ); place_local = temp; diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 8c2149ef96fb0..3be3c19ab198e 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -284,7 +284,7 @@ impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> { match &statement.kind { StatementKind::Assign(box (dest, rvalue)) => { match rvalue { - Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) => { + Rvalue::Use(Operand::Copy(place) | Operand::Move(place), _) => { // These might've been turned into self-assignments by the replacement // (this includes the original statement we wanted to eliminate). if dest == place { @@ -398,7 +398,7 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { if let StatementKind::Assign(box ( lhs, - Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), + Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _), )) = &statement.kind && let Some(src) = lhs.as_local() && let Some(dest) = rhs.as_local() @@ -574,7 +574,7 @@ fn save_as_intervals<'tcx>( StatementKind::Assign(box ( lhs, Rvalue::CopyForDeref(rhs) - | Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), + | Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _), )) => lhs.projection == rhs.projection, _ => false, }; diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 1fe745a5d5197..a6c6c74b11af7 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -359,11 +359,10 @@ where let obj_ref_place = Place::from(self.new_temp(unwrap_ty)); call_statements.push(self.assign( obj_ref_place, - Rvalue::Use(Operand::Copy(tcx.mk_place_field( - pin_obj_place, - FieldIdx::ZERO, - unwrap_ty, - ))), + Rvalue::Use( + Operand::Copy(tcx.mk_place_field(pin_obj_place, FieldIdx::ZERO, unwrap_ty)), + WithRetag::Yes, + ), )); let obj_ptr_place = Place::from(self.new_temp(obj_ptr_ty)); @@ -1278,7 +1277,7 @@ where Operand::Copy(Place::from(self.place.local)), ), ), - self.assign(cur.into(), Rvalue::Use(zero)), + self.assign(cur.into(), Rvalue::Use(zero, WithRetag::Yes)), ], Some(Terminator { source_info: self.source_info, diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 833a671de1d7d..3787276919cf5 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -403,11 +403,14 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { } fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { - Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span, - user_ty: None, - const_: Const::from_bool(self.tcx, val), - }))) + Rvalue::Use( + Operand::Constant(Box::new(ConstOperand { + span, + user_ty: None, + const_: Const::from_bool(self.tcx, val), + })), + WithRetag::Yes, + ) } fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) { diff --git a/compiler/rustc_mir_transform/src/erase_deref_temps.rs b/compiler/rustc_mir_transform/src/erase_deref_temps.rs index ee0c7715c3cb5..445c567bcb661 100644 --- a/compiler/rustc_mir_transform/src/erase_deref_temps.rs +++ b/compiler/rustc_mir_transform/src/erase_deref_temps.rs @@ -16,7 +16,9 @@ impl<'tcx> MutVisitor<'tcx> for EraseDerefTempsVisitor<'tcx> { fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, _: Location) { if let &mut Rvalue::CopyForDeref(place) = rvalue { - *rvalue = Rvalue::Use(Operand::Copy(place)) + // We do *NOT* want a retag here! This assignment might copy a mutable reference we + // can't actually copy, we just need it temporarily to create another pointer. + *rvalue = Rvalue::Use(Operand::Copy(place), WithRetag::No) } } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index e9a20aa016550..55e68cd8dba9b 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1035,7 +1035,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { ) -> Option { let value = match *rvalue { // Forward values. - Rvalue::Use(ref mut operand) => return self.simplify_operand(operand, location), + Rvalue::Use(ref mut operand, _) => return self.simplify_operand(operand, location), // Roots. Rvalue::Repeat(ref mut op, amount) => { @@ -1237,7 +1237,8 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { if let Some(value) = self.simplify_aggregate_to_copy(ty, variant_index, &fields) { if let Some(place) = self.try_as_place(value, location, true) { self.reused_locals.insert(place.local); - *rvalue = Rvalue::Use(Operand::Copy(place)); + // FIXME: Is it correct to make these retagging assignments? + *rvalue = Rvalue::Use(Operand::Copy(place), WithRetag::Yes); } return Some(value); } @@ -1993,13 +1994,13 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> { let value = self.simplify_rvalue(lhs, rvalue, location); if let Some(value) = value { + // FIXME: Is it correct to make these retagging assignments? if let Some(const_) = self.try_as_constant(value) { - *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); + *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_)), WithRetag::Yes); } else if let Some(place) = self.try_as_place(value, location, false) - && *rvalue != Rvalue::Use(Operand::Move(place)) - && *rvalue != Rvalue::Use(Operand::Copy(place)) + && !matches!(rvalue, Rvalue::Use(Operand::Move(p) | Operand::Copy(p), _) if p == &place) { - *rvalue = Rvalue::Use(Operand::Copy(place)); + *rvalue = Rvalue::Use(Operand::Copy(place), WithRetag::Yes); self.reused_locals.insert(place.local); } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index afcea3236dbda..85753b2f984fa 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -962,7 +962,7 @@ fn inline_call<'tcx, I: Inliner<'tcx>>( callsite.source_info, StatementKind::Assign(Box::new(( dest, - Rvalue::Use(Operand::Move(destination_local.into())), + Rvalue::Use(Operand::Move(destination_local.into()), WithRetag::Yes), ))), )); n += 1; @@ -1134,7 +1134,7 @@ fn create_temp_if_necessary<'tcx, I: Inliner<'tcx>>( let local = new_call_temp(caller_body, callsite, arg_ty, return_block); caller_body[callsite.block].statements.push(Statement::new( callsite.source_info, - StatementKind::Assign(Box::new((Place::from(local), Rvalue::Use(arg)))), + StatementKind::Assign(Box::new((Place::from(local), Rvalue::Use(arg, WithRetag::Yes)))), )); local } @@ -1271,16 +1271,6 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { self.in_cleanup_block = false; } - fn visit_retag(&mut self, kind: &mut RetagKind, place: &mut Place<'tcx>, loc: Location) { - self.super_retag(kind, place, loc); - - // We have to patch all inlined retags to be aware that they are no longer - // happening on function entry. - if *kind == RetagKind::FnEntry { - *kind = RetagKind::Default; - } - } - fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { if let StatementKind::StorageLive(local) | StatementKind::StorageDead(local) = statement.kind diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index b97901f075bc6..8489535fb1bc6 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -107,16 +107,16 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { let Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) = &*rvalue else { return }; *rvalue = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) { // Transform "Eq(a, true)" ==> "a" - (BinOp::Eq, _, Some(true)) => Rvalue::Use(a.clone()), + (BinOp::Eq, _, Some(true)) => Rvalue::Use(a.clone(), WithRetag::Yes), // Transform "Ne(a, false)" ==> "a" - (BinOp::Ne, _, Some(false)) => Rvalue::Use(a.clone()), + (BinOp::Ne, _, Some(false)) => Rvalue::Use(a.clone(), WithRetag::Yes), // Transform "Eq(true, b)" ==> "b" - (BinOp::Eq, Some(true), _) => Rvalue::Use(b.clone()), + (BinOp::Eq, Some(true), _) => Rvalue::Use(b.clone(), WithRetag::Yes), // Transform "Ne(false, b)" ==> "b" - (BinOp::Ne, Some(false), _) => Rvalue::Use(b.clone()), + (BinOp::Ne, Some(false), _) => Rvalue::Use(b.clone(), WithRetag::Yes), // Transform "Eq(false, b)" ==> "Not(b)" (BinOp::Eq, Some(false), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()), @@ -145,10 +145,24 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { && let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() && rvalue.ty(self.local_decls, self.tcx) == base.ty(self.local_decls, self.tcx).ty { - *rvalue = Rvalue::Use(Operand::Copy(Place { - local: base.local, - projection: self.tcx.mk_place_elems(base.projection), - })); + *rvalue = Rvalue::Use( + Operand::Copy(Place { + local: base.local, + projection: self.tcx.mk_place_elems(base.projection), + }), + // This might have been a two-phase borrow, which we should not upgrade + // to a full `&mut` reborrow. + // FIXME: Once Stacked Borrows is fully removed, we can use `Yes` here as + // Tree Borrows treats two-phase and full borrows the same. + if matches!( + rvalue, + Rvalue::Ref(_, BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow }, _) + ) { + WithRetag::No + } else { + WithRetag::Yes + }, + ); } } @@ -172,7 +186,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { let operand_ty = operand.ty(self.local_decls, self.tcx); if operand_ty == *cast_ty { - *rvalue = Rvalue::Use(operand.clone()); + *rvalue = Rvalue::Use(operand.clone(), WithRetag::Yes); } else if *kind == CastKind::Transmute // Transmuting an integer to another integer is just a signedness cast && let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) = @@ -236,9 +250,10 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { terminator.source_info, StatementKind::Assign(Box::new(( *destination, - Rvalue::Use(Operand::Copy( - arg_place.project_deeper(&[ProjectionElem::Deref], self.tcx), - )), + Rvalue::Use( + Operand::Copy(arg_place.project_deeper(&[ProjectionElem::Deref], self.tcx)), + WithRetag::Yes, + ), ))), )); terminator.kind = TerminatorKind::Goto { target: *destination_block }; @@ -294,7 +309,10 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { ); statements.push(Statement::new( source_info, - StatementKind::Assign(Box::new((*destination, Rvalue::Use(const_op)))), + StatementKind::Assign(Box::new(( + *destination, + Rvalue::Use(const_op, WithRetag::Yes), + ))), )); terminator.kind = TerminatorKind::Goto { target: *destination_block }; } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index a1e5d810afc02..6913eb0a4067a 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -395,7 +395,6 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { Some((Place::from(local), None)) } - StatementKind::Retag(..) | StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(..)) // copy_nonoverlapping takes pointers and mutated the pointed-to value. | StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(..)) @@ -504,7 +503,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { ) { let Some(lhs) = self.place(*lhs_place, None) else { return }; match rvalue { - Rvalue::Use(operand) => self.process_operand(lhs, operand, state), + Rvalue::Use(operand, _) => self.process_operand(lhs, operand, state), // Transfer the conditions on the copy rhs. Rvalue::Discriminant(rhs) => { let Some(rhs) = self.place(*rhs, Some(TrackElem::Discriminant)) else { return }; diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 8d0922db8f40e..b754a4621ca14 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -546,7 +546,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let val: Value<'_> = match *rvalue { ThreadLocalRef(_) => return None, - Use(ref operand) | WrapUnsafeBinder(ref operand, _) => { + Use(ref operand, _) | WrapUnsafeBinder(ref operand, _) => { self.eval_operand(operand)?.into() } diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 89bd91e7013da..36bcc06aef11b 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -49,7 +49,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { for (statement_index, st) in data.statements.iter_mut().enumerate() { let StatementKind::Assign(box ( lhs, - Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), + Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _), )) = &st.kind else { continue; @@ -81,7 +81,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { tmp_ty, ), }; - let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals))); + let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals)), WithRetag::No); let const_assign = StatementKind::Assign(Box::new((place, rval))); let discr_place = @@ -98,10 +98,14 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { let size_place = Place::from(patch.new_temp(tcx.types.usize, span)); let store_size = StatementKind::Assign(Box::new(( size_place, - Rvalue::Use(Operand::Copy(Place { - local: size_array_local, - projection: tcx.mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), - })), + Rvalue::Use( + Operand::Copy(Place { + local: size_array_local, + projection: tcx + .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), + }), + WithRetag::No, + ), ))); let dst = Place::from(patch.new_temp(Ty::new_mut_ptr(tcx, ty), span)); diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 094aae499c4b4..e0abf787e9838 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -22,7 +22,7 @@ use rustc_index::IndexVec; use rustc_middle::mir::{ AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, LocalDecl, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, START_BLOCK, - SourceInfo, Statement, StatementKind, TerminatorKind, + SourceInfo, Statement, StatementKind, TerminatorKind, WithRetag, }; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_middle::util::Providers; @@ -122,7 +122,6 @@ declare_passes! { mod abort_unwinding_calls : AbortUnwindingCalls; mod add_call_guards : AddCallGuards { AllCallEdges, CriticalCallEdges }; mod add_moves_for_packed_drops : AddMovesForPackedDrops; - mod add_retag : AddRetag; mod add_subtyping_projections : Subtyper; mod check_inline : CheckForceInline; mod check_call_recursion : CheckCallRecursion, CheckDropRecursion; @@ -275,7 +274,7 @@ fn remap_mir_for_const_eval_select<'tcx>( SourceInfo::outermost(fn_span), StatementKind::Assign(Box::new(( local.into(), - Rvalue::Use(tupled_args.node.clone()), + Rvalue::Use(tupled_args.node.clone(), WithRetag::Yes), ))), )); (Operand::Move, local.into()) @@ -647,9 +646,6 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // AddMovesForPackedDrops needs to run after drop // elaboration. &add_moves_for_packed_drops::AddMovesForPackedDrops, - // `AddRetag` needs to run after `ElaborateDrops` but before `ElaborateBoxDerefs`. - // Otherwise it should run fairly late, but before optimizations begin. - &add_retag::AddRetag, &erase_deref_temps::EraseDerefTemps, &elaborate_box_derefs::ElaborateBoxDerefs, &coroutine::StateTransform, diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index af246735b95a7..3fd0f8cf5b598 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -391,7 +391,7 @@ fn find_self_assignments<'tcx>( let Some(assign) = body.basic_blocks[*target].statements.first() else { continue; }; - let StatementKind::Assign(box (dest, Rvalue::Use(Operand::Move(temp)))) = + let StatementKind::Assign(box (dest, Rvalue::Use(Operand::Move(temp), _))) = assign.kind else { continue; @@ -709,8 +709,7 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { | StatementKind::SetDiscriminant { box place, .. } => { check_place(*place, AccessKind::Assign, statement.source_info, live); } - StatementKind::Retag(_, _) - | StatementKind::StorageLive(_) + StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Coverage(_) | StatementKind::Intrinsic(_) diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 8b2e68f156f9d..fe53d301c5574 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -35,7 +35,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.source_info, StatementKind::Assign(Box::new(( *destination, - Rvalue::Use(Operand::RuntimeChecks(op)), + Rvalue::Use(Operand::RuntimeChecks(op), WithRetag::Yes), ))), )); terminator.kind = TerminatorKind::Goto { target }; @@ -46,11 +46,14 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.source_info, StatementKind::Assign(Box::new(( *destination, - Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span: terminator.source_info.span, - user_ty: None, - const_: Const::zero_sized(tcx.types.unit), - }))), + Rvalue::Use( + Operand::Constant(Box::new(ConstOperand { + span: terminator.source_info.span, + user_ty: None, + const_: Const::zero_sized(tcx.types.unit), + })), + WithRetag::Yes, + ), ))), )); terminator.kind = TerminatorKind::Goto { target }; @@ -165,7 +168,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.source_info, StatementKind::Assign(Box::new(( *destination, - Rvalue::Use(Operand::Copy(derefed_place)), + Rvalue::Use(Operand::Copy(derefed_place), WithRetag::Yes), ))), )); terminator.kind = match *target { diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 05d085fafe937..a8b7f94936020 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -72,7 +72,9 @@ impl<'tcx, 'a> SimplifyMatch<'tcx, 'a> { }) { Some(StatementKind::Assign(Box::new(( dest, - Rvalue::Use(Operand::Constant(Box::new(first_const.clone()))), + // We didn't remember the `WithRetag` of the original assignments, so in case + // one of them had "no", we also have to use "no" here. + Rvalue::Use(Operand::Constant(Box::new(first_const.clone())), WithRetag::No), )))) } else { None @@ -202,7 +204,7 @@ impl<'tcx, 'a> SimplifyMatch<'tcx, 'a> { }) { let operand = Operand::Copy(Place::from(self.discr_local())); let rval = if first_const.ty() == self.discr_ty { - Rvalue::Use(operand) + Rvalue::Use(operand, WithRetag::No) } else { Rvalue::Cast(CastKind::IntToInt, operand, first_const.ty()) }; @@ -262,7 +264,7 @@ impl<'tcx, 'a> SimplifyMatch<'tcx, 'a> { for &(case, rvalue) in rvals.iter() { match rvalue { // Check if `_3 = const Foo::B` can be transformed to `_3 = copy *_1`. - Rvalue::Use(Operand::Constant(box constant)) + Rvalue::Use(Operand::Constant(box constant), _) if let Const::Val(const_, ty) = constant.const_ => { let (ecx, op) = mk_eval_cx_for_const_val( @@ -280,7 +282,7 @@ impl<'tcx, 'a> SimplifyMatch<'tcx, 'a> { return None; } } - Rvalue::Use(Operand::Copy(src_place)) if *src_place == copy_src_place => {} + Rvalue::Use(Operand::Copy(src_place), _) if *src_place == copy_src_place => {} // Check if `_3 = Foo::B` can be transformed to `_3 = copy *_1`. Rvalue::Aggregate(box AggregateKind::Adt(_, variant_index, _, _, None), fields) if fields.is_empty() @@ -290,7 +292,12 @@ impl<'tcx, 'a> SimplifyMatch<'tcx, 'a> { _ => return None, } } - Some(StatementKind::Assign(Box::new((dest, Rvalue::Use(Operand::Copy(copy_src_place)))))) + // We didn't remember the `WithRetag` of the original assignments, so in case + // one of them had "no", we also have to use "no" here. + Some(StatementKind::Assign(Box::new(( + dest, + Rvalue::Use(Operand::Copy(copy_src_place), WithRetag::No), + )))) } /// Returns a new statement if we can use the statement replace all statements. @@ -427,7 +434,7 @@ fn simplify_match<'tcx>( let mut patch = simplify_match.patch; if let Some(discr_local) = simplify_match.discr_local { patch.add_statement(parent_end, StatementKind::StorageLive(discr_local)); - patch.add_assign(parent_end, Place::from(discr_local), Rvalue::Use(discr)); + patch.add_assign(parent_end, Place::from(discr_local), Rvalue::Use(discr, WithRetag::No)); } for new_stmt in new_stmts { patch.add_statement(parent_end, new_stmt); @@ -501,8 +508,9 @@ fn candidate_const<'tcx, 'a>( rvals: &'a [(u128, &'a Rvalue<'tcx>)], otherwise: Option<&'a Rvalue<'tcx>>, ) -> Option<(Vec<(u128, &'a ConstOperand<'tcx>)>, Option<&'a ConstOperand<'tcx>>)> { + // We ignore the retag mode here, which means the `Use` we insert later must be without retag. let otherwise = if let Some(otherwise) = otherwise { - let Rvalue::Use(Operand::Constant(box const_)) = otherwise else { + let Rvalue::Use(Operand::Constant(box const_), _) = otherwise else { return None; }; Some(const_) @@ -512,7 +520,7 @@ fn candidate_const<'tcx, 'a>( let consts = rvals .into_iter() .map(|&(case, rval)| { - let Rvalue::Use(Operand::Constant(box const_)) = rval else { return None }; + let Rvalue::Use(Operand::Constant(box const_), _) = rval else { return None }; Some((case, const_)) }) .try_collect()?; diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index a47b3ce64ed23..041ff45c11d7e 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -310,7 +310,7 @@ impl<'tcx> Validator<'_, 'tcx> { if let Some(local) = place_base.as_local() && let TempState::Defined { location, .. } = self.temps[local] && let Left(def_stmt) = self.body.stmt_at(location) - && let Some((_, Rvalue::Use(Operand::Constant(c)))) = def_stmt.kind.as_assign() + && let Some((_, Rvalue::Use(Operand::Constant(c), _))) = def_stmt.kind.as_assign() && let Some(did) = c.check_static_ptr(self.tcx) // Evaluating a promoted may not read statics except if it got // promoted from a static (this is a CTFE check). So we @@ -327,7 +327,7 @@ impl<'tcx> Validator<'_, 'tcx> { // Only accept if we can predict the index and are indexing an array. if let TempState::Defined { location: loc, .. } = self.temps[local] && let Left(statement) = self.body.stmt_at(loc) - && let Some((_, Rvalue::Use(Operand::Constant(c)))) = statement.kind.as_assign() + && let Some((_, Rvalue::Use(Operand::Constant(c), _))) = statement.kind.as_assign() && self.should_evaluate_for_promotion_checks(c.const_) && let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.typing_env) // Determine the type of the thing we are indexing. @@ -424,7 +424,12 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> { match rvalue { - Rvalue::Use(operand) + Rvalue::Use(_operand, WithRetag::No) => { + // This shouldn't actually happen, but just to be safe: we'll later add the promoted + // with retagging, so don't promote anything that didn't already have retagging. + return Err(Unpromotable); + } + Rvalue::Use(operand, _) | Rvalue::Repeat(operand, _) | Rvalue::WrapUnsafeBinder(operand, _) => { self.validate_operand(operand)?; @@ -793,11 +798,14 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { if self.keep_original { rhs.clone() } else { - let unit = Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span: statement.source_info.span, - user_ty: None, - const_: Const::zero_sized(self.tcx.types.unit), - }))); + let unit = Rvalue::Use( + Operand::Constant(Box::new(ConstOperand { + span: statement.source_info.span, + user_ty: None, + const_: Const::zero_sized(self.tcx.types.unit), + })), + WithRetag::Yes, + ); mem::replace(rhs, unit) }, statement.source_info, @@ -918,7 +926,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { statement.source_info, StatementKind::Assign(Box::new(( Place::from(promoted_ref), - Rvalue::Use(Operand::Constant(Box::new(promoted_operand))), + // We can retag here because we wouldn't promote non-retagged values (they get + // rejected in validate_rvalue). + Rvalue::Use(Operand::Constant(Box::new(promoted_operand)), WithRetag::Yes), ))), ); self.extra_statements.push((loc, promoted_ref_statement)); diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 0c5d8913a8070..2643c53eac1ac 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -247,7 +247,7 @@ fn compute_replacement<'tcx>( // This is a copy, just use the value we have in store for the previous one. // As we are visiting in `assignment_order`, i.e. reverse postorder, `rhs` should // have been visited before. - Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) => { + Rvalue::Use(Operand::Copy(place) | Operand::Move(place), _) => { if let Some(rhs) = place.as_local() && ssa.is_ssa(rhs) { diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index f7105f62e4beb..e8058422d3c54 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -102,7 +102,7 @@ impl RemoveNoopLandingPads { // These are all noops in a landing pad } - StatementKind::Assign(box (place, Rvalue::Use(_) | Rvalue::Discriminant(_))) => { + StatementKind::Assign(box (place, Rvalue::Use(..) | Rvalue::Discriminant(_))) => { if place.as_local().is_some() { // Writing to a local (e.g., a drop flag) does not // turn a landing pad to a non-nop @@ -113,8 +113,7 @@ impl RemoveNoopLandingPads { StatementKind::Assign { .. } | StatementKind::SetDiscriminant { .. } - | StatementKind::Intrinsic(..) - | StatementKind::Retag { .. } => { + | StatementKind::Intrinsic(..) => { return false; } } diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index bebd8fab74565..7d837993ed3a6 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -124,7 +124,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { } StatementKind::SetDiscriminant { box place, variant_index: _ } | StatementKind::AscribeUserType(box (place, _), _) - | StatementKind::Retag(_, box place) | StatementKind::PlaceMention(box place) | StatementKind::FakeRead(box (_, place)) => Some(place), StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 4fd0629befecf..50a691f36e0d7 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -295,40 +295,6 @@ fn local_decls_for_sig<'tcx>( .collect() } -fn dropee_emit_retag<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - mut dropee_ptr: Place<'tcx>, - span: Span, -) -> Place<'tcx> { - if tcx.sess.opts.unstable_opts.mir_emit_retag { - let source_info = SourceInfo::outermost(span); - // We want to treat the function argument as if it was passed by `&mut`. As such, we - // generate - // ``` - // temp = &mut *arg; - // Retag(temp, FnEntry) - // ``` - // It's important that we do this first, before anything that depends on `dropee_ptr` - // has been put into the body. - let reborrow = Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { kind: MutBorrowKind::Default }, - tcx.mk_place_deref(dropee_ptr), - ); - let ref_ty = reborrow.ty(body.local_decls(), tcx); - dropee_ptr = body.local_decls.push(LocalDecl::new(ref_ty, span)).into(); - let new_statements = [ - StatementKind::Assign(Box::new((dropee_ptr, reborrow))), - StatementKind::Retag(RetagKind::FnEntry, Box::new(dropee_ptr)), - ]; - for s in new_statements { - body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, s)); - } - } - dropee_ptr -} - fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) -> Body<'tcx> { debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty); @@ -359,7 +325,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) // The first argument (index 0), but add 1 for the return value. let dropee_ptr = Place::from(Local::new(1 + 0)); - let dropee_ptr = dropee_emit_retag(tcx, &mut body, dropee_ptr, span); if ty.is_some() { let patch = { @@ -626,7 +591,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { let rcvr = self.tcx.mk_place_deref(Place::from(Local::new(1 + 0))); let ret_statement = self.make_statement(StatementKind::Assign(Box::new(( Place::return_place(), - Rvalue::Use(Operand::Copy(rcvr)), + Rvalue::Use(Operand::Copy(rcvr), WithRetag::Yes), )))); self.block(vec![ret_statement], TerminatorKind::Return, false); } 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 a0f1260cd986d..0f96fe481d737 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -124,13 +124,12 @@ pub(super) fn build_async_drop_shim<'tcx>( return body; } - let mut dropee_ptr = Place::from(body.local_decls.push(LocalDecl::new(drop_ptr_ty, span))); + let dropee_ptr = Place::from(body.local_decls.push(LocalDecl::new(drop_ptr_ty, span))); let st_kind = StatementKind::Assign(Box::new(( dropee_ptr, - Rvalue::Use(Operand::Move(coroutine_layout_dropee)), + Rvalue::Use(Operand::Move(coroutine_layout_dropee), WithRetag::Yes), ))); body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, st_kind)); - dropee_ptr = dropee_emit_retag(tcx, &mut body, dropee_ptr, span); let dropline = body.basic_blocks.last_index(); @@ -240,7 +239,7 @@ fn build_adrop_for_coroutine_shim<'tcx>( source_info, StatementKind::Assign(Box::new(( Place::from(proxy_ref_local), - Rvalue::Use(Operand::Copy(proxy_ref_place)), + Rvalue::Use(Operand::Copy(proxy_ref_place), WithRetag::Yes), ))), ), ); @@ -261,7 +260,7 @@ fn build_adrop_for_coroutine_shim<'tcx>( source_info, StatementKind::Assign(Box::new(( Place::from(cor_ptr_local), - Rvalue::Use(Operand::Copy(impl_ptr_place)), + Rvalue::Use(Operand::Copy(impl_ptr_place), WithRetag::Yes), ))), ), ); @@ -334,7 +333,7 @@ fn build_adrop_for_adrop_shim<'tcx>( source_info, StatementKind::Assign(Box::new(( Place::from(proxy_ref_local), - Rvalue::Use(Operand::Copy(proxy_ref_place)), + Rvalue::Use(Operand::Copy(proxy_ref_place), WithRetag::Yes), ))), )); @@ -350,7 +349,7 @@ fn build_adrop_for_adrop_shim<'tcx>( source_info, StatementKind::Assign(Box::new(( Place::from(cor_ptr_local), - Rvalue::Use(Operand::Copy(impl_ptr_place)), + Rvalue::Use(Operand::Copy(impl_ptr_place), WithRetag::Yes), ))), )); } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index da31600e8324c..80f16304f56d5 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -568,7 +568,6 @@ impl<'tcx> Visitor<'tcx> for UsedLocals { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { StatementKind::Intrinsic(..) - | StatementKind::Retag(..) | StatementKind::Coverage(..) | StatementKind::FakeRead(..) | StatementKind::PlaceMention(..) diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 70ae3433353b2..3fb77961c15fe 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -63,7 +63,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { continue 'blocks; } } else if let StatementKind::Assign(box (lhs, ref rvalue)) = stmt.kind - && let Rvalue::Use(Operand::Constant(c)) = rvalue + && let Rvalue::Use(Operand::Constant(c), _) = rvalue { pre_place_const = Some((lhs, c)); } diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 91e040d5cbc89..78f4457a4c689 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -59,7 +59,7 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { }; let (place, rvalue) = *place_and_rvalue; assert_eq!(place.as_local(), Some(local)); - let Rvalue::Use(operand) = rvalue else { bug!("No longer a use?") }; + let Rvalue::Use(operand, _) = rvalue else { bug!("No longer a use?") }; let mut replacer = LocalReplacer { tcx, local, operand: Some(operand) }; @@ -114,7 +114,7 @@ struct SingleUseConstsFinder { impl<'tcx> Visitor<'tcx> for SingleUseConstsFinder { fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { if let Some(local) = place.as_local() - && let Rvalue::Use(operand) = rvalue + && let Rvalue::Use(operand, _) = rvalue && let Operand::Constant(_) = operand { let locations = &mut self.locations[local]; diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index a6ed66c8427b3..0032081fb39de 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -348,7 +348,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { // Replace mentions of SROA'd locals that appear in the operand. self.visit_operand(&mut operand, location); - let rvalue = Rvalue::Use(operand); + let rvalue = Rvalue::Use(operand, WithRetag::Yes); self.patch.add_statement( location, StatementKind::Assign(Box::new((new_local.into(), rvalue))), @@ -368,13 +368,13 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { // ... // ``` // ConstProp will pick up the pieces and replace them by actual constants. - StatementKind::Assign(box (place, Rvalue::Use(Operand::Constant(_)))) => { + StatementKind::Assign(box (place, Rvalue::Use(Operand::Constant(_), retag))) => { if let Some(final_locals) = self.replacements.place_fragments(place) { // Put the deaggregated statements *after* the original one. let location = location.successor_within_block(); for (field, ty, new_local) in final_locals { let rplace = self.tcx.mk_place_field(place, field, ty); - let rvalue = Rvalue::Use(Operand::Move(rplace)); + let rvalue = Rvalue::Use(Operand::Move(rplace), retag); self.patch.add_statement( location, StatementKind::Assign(Box::new((new_local.into(), rvalue))), @@ -394,7 +394,7 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { // ``` StatementKind::Assign(box ( lhs, - Rvalue::Use(ref op @ (Operand::Copy(rplace) | Operand::Move(rplace))), + Rvalue::Use(ref op @ (Operand::Copy(rplace) | Operand::Move(rplace)), retag), )) => { let copy = match *op { Operand::Copy(_) => true, @@ -411,9 +411,9 @@ impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> { .unwrap_or(rplace); debug!(?rplace); let rvalue = if copy { - Rvalue::Use(Operand::Copy(rplace)) + Rvalue::Use(Operand::Copy(rplace), retag) } else { - Rvalue::Use(Operand::Move(rplace)) + Rvalue::Use(Operand::Move(rplace), retag) }; self.patch.add_statement( location, diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 4f9f2e5fabb93..2465b6c341afc 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -297,7 +297,7 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) { let mut copies = IndexVec::from_fn_n(|l| l, body.local_decls.len()); for (local, rvalue, _) in ssa.assignments(body) { - let Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) = rvalue else { + let Rvalue::Use(Operand::Copy(place) | Operand::Move(place), _) = rvalue else { continue; }; diff --git a/compiler/rustc_mir_transform/src/trivial_const.rs b/compiler/rustc_mir_transform/src/trivial_const.rs index 529c8c65acfc0..027e9ec631666 100644 --- a/compiler/rustc_mir_transform/src/trivial_const.rs +++ b/compiler/rustc_mir_transform/src/trivial_const.rs @@ -86,7 +86,7 @@ where return None; } - let Rvalue::Use(Operand::Constant(c)) = rvalue else { + let Rvalue::Use(Operand::Constant(c), _) = rvalue else { return None; }; match c.const_ { diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 656b74e15f727..c6835020b537a 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -319,14 +319,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { self.fail(location, "`SetDiscriminant`is not allowed until deaggregation"); } } - StatementKind::Retag(kind, _) => { - // FIXME(JakobDegen) The validator should check that `self.body.phase < - // DropsLowered`. However, this causes ICEs with generation of drop shims, which - // seem to fail to set their `MirPhase` correctly. - if matches!(kind, RetagKind::TwoPhase) { - self.fail(location, format!("explicit `{kind:?}` is forbidden")); - } - } StatementKind::Coverage(kind) => { if self.body.phase >= MirPhase::Analysis(AnalysisPhase::PostCleanup) && let CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. } = kind @@ -1016,7 +1008,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; } match rvalue { - Rvalue::Use(_) => {} + Rvalue::Use(_, _) => {} Rvalue::CopyForDeref(_) => { if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail(location, "`CopyForDeref` should have been removed in runtime MIR"); @@ -1557,14 +1549,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - StatementKind::Retag(kind, _) => { - // FIXME(JakobDegen) The validator should check that `self.body.phase < - // DropsLowered`. However, this causes ICEs with generation of drop shims, which - // seem to fail to set their `MirPhase` correctly. - if matches!(kind, RetagKind::TwoPhase) { - self.fail(location, format!("explicit `{kind:?}` is forbidden")); - } - } StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Coverage(_) diff --git a/compiler/rustc_public/src/mir/body.rs b/compiler/rustc_public/src/mir/body.rs index 51757c5827221..6aeed20b1f481 100644 --- a/compiler/rustc_public/src/mir/body.rs +++ b/compiler/rustc_public/src/mir/body.rs @@ -439,11 +439,9 @@ pub enum FakeReadCause { /// Describes what kind of retag is to be performed #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)] -pub enum RetagKind { - FnEntry, - TwoPhase, - Raw, - Default, +pub enum WithRetag { + Yes, + No, } #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)] @@ -480,7 +478,6 @@ pub enum StatementKind { SetDiscriminant { place: Place, variant_index: VariantIdx }, StorageLive(Local), StorageDead(Local), - Retag(RetagKind, Place), PlaceMention(Place), AscribeUserType { place: Place, projections: UserTypeProjection, variance: Variance }, Coverage(Coverage), @@ -587,14 +584,14 @@ pub enum Rvalue { /// return a value with the same type as their operand. UnaryOp(UnOp, Operand), - /// Yields the operand unchanged - Use(Operand), + /// Yields the operand unchanged, except for possibly a retag. + Use(Operand, WithRetag), } impl Rvalue { pub fn ty(&self, locals: &[LocalDecl]) -> Result { match self { - Rvalue::Use(operand) => operand.ty(locals), + Rvalue::Use(operand, _) => operand.ty(locals), Rvalue::Repeat(operand, count) => { Ok(Ty::new_array_with_const_len(operand.ty(locals)?, count.clone())) } diff --git a/compiler/rustc_public/src/mir/pretty.rs b/compiler/rustc_public/src/mir/pretty.rs index bf2655e9a789c..dac39c636e31e 100644 --- a/compiler/rustc_public/src/mir/pretty.rs +++ b/compiler/rustc_public/src/mir/pretty.rs @@ -108,7 +108,6 @@ fn pretty_statement(writer: &mut W, statement: &StatementKind) -> io:: StatementKind::StorageDead(local) => { writeln!(writer, "{INDENT}StorageDead(_{local});") } - StatementKind::Retag(kind, place) => writeln!(writer, "Retag({kind:?}, {place:?});"), StatementKind::PlaceMention(place) => { writeln!(writer, "{INDENT}PlaceMention({place:?};") } @@ -389,7 +388,12 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { Rvalue::UnaryOp(un, op) => { write!(writer, "{:?}({})", un, pretty_operand(op)) } - Rvalue::Use(op) => write!(writer, "{}", pretty_operand(op)), + Rvalue::Use(op, retag) => write!( + writer, + "{}{}", + if matches!(retag, crate::mir::WithRetag::No) { "no_retag " } else { "" }, + pretty_operand(op) + ), } } diff --git a/compiler/rustc_public/src/mir/visit.rs b/compiler/rustc_public/src/mir/visit.rs index e1d9cf31036e2..cf6540cc6c772 100644 --- a/compiler/rustc_public/src/mir/visit.rs +++ b/compiler/rustc_public/src/mir/visit.rs @@ -169,8 +169,7 @@ macro_rules! make_mir_visitor { StatementKind::FakeRead(_, place) | StatementKind::PlaceMention(place) => { self.visit_place(place, PlaceContext::NON_MUTATING, location); } - StatementKind::SetDiscriminant { place, .. } - | StatementKind::Retag(_, place) => { + StatementKind::SetDiscriminant { place, .. } => { self.visit_place(place, PlaceContext::MUTATING, location); } StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { @@ -278,7 +277,7 @@ macro_rules! make_mir_visitor { self.visit_ty_const(constant, location); } Rvalue::ThreadLocalRef(_) => {} - Rvalue::UnaryOp(_, op) | Rvalue::Use(op) => { + Rvalue::UnaryOp(_, op) | Rvalue::Use(op, _) => { self.visit_operand(op, location); } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/mir.rs b/compiler/rustc_public/src/unstable/convert/stable/mir.rs index d25751c81f3f5..3102ce0e3e60a 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/mir.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/mir.rs @@ -157,9 +157,6 @@ impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> { mir::StatementKind::StorageDead(place) => { crate::mir::StatementKind::StorageDead(place.stable(tables, cx)) } - mir::StatementKind::Retag(retag, place) => { - crate::mir::StatementKind::Retag(retag.stable(tables, cx), place.stable(tables, cx)) - } mir::StatementKind::PlaceMention(place) => { crate::mir::StatementKind::PlaceMention(place.stable(tables, cx)) } @@ -195,7 +192,9 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { ) -> Self::T { use rustc_middle::mir::Rvalue::*; match self { - Use(op) => crate::mir::Rvalue::Use(op.stable(tables, cx)), + Use(op, retag) => { + crate::mir::Rvalue::Use(op.stable(tables, cx), retag.stable(tables, cx)) + } Repeat(op, len) => { let len = len.stable(tables, cx); crate::mir::Rvalue::Repeat(op.stable(tables, cx), len) @@ -462,15 +461,13 @@ impl<'tcx> Stable<'tcx> for mir::Local { } } -impl<'tcx> Stable<'tcx> for mir::RetagKind { - type T = crate::mir::RetagKind; +impl<'tcx> Stable<'tcx> for mir::WithRetag { + type T = crate::mir::WithRetag; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { - use rustc_middle::mir::RetagKind; + use rustc_middle::mir::WithRetag; match self { - RetagKind::FnEntry => crate::mir::RetagKind::FnEntry, - RetagKind::TwoPhase => crate::mir::RetagKind::TwoPhase, - RetagKind::Raw => crate::mir::RetagKind::Raw, - RetagKind::Default => crate::mir::RetagKind::Default, + WithRetag::Yes => crate::mir::WithRetag::Yes, + WithRetag::No => crate::mir::WithRetag::No, } } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7abaae1c17606..ddbae12fa78ff 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2476,9 +2476,6 @@ options! { "align all functions to at least this many bytes. Must be a power of 2"), min_recursion_limit: Option = (None, parse_opt_number, [TRACKED], "set a minimum recursion limit (final limit = max(this, recursion_limit_from_crate))"), - mir_emit_retag: bool = (false, parse_bool, [TRACKED], - "emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \ - (default: no)"), mir_enable_passes: Vec<(String, bool)> = (Vec::new(), parse_list_with_polarity, [TRACKED], "use like `-Zmir-enable-passes=+DestinationPropagation,-InstSimplify`. Forces the \ specified passes to be enabled, overriding all other checks. In particular, this will \ diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d3e25c2262f0a..767ec202f1eaa 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1280,7 +1280,6 @@ symbols! { mir_move, mir_offset, mir_ptr_metadata, - mir_retag, mir_return, mir_return_to, mir_set_discriminant, diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 5008794bcb191..264809b8537e9 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -589,6 +589,11 @@ fn fn_abi_new_uncached<'tcx>( extra_args }; + // For some functions we treat their first argument as-if it was a mutable reference + // even if it is a raw pointer. This is a terrible hack since it becomes effectively + // part of the MIR semantics that every MIR consumer needs to be aware of. + // Do not add more functions here! Instead, put the actually intended type in the signature. + // FIXME(#154274): remove this hack. let is_drop_in_place = determined_fn_def_id.is_some_and(|def_id| { tcx.is_lang_item(def_id, LangItem::DropInPlace) || tcx.is_lang_item(def_id, LangItem::AsyncDropInPlace) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index ae16a8401552d..3e177f7767c9e 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1407,9 +1407,11 @@ impl Box { pub fn into_raw(b: Self) -> *mut T { // Avoid `into_raw_with_allocator` as that interacts poorly with Miri's Stacked Borrows. let mut b = mem::ManuallyDrop::new(b); - // We go through the built-in deref for `Box`, which is crucial for Miri to recognize this - // operation for it's alias tracking. - &raw mut **b + // We go through an intermediate raw pointer, which is crucial for Miri to recognize this + // operation for it's alias tracking. It would be wrong for `into_raw_with_allocator` to + // do the same as that would induce uniqueness assumptions that we only want with + // the default allocator. + &mut **b } /// Consumes the `Box`, returning a wrapped `NonNull` pointer. diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 7659e0042b379..183db46c6405e 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -229,7 +229,7 @@ //! //! #### Statements //! - Assign statements work via normal Rust assignment. -//! - [`Retag`], [`StorageLive`], [`StorageDead`] statements have an associated function. +//! - [`StorageLive`], [`StorageDead`] statements have an associated function. //! //! #### Rvalues //! @@ -407,7 +407,6 @@ define!( "mir_ptr_metadata", fn PtrMetadata(place: *const P) ->

::Metadata ); -define!("mir_retag", fn Retag(place: T)); define!("mir_move", fn Move(place: T) -> T); define!("mir_static", fn Static(s: T) -> &'static T); define!("mir_static_mut", fn StaticMut(s: T) -> *mut T); diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index d2d9e1642d441..bfb704dd21719 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -293,7 +293,7 @@ fn find_stmt_assigns_to<'tcx>( })?; match (by_ref, rvalue) { - (true, mir::Rvalue::Ref(_, _, place)) | (false, mir::Rvalue::Use(mir::Operand::Copy(place))) => { + (true, mir::Rvalue::Ref(_, _, place)) | (false, mir::Rvalue::Use(mir::Operand::Copy(place), _)) => { Some(base_local_and_movability(cx, mir, *place)) }, (false, mir::Rvalue::Ref(_, _, place)) => { diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 0ead5944b4b33..cbd55ce9b4351 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -155,7 +155,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { }; match rvalue { - Use(op) | Repeat(op, _) | Cast(_, op, _) | UnaryOp(_, op) => visit_op(op), + Use(op, _) | Repeat(op, _) | Cast(_, op, _) | UnaryOp(_, op) => visit_op(op), Aggregate(_, ops) => ops.iter().for_each(visit_op), BinaryOp(_, box (lhs, rhs)) => { visit_op(lhs); diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs index fee22c436b0fb..742eedfa225bc 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs @@ -46,7 +46,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'_, 'tcx> { mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, borrowed) | // _2: &mut _; // _3 = move _2 - mir::Rvalue::Use(mir::Operand::Move(borrowed)) | + mir::Rvalue::Use(mir::Operand::Move(borrowed), _) | // _3 = move _2 as &mut _; mir::Rvalue::Cast(_, mir::Operand::Move(borrowed), _) => { diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 1484b8c8bcc45..0422ec320e65a 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -131,7 +131,7 @@ fn check_rvalue<'tcx>( }, Rvalue::CopyForDeref(place) => check_place(cx, *place, span, body, msrv), Rvalue::Repeat(operand, _) - | Rvalue::Use(operand) + | Rvalue::Use(operand, _) | Rvalue::WrapUnsafeBinder(operand, _) | Rvalue::Cast( CastKind::PointerWithExposedProvenance @@ -241,7 +241,6 @@ fn check_statement<'tcx>( // These are all NOPs StatementKind::StorageLive(_) | StatementKind::StorageDead(_) - | StatementKind::Retag { .. } | StatementKind::AscribeUserType(..) | StatementKind::PlaceMention(..) | StatementKind::Coverage(..) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index f51cd96486b4f..00b7762778ad4 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -432,14 +432,13 @@ to Miri failing to detect cases of undefined behavior in a program. be detected. Using this flag is **unsound** (but the affected soundness rules are experimental). Later flags take precedence: borrow tracking can be reactivated by `-Zmiri-tree-borrows`. -* `-Zmiri-disable-validation` disables enforcing validity invariants, which are - enforced by default. This only disables these checks for typed copies; using - invalid values in any other operation will still cause an error. This is mostly useful - to focus on other failures (such as out-of-bounds accesses) first. Setting this - flag means Miri can miss bugs in your program. However, this can also help to - make Miri run faster. Using this flag is **unsound**. -* `-Zmiri-disable-weak-memory-emulation` disables the emulation of some C++11 weak - memory effects. +* `-Zmiri-disable-validation` disables enforcing validity invariants, which are enforced by default. + This only disables these checks for typed copies; using invalid values in any other operation will + still cause an error. This also disables the aliasing model (Stacked/Tree Borrows). This is mostly + useful to focus on other failures (such as out-of-bounds accesses) first. Setting this flag means + Miri can miss bugs in your program. However, this can also help to make Miri run faster. Using + this flag is **unsound**. +* `-Zmiri-disable-weak-memory-emulation` disables the emulation of some C++11 weak memory effects. * `-Zmiri-fixed-schedule` disables preemption (like `-Zmiri-preemption-rate=0.0`) and furthermore disables the randomization of the next thread to be picked, instead fixing a round-robin schedule. Note however that other aspects of Miri's concurrency behavior are still randomize; use @@ -520,17 +519,6 @@ to Miri failing to detect cases of undefined behavior in a program. [function ABI]: https://doc.rust-lang.org/reference/items/functions.html#extern-function-qualifier -Some native rustc `-Z` flags are also very relevant for Miri: - -* `-Zmir-opt-level` controls how many MIR optimizations are performed. Miri - overrides the default to be `0`; be advised that using any higher level can - make Miri miss bugs in your program because they got optimized away. -* `-Zalways-encode-mir` makes rustc dump MIR even for completely monomorphic - functions. This is needed so that Miri can execute such functions, so Miri - sets this flag per default. -* `-Zmir-emit-retag` controls whether `Retag` statements are emitted. Miri - enables this per default because it is needed for [Stacked Borrows] and [Tree Borrows]. - Moreover, Miri recognizes some environment variables: * `MIRIFLAGS` defines extra flags to be passed to Miri. diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index e73c870508bd0..024b8c4219354 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -714,6 +714,11 @@ fn main() -> ExitCode { } } + // Disabling validation also disables aliasing checks (as retags are done during validation). + if miri_config.validation == ValidationMode::No { + miri_config.borrow_tracker = None; + } + // Native calls and strict provenance are not compatible. if !miri_config.native_lib.is_empty() && miri_config.provenance_mode == ProvenanceMode::Strict { fatal_error!("strict provenance is not compatible with calling native functions"); diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 9aa0ce48e09a0..2689c6f69dec0 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -1,10 +1,10 @@ use std::cell::RefCell; -use std::fmt; use std::num::NonZero; +use std::{fmt, mem}; use rustc_abi::Size; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_middle::mir::RetagKind; +use rustc_middle::ty::Ty; use smallvec::SmallVec; use crate::*; @@ -103,6 +103,8 @@ impl VisitProvenance for FrameState { pub struct GlobalStateInner { /// Borrow tracker method currently in use. borrow_tracker_method: BorrowTrackerMethod, + /// The currently active retag mode. + retag_mode: RetagMode, /// Next unused pointer ID (tag). next_ptr_tag: BorTag, /// Table storing the "root" tag for each allocation. @@ -157,6 +159,7 @@ impl GlobalStateInner { ) -> Self { GlobalStateInner { borrow_tracker_method, + retag_mode: RetagMode::Default, next_ptr_tag: BorTag::one(), root_ptr_tags: FxHashMap::default(), protected_tags: FxHashMap::default(), @@ -265,36 +268,43 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn retag_ptr_value( &mut self, - kind: RetagKind, val: &ImmTy<'tcx>, - ) -> InterpResult<'tcx, ImmTy<'tcx>> { - let _trace = enter_trace_span!(borrow_tracker::retag_ptr_value, ?kind, ?val.layout); + ty: Ty<'tcx>, + ) -> InterpResult<'tcx, Option>> { + let _trace = enter_trace_span!(borrow_tracker::retag_ptr_value, ?ty); let this = self.eval_context_mut(); - let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; + let state = this.machine.borrow_tracker.as_mut().unwrap().get_mut(); + let method = state.borrow_tracker_method; + let retag_mode = state.retag_mode; + info!("retag_ptr_value: type={ty}, mode={retag_mode:?}, val={:?}", **val); match method { - BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(kind, val), - BorrowTrackerMethod::TreeBorrows { .. } => this.tb_retag_ptr_value(kind, val), + BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(val, ty, retag_mode), + BorrowTrackerMethod::TreeBorrows { .. } => this.tb_retag_ptr_value(val, ty, retag_mode), } } - fn retag_place_contents( + fn with_retag_mode( &mut self, - kind: RetagKind, - place: &PlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - let _trace = enter_trace_span!(borrow_tracker::retag_place_contents, ?kind, ?place); - let this = self.eval_context_mut(); - let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; - match method { - BorrowTrackerMethod::StackedBorrows => this.sb_retag_place_contents(kind, place), - BorrowTrackerMethod::TreeBorrows { .. } => this.tb_retag_place_contents(kind, place), - } + mode: RetagMode, + f: impl FnOnce(&mut Self) -> InterpResult<'tcx, T>, + ) -> InterpResult<'tcx, T> { + // Set up new mode, remembering the old mode. + let state = self.eval_context_mut().machine.borrow_tracker.as_mut().unwrap().get_mut(); + let old_mode = mem::replace(&mut state.retag_mode, mode); + + let ret = f(self); + + // Restore old mode. + let state = self.eval_context_mut().machine.borrow_tracker.as_mut().unwrap().get_mut(); + state.retag_mode = old_mode; + + ret } fn protect_place(&mut self, place: &MPlaceTy<'tcx>) -> InterpResult<'tcx, MPlaceTy<'tcx>> { let _trace = enter_trace_span!(borrow_tracker::protect_place, ?place); let this = self.eval_context_mut(); - let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; + let method = this.machine.borrow_tracker.as_mut().unwrap().get_mut().borrow_tracker_method; match method { BorrowTrackerMethod::StackedBorrows => this.sb_protect_place(place), BorrowTrackerMethod::TreeBorrows { .. } => this.tb_protect_place(place), @@ -319,7 +329,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { name: &str, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; + let method = this.machine.borrow_tracker.as_mut().unwrap().get_mut().borrow_tracker_method; match method { BorrowTrackerMethod::StackedBorrows => { this.tcx.tcx.dcx().warn("Stacked Borrows does not support named pointers; `miri_pointer_name` is a no-op"); @@ -332,11 +342,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn print_borrow_state(&mut self, alloc_id: AllocId, show_unnamed: bool) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let Some(borrow_tracker) = &this.machine.borrow_tracker else { + let Some(borrow_tracker) = &mut this.machine.borrow_tracker else { eprintln!("attempted to print borrow state, but no borrow state is being tracked"); return interp_ok(()); }; - let method = borrow_tracker.borrow().borrow_tracker_method; + let method = borrow_tracker.get_mut().borrow_tracker_method; match method { BorrowTrackerMethod::StackedBorrows => this.print_stacks(alloc_id), BorrowTrackerMethod::TreeBorrows { .. } => this.print_tree(alloc_id, show_unnamed), diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 6b7c0adc8afb0..8f6a508e605a0 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -191,7 +191,6 @@ struct RetagOp { #[derive(Debug, Clone, Copy, PartialEq)] pub struct RetagInfo { pub cause: RetagCause, - pub in_field: bool, } #[derive(Debug, Clone, Copy, PartialEq)] @@ -386,10 +385,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { self.history.id, self.offset.bytes(), ); - let mut helps = vec![operation_summary(&op.info.summary(), self.history.id, op.range)]; - if op.info.in_field { - helps.push(format!("errors for retagging in fields are fairly new; please reach out to us (e.g. at ) if you find this error troubling")); - } + let helps = vec![operation_summary(&op.info.summary(), self.history.id, op.range)]; err_sb_ub( format!("{action}{}", error_cause(stack, op.orig_tag)), helps, @@ -505,16 +501,12 @@ fn error_cause(stack: &Stack, prov_extra: ProvenanceExtra) -> &'static str { impl RetagInfo { fn summary(&self) -> String { - let mut s = match self.cause { + match self.cause { RetagCause::Normal => "retag", RetagCause::FnEntry => "function-entry retag", RetagCause::InPlaceFnPassing => "in-place function argument/return passing protection", RetagCause::TwoPhase => "two-phase retag", } - .to_string(); - if self.in_field { - s.push_str(" (of a reference/box inside this compound value)"); - } - s + .to_string() } } 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 66e804d972b76..58fbd8e0a6570 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -5,13 +5,13 @@ pub mod diagnostics; mod item; mod stack; +use std::cmp; use std::fmt::Write; use std::sync::atomic::AtomicBool; -use std::{cmp, mem}; use rustc_abi::Size; use rustc_data_structures::fx::FxHashSet; -use rustc_middle::mir::{Mutability, RetagKind}; +use rustc_middle::mir::Mutability; use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; @@ -59,13 +59,13 @@ enum NewPermission { impl NewPermission { /// A key function: determine the permissions to grant at a retag for the given kind of /// reference/pointer. - fn from_ref_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self { - let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector); + fn from_ref_ty<'tcx>(ty: Ty<'tcx>, mode: RetagMode, cx: &crate::MiriInterpCx<'tcx>) -> Self { + let protector = (mode == RetagMode::FnEntry).then_some(ProtectorKind::StrongProtector); match ty.kind() { ty::Ref(_, pointee, Mutability::Mut) => { - if kind == RetagKind::TwoPhase { + if mode == RetagMode::TwoPhase { // We mostly just give up on 2phase-borrows, and treat these exactly like raw pointers. - assert!(protector.is_none()); // RetagKind can't be both FnEntry and TwoPhase. + assert!(protector.is_none()); // RetagMode can't be both FnEntry and TwoPhase. NewPermission::Uniform { perm: Permission::SharedReadWrite, access: None, @@ -90,7 +90,8 @@ impl NewPermission { } } ty::RawPtr(_, Mutability::Mut) => { - assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw. + assert!(mode == RetagMode::Raw); + assert!(protector.is_none()); // RetagMode can't be both FnEntry and Raw. // Mutable raw pointer. No access, not protected. NewPermission::Uniform { perm: Permission::SharedReadWrite, @@ -114,7 +115,8 @@ impl NewPermission { } } ty::RawPtr(_, Mutability::Not) => { - assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw. + assert!(mode == RetagMode::Raw); + assert!(protector.is_none()); // RetagMode 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, @@ -128,7 +130,7 @@ impl NewPermission { } } - fn from_box_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self { + fn from_box_ty<'tcx>(ty: Ty<'tcx>, mode: RetagMode, cx: &crate::MiriInterpCx<'tcx>) -> Self { // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling). let pointee = ty.builtin_deref(true).unwrap(); if pointee.is_unpin(*cx.tcx, cx.typing_env()) @@ -139,7 +141,7 @@ impl NewPermission { NewPermission::Uniform { perm: Permission::Unique, access: Some(AccessKind::Write), - protector: (kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector), + protector: (mode == RetagMode::FnEntry).then_some(ProtectorKind::WeakProtector), } } else { // `!Unpin` boxes do not get `noalias` nor `dereferenceable`. @@ -664,7 +666,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { if size == Size::ZERO { trace!( - "reborrow of size 0: reference {:?} derived from {:?} (pointee {})", + "reborrow of size 0: reference {:?} derived from {:?} (pointee {}) with permissions {new_perm:?}", new_tag, place.ptr(), place.layout.ty, @@ -699,7 +701,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { log_creation(this, Some((alloc_id, base_offset, orig_tag)))?; trace!( - "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}", + "reborrow: reference {:?} derived from {:?} (pointee {}) with permissions {new_perm:?}: {:?}, size {}", new_tag, orig_tag, place.layout.ty, @@ -849,136 +851,38 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { // one must also be `Some`.) interp_ok(place.clone().map_provenance(|_| new_prov.unwrap())) } - - /// Retags an individual pointer, returning the retagged version. - /// `kind` indicates what kind of reference is being created. - fn sb_retag_reference( - &mut self, - val: &ImmTy<'tcx>, - new_perm: NewPermission, - info: RetagInfo, // diagnostics info about this retag - ) -> InterpResult<'tcx, ImmTy<'tcx>> { - let this = self.eval_context_mut(); - let place = this.ref_to_mplace(val)?; - let new_place = this.sb_retag_place(&place, new_perm, info)?; - interp_ok(ImmTy::from_immediate(new_place.to_ref(this), val.layout)) - } } impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn sb_retag_ptr_value( &mut self, - kind: RetagKind, 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, - }; - this.sb_retag_reference(val, new_perm, RetagInfo { cause, in_field: false }) - } - - fn sb_retag_place_contents( - &mut self, - kind: RetagKind, - place: &PlaceTy<'tcx>, - ) -> InterpResult<'tcx> { + ty: Ty<'tcx>, + mode: RetagMode, + ) -> InterpResult<'tcx, Option>> { let this = self.eval_context_mut(); - let retag_cause = match kind { - RetagKind::TwoPhase => unreachable!(), // can only happen in `retag_ptr_value` - RetagKind::FnEntry => RetagCause::FnEntry, - RetagKind::Default | RetagKind::Raw => RetagCause::Normal, + let cause = match mode { + RetagMode::TwoPhase => RetagCause::TwoPhase, + RetagMode::FnEntry => RetagCause::FnEntry, + RetagMode::Raw | RetagMode::Default => RetagCause::Normal, + RetagMode::None => return interp_ok(None), // no retagging }; - let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, in_field: false }; - return visitor.visit_value(place); - - // The actual visitor. - struct RetagVisitor<'ecx, 'tcx> { - ecx: &'ecx mut MiriInterpCx<'tcx>, - kind: RetagKind, - retag_cause: RetagCause, - in_field: bool, - } - impl<'ecx, 'tcx> RetagVisitor<'ecx, 'tcx> { - #[inline(always)] // yes this helps in our benchmarks - fn retag_ptr_inplace( - &mut self, - place: &PlaceTy<'tcx>, - new_perm: NewPermission, - ) -> InterpResult<'tcx> { - let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?; - let val = self.ecx.sb_retag_reference( - &val, - new_perm, - RetagInfo { cause: self.retag_cause, in_field: self.in_field }, - )?; - self.ecx.write_immediate(*val, place)?; - - interp_ok(()) - } - } - impl<'ecx, 'tcx> ValueVisitor<'tcx, MiriMachine<'tcx>> for RetagVisitor<'ecx, 'tcx> { - type V = PlaceTy<'tcx>; - - #[inline(always)] - fn ecx(&self) -> &MiriInterpCx<'tcx> { - self.ecx - } - - fn visit_box(&mut self, box_ty: Ty<'tcx>, place: &PlaceTy<'tcx>) -> InterpResult<'tcx> { - // Only boxes for the global allocator get any special treatment. - if box_ty.is_box_global(*self.ecx.tcx) { - // Boxes get a weak protectors, since they may be deallocated. - let new_perm = NewPermission::from_box_ty(place.layout.ty, self.kind, self.ecx); - self.retag_ptr_inplace(place, new_perm)?; - } - interp_ok(()) + let new_perm = if ty.is_box() { + if ty.is_box_global(*this.tcx) { + NewPermission::from_box_ty(val.layout.ty, mode, this) + } else { + // Boxes with local allocator are not retagged. + return interp_ok(None); } + } else { + NewPermission::from_ref_ty(val.layout.ty, mode, this) + }; - fn visit_value(&mut self, place: &PlaceTy<'tcx>) -> InterpResult<'tcx> { - // If this place is smaller than a pointer, we know that it can't contain any - // pointers we need to retag, so we can stop recursion early. - // This optimization is crucial for ZSTs, because they can contain way more fields - // than we can ever visit. - if place.layout.is_sized() && place.layout.size < self.ecx.pointer_size() { - return interp_ok(()); - } - - // 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::Adt(adt, _) if adt.is_box() => { - // Recurse for boxes, they require some tricky handling and will end up in `visit_box` above. - // (Yes this means we technically also recursively retag the allocator itself - // even if field retagging is not enabled. *shrug*) - self.walk_value(place)?; - } - ty::Adt(adt, _) if adt.is_maybe_dangling() => { - // Skip traversing for everything inside of `MaybeDangling` - } - _ => { - // Not a reference/pointer/box. Recurse. - let in_field = mem::replace(&mut self.in_field, true); // remember and restore old value - self.walk_value(place)?; - self.in_field = in_field; - } - } - - interp_ok(()) - } - } + let info = RetagInfo { cause }; + let place = this.ref_to_mplace(val)?; + let new_place = this.sb_retag_place(&place, new_perm, info)?; + interp_ok(Some(ImmTy::from_immediate(new_place.to_ref(this), val.layout))) } /// Protect a place so that it cannot be used any more for the duration of the current function @@ -994,11 +898,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { access: Some(AccessKind::Write), protector: Some(ProtectorKind::StrongProtector), }; - this.sb_retag_place( - place, - new_perm, - RetagInfo { cause: RetagCause::InPlaceFnPassing, in_field: false }, - ) + this.sb_retag_place(place, new_perm, RetagInfo { cause: RetagCause::InPlaceFnPassing }) } /// Mark the given tag as exposed. It was found on a pointer with the given AllocId. diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index a205502327307..46a58dec4a3eb 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,5 +1,5 @@ use rustc_abi::Size; -use rustc_middle::mir::{Mutability, RetagKind}; +use rustc_middle::mir::Mutability; use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; @@ -130,13 +130,17 @@ impl<'tcx> NewPermission { fn new( pointee: Ty<'tcx>, ref_mutability: Option, - retag_kind: RetagKind, + mode: RetagMode, cx: &crate::MiriInterpCx<'tcx>, ) -> Option { + if mode == RetagMode::None { + return None; + } + let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env()) && pointee.is_unsafe_unpin(*cx.tcx, cx.typing_env()); let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env()); - let is_protected = retag_kind == RetagKind::FnEntry; + let is_protected = mode == RetagMode::FnEntry; if matches!(ref_mutability, Some(Mutability::Mut) | None if !ty_is_unpin) { // Mutable reference / Box to pinning type: retagging is a NOP. @@ -407,18 +411,6 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // one must also be `Some`.) interp_ok(place.clone().map_provenance(|_| new_prov.unwrap())) } - - /// Retags an individual pointer, returning the retagged version. - fn tb_retag_reference( - &mut self, - val: &ImmTy<'tcx>, - new_perm: NewPermission, - ) -> InterpResult<'tcx, ImmTy<'tcx>> { - let this = self.eval_context_mut(); - let place = this.ref_to_mplace(val)?; - let new_place = this.tb_retag_place(&place, new_perm)?; - interp_ok(ImmTy::from_immediate(new_place.to_ref(this), val.layout)) - } } impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} @@ -427,112 +419,36 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// raw pointers are never reborrowed. fn tb_retag_ptr_value( &mut self, - kind: RetagKind, val: &ImmTy<'tcx>, - ) -> InterpResult<'tcx, ImmTy<'tcx>> { + ty: Ty<'tcx>, + mode: RetagMode, + ) -> InterpResult<'tcx, Option>> { let this = self.eval_context_mut(); - let new_perm = match val.layout.ty.kind() { - &ty::Ref(_, pointee, mutability) => - NewPermission::new(pointee, Some(mutability), kind, this), - _ => None, - }; - if let Some(new_perm) = new_perm { - this.tb_retag_reference(val, new_perm) - } else { - interp_ok(val.clone()) - } - } - - /// Retag all pointers that are stored in this place. - fn tb_retag_place_contents( - &mut self, - kind: RetagKind, - place: &PlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - let mut visitor = RetagVisitor { ecx: this, kind }; - return visitor.visit_value(place); - - // The actual visitor. - struct RetagVisitor<'ecx, 'tcx> { - ecx: &'ecx mut MiriInterpCx<'tcx>, - kind: RetagKind, - } - impl<'ecx, 'tcx> RetagVisitor<'ecx, 'tcx> { - #[inline(always)] // yes this helps in our benchmarks - fn retag_ptr_inplace( - &mut self, - place: &PlaceTy<'tcx>, - new_perm: Option, - ) -> InterpResult<'tcx> { - if let Some(new_perm) = new_perm { - let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?; - let val = self.ecx.tb_retag_reference(&val, new_perm)?; - self.ecx.write_immediate(*val, place)?; - } - interp_ok(()) + let new_perm = match ty.kind() { + _ if ty.is_box_global(*this.tcx) => { + // The `None` marks this as a Box. + NewPermission::new(ty.builtin_deref(true).unwrap(), None, mode, this) } - } - impl<'ecx, 'tcx> ValueVisitor<'tcx, MiriMachine<'tcx>> for RetagVisitor<'ecx, 'tcx> { - type V = PlaceTy<'tcx>; + &ty::Ref(_, pointee, mutability) => + NewPermission::new(pointee, Some(mutability), mode, this), - #[inline(always)] - fn ecx(&self) -> &MiriInterpCx<'tcx> { - self.ecx + &ty::RawPtr(..) => { + assert!(mode == RetagMode::Raw); + // We don't give new tags to raw pointers. + None } - - /// Regardless of how `Unique` is handled, Boxes are always reborrowed. - /// When `Unique` is also reborrowed, then it behaves exactly like `Box` - /// except for the fact that `Box` has a non-zero-sized reborrow. - fn visit_box(&mut self, box_ty: Ty<'tcx>, place: &PlaceTy<'tcx>) -> InterpResult<'tcx> { - // Only boxes for the global allocator get any special treatment. - if box_ty.is_box_global(*self.ecx.tcx) { - let pointee = place.layout.ty.builtin_deref(true).unwrap(); - let new_perm = - NewPermission::new(pointee, /* not a ref */ None, self.kind, self.ecx); - self.retag_ptr_inplace(place, new_perm)?; - } - interp_ok(()) - } - - fn visit_value(&mut self, place: &PlaceTy<'tcx>) -> InterpResult<'tcx> { - // If this place is smaller than a pointer, we know that it can't contain any - // pointers we need to retag, so we can stop recursion early. - // This optimization is crucial for ZSTs, because they can contain way more fields - // than we can ever visit. - if place.layout.is_sized() && place.layout.size < self.ecx.pointer_size() { - return interp_ok(()); - } - - // Check the type of this value to see what to do with it (retag, or recurse). - match place.layout.ty.kind() { - &ty::Ref(_, pointee, mutability) => { - let new_perm = - NewPermission::new(pointee, Some(mutability), 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. - // (Yes this means we technically also recursively retag the allocator itself - // even if field retagging is not enabled. *shrug*) - self.walk_value(place)?; - } - ty::Adt(adt, _) if adt.is_maybe_dangling() => { - // Skip traversing for everything inside of `MaybeDangling` - } - _ => { - // Not a reference/pointer/box. Recurse. - self.walk_value(place)?; - } - } - interp_ok(()) + _ if ty.is_box() => { + // No retagging for boxes with local allocators. + None } + _ => panic!("tb_retag_ptr_value: invalid type {ty}"), + }; + if let Some(new_perm) = new_perm { + let place = this.ref_to_mplace(val)?; + let new_place = this.tb_retag_place(&place, new_perm)?; + interp_ok(Some(ImmTy::from_immediate(new_place.to_ref(this), val.layout))) + } else { + interp_ok(None) } } diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 9d93edcaa3445..ac8ed09719399 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -106,7 +106,17 @@ impl fmt::Debug for TerminationInfo { } } -impl MachineStopType for TerminationInfo {} +impl MachineStopType for TerminationInfo { + fn with_validation_path(&mut self, path: String) { + use TerminationInfo::*; + match self { + StackedBorrowsUb { help, .. } => { + help.push(format!("while retagging field {path}")); + } + _ => {} + } + } +} /// Miri specific diagnostics pub enum NonHaltingDiagnostic { diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index f41e3c20a7d54..b94484fe0cf67 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -180,10 +180,16 @@ pub const MIRI_DEFAULT_ARGS: &[&str] = &[ "--cfg=miri", "-Zalways-encode-mir", "-Zextra-const-ub-checks", - "-Zmir-emit-retag", "-Zmir-preserve-ub", "-Zmir-opt-level=0", + // Disable passes that add checks for language UB -- we get better diagnostics if + // we let Miri do these checks. "-Zmir-enable-passes=-CheckAlignment,-CheckNull,-CheckEnums", + // FIXME: Disable some passes to make higher opt levels also work. + // - ReferencePropagation is incompatible with SB's ref-to-raw castb behavior. + // The fix here is to ditch SB and use TB instead but we're not yet ready for that. + // - GVN is not yet adjusted for implicit retags during assignments. + "-Zmir-enable-passes=-ReferencePropagation,-GVN", // Deduplicating diagnostics means we miss events when tracking what happens during an // execution. Let's not do that. "-Zdeduplicate-diagnostics=no", diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index d8224f1878f05..22688552efee2 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1656,26 +1656,23 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { #[inline(always)] fn retag_ptr_value( ecx: &mut InterpCx<'tcx, Self>, - kind: mir::RetagKind, val: &ImmTy<'tcx>, - ) -> InterpResult<'tcx, ImmTy<'tcx>> { + ty: Ty<'tcx>, + ) -> InterpResult<'tcx, Option>> { if ecx.machine.borrow_tracker.is_some() { - ecx.retag_ptr_value(kind, val) + ecx.retag_ptr_value(val, ty) } else { - interp_ok(val.clone()) + interp_ok(None) } } #[inline(always)] - fn retag_place_contents( + fn with_retag_mode( ecx: &mut InterpCx<'tcx, Self>, - kind: mir::RetagKind, - place: &PlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - if ecx.machine.borrow_tracker.is_some() { - ecx.retag_place_contents(kind, place)?; - } - interp_ok(()) + mode: RetagMode, + f: impl FnOnce(&mut InterpCx<'tcx, Self>) -> InterpResult<'tcx, T>, + ) -> InterpResult<'tcx, T> { + if ecx.machine.borrow_tracker.is_some() { ecx.with_retag_mode(mode, f) } else { f(ecx) } } fn protect_in_place_function_argument( diff --git a/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.stack.stderr b/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.stack.stderr index e0fbe02edc2de..502b438e54ffc 100644 --- a/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.stack.stderr @@ -10,7 +10,7 @@ help: was created by a SharedReadOnly retag at offsets [0x0..0x4] --> tests/fail/both_borrows/alias_through_mutation.rs:LL:CC | LL | *x = &mut *(target as *mut _); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: was later invalidated at offsets [0x0..0x4] by a write access --> tests/fail/both_borrows/alias_through_mutation.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.tree.stderr b/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.tree.stderr index 0a24a1ef3982e..b6ab76fa4e43a 100644 --- a/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/alias_through_mutation.tree.stderr @@ -11,7 +11,7 @@ help: the accessed tag was created here, in the initial state Frozen --> tests/fail/both_borrows/alias_through_mutation.rs:LL:CC | LL | *x = &mut *(target as *mut _); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4] --> tests/fail/both_borrows/alias_through_mutation.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr index cdd668f1f6330..9e0984d07353a 100644 --- a/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/aliasing_mut1.stack.stderr @@ -10,7 +10,7 @@ help: was created by a Unique retag at offsets [0x0..0x4] --> tests/fail/both_borrows/aliasing_mut1.rs:LL:CC | LL | let xraw: *mut i32 = unsafe { mem::transmute(&mut x) }; - | ^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ help: is this argument --> tests/fail/both_borrows/aliasing_mut1.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr index ef7d54b0b19d9..7a34e7d4e991e 100644 --- a/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.stack.stderr @@ -7,8 +7,8 @@ LL | | from_raw_parts_mut(ptr.offset(mid as isize), len - mid), LL | | ) | | ^ | | | - | |_____________this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x0..0x10] - | errors for retagging in fields are fairly new; please reach out to us (e.g. at ) if you find this error troubling + | |_____________this error occurs as part of retag at ALLOC[0x0..0x10] + | while retagging field .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 diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.rs b/src/tools/miri/tests/fail/both_borrows/drop_in_place_protector.rs similarity index 57% rename from src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.rs rename to src/tools/miri/tests/fail/both_borrows/drop_in_place_protector.rs index 8cf63ee700b85..7788b091960e9 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.rs +++ b/src/tools/miri/tests/fail/both_borrows/drop_in_place_protector.rs @@ -1,3 +1,6 @@ +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows + //! Test that drop_in_place retags the entire place, //! invalidating all aliases to it. @@ -9,8 +12,11 @@ struct HasDrop; impl Drop for HasDrop { fn drop(&mut self) { unsafe { - let _val = *P; - //~^ ERROR: /not granting access .* because that would remove .* which is strongly protected/ + // The error really has to mention a protector to make sure we're checking the right thing! + P.write(0); + //~[stack]^ ERROR: /not granting access .* because that would remove .* which is strongly protected/ + //~[tree]| ERROR: forbidden + // For Tree Borrows, the protector is only mentioned in the "help:" texts unfortunately. } } } diff --git a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr b/src/tools/miri/tests/fail/both_borrows/drop_in_place_protector.stack.stderr similarity index 74% rename from src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr rename to src/tools/miri/tests/fail/both_borrows/drop_in_place_protector.stack.stderr index 027fe239319a3..76a22ea1bd4e1 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/drop_in_place_protector.stderr +++ b/src/tools/miri/tests/fail/both_borrows/drop_in_place_protector.stack.stderr @@ -1,30 +1,30 @@ error: Undefined Behavior: not granting access to tag because that would remove [Unique for ] which is strongly protected - --> tests/fail/stacked_borrows/drop_in_place_protector.rs:LL:CC + --> tests/fail/both_borrows/drop_in_place_protector.rs:LL:CC | -LL | let _val = *P; - | ^^ Undefined Behavior occurred here +LL | P.write(0); + | ^^^^^^^^^^ Undefined Behavior occurred here | = 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/stacked_borrows/drop_in_place_protector.rs:LL:CC + --> tests/fail/both_borrows/drop_in_place_protector.rs:LL:CC | LL | let x = core::ptr::addr_of_mut!(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: is this argument - --> tests/fail/stacked_borrows/drop_in_place_protector.rs:LL:CC + --> tests/fail/both_borrows/drop_in_place_protector.rs:LL:CC | LL | core::ptr::drop_in_place(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: stack backtrace: 0: ::drop - at tests/fail/stacked_borrows/drop_in_place_protector.rs:LL:CC + at tests/fail/both_borrows/drop_in_place_protector.rs:LL:CC 1: std::ptr::drop_in_place - shim(Some(HasDrop)) at RUSTLIB/core/src/ptr/mod.rs:LL:CC 2: std::ptr::drop_in_place - shim(Some((HasDrop, u8))) at RUSTLIB/core/src/ptr/mod.rs:LL:CC 3: main - at tests/fail/stacked_borrows/drop_in_place_protector.rs:LL:CC + at tests/fail/both_borrows/drop_in_place_protector.rs:LL:CC = 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/both_borrows/drop_in_place_protector.tree.stderr b/src/tools/miri/tests/fail/both_borrows/drop_in_place_protector.tree.stderr new file mode 100644 index 0000000000000..9b2bd1a9ef6b3 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/drop_in_place_protector.tree.stderr @@ -0,0 +1,35 @@ +error: Undefined Behavior: write access through (root of the allocation) at ALLOC[0x0] is forbidden + --> tests/fail/both_borrows/drop_in_place_protector.rs:LL:CC + | +LL | P.write(0); + | ^^^^^^^^^^ Undefined Behavior occurred here + | + = 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: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the accessed tag (root of the allocation) is foreign to the protected tag (i.e., it is not a child) + = help: this foreign write access would cause the protected tag (currently Reserved) to become Disabled + = help: protected tags must never be Disabled +help: the accessed tag was created here + --> tests/fail/both_borrows/drop_in_place_protector.rs:LL:CC + | +LL | let mut x = (HasDrop, 0u8); + | ^^^^^^^^^^^^^^ +help: the protected tag was created here, in the initial state Reserved + --> tests/fail/both_borrows/drop_in_place_protector.rs:LL:CC + | +LL | core::ptr::drop_in_place(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: stack backtrace: + 0: ::drop + at tests/fail/both_borrows/drop_in_place_protector.rs:LL:CC + 1: std::ptr::drop_in_place - shim(Some(HasDrop)) + at RUSTLIB/core/src/ptr/mod.rs:LL:CC + 2: std::ptr::drop_in_place - shim(Some((HasDrop, u8))) + at RUSTLIB/core/src/ptr/mod.rs:LL:CC + 3: main + at tests/fail/both_borrows/drop_in_place_protector.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/issue-miri-1050-1.rs b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs deleted file mode 100644 index d907c5de79700..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@revisions: stack tree -// Ensure this even hits the aliasing model -//@compile-flags: -Zmiri-disable-validation -//@[tree]compile-flags: -Zmiri-tree-borrows -//@error-in-other-file: pointer not dereferenceable - -fn main() { - unsafe { - let ptr = Box::into_raw(Box::new(0u16)); - drop(Box::from_raw(ptr as *mut u32)); - } -} diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr deleted file mode 100644 index 14a4065c1f0a5..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got ALLOC which is only 2 bytes from the end of the allocation - --> RUSTLIB/alloc/src/boxed.rs:LL:CC - | -LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here - | - = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior - = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information -help: ALLOC was allocated here: - --> tests/fail/both_borrows/issue-miri-1050-1.rs:LL:CC - | -LL | let ptr = Box::into_raw(Box::new(0u16)); - | ^^^^^^^^^^^^^^ - = note: stack backtrace: - 0: std::boxed::Box::from_raw_in - at RUSTLIB/alloc/src/boxed.rs:LL:CC - 1: std::boxed::Box::from_raw - at RUSTLIB/alloc/src/boxed.rs:LL:CC - 2: main - at tests/fail/both_borrows/issue-miri-1050-1.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/issue-miri-1050-1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr deleted file mode 100644 index 14a4065c1f0a5..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got ALLOC which is only 2 bytes from the end of the allocation - --> RUSTLIB/alloc/src/boxed.rs:LL:CC - | -LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here - | - = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior - = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information -help: ALLOC was allocated here: - --> tests/fail/both_borrows/issue-miri-1050-1.rs:LL:CC - | -LL | let ptr = Box::into_raw(Box::new(0u16)); - | ^^^^^^^^^^^^^^ - = note: stack backtrace: - 0: std::boxed::Box::from_raw_in - at RUSTLIB/alloc/src/boxed.rs:LL:CC - 1: std::boxed::Box::from_raw - at RUSTLIB/alloc/src/boxed.rs:LL:CC - 2: main - at tests/fail/both_borrows/issue-miri-1050-1.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/issue-miri-1050-2.rs b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs deleted file mode 100644 index b54f27bb8b23e..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@revisions: stack tree -// Ensure this even hits the aliasing model -//@compile-flags: -Zmiri-disable-validation -//@[tree]compile-flags: -Zmiri-tree-borrows -//@error-in-other-file: is a dangling pointer -use std::ptr::NonNull; - -fn main() { - unsafe { - let ptr = NonNull::::dangling(); - drop(Box::from_raw(ptr.as_ptr())); - } -} diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr deleted file mode 100644 index beb712388f91f..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got 0x4[noalloc] which is a dangling pointer (it has no provenance) - --> RUSTLIB/alloc/src/boxed.rs:LL:CC - | -LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here - | - = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior - = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: stack backtrace: - 0: std::boxed::Box::from_raw_in - at RUSTLIB/alloc/src/boxed.rs:LL:CC - 1: std::boxed::Box::from_raw - at RUSTLIB/alloc/src/boxed.rs:LL:CC - 2: main - at tests/fail/both_borrows/issue-miri-1050-2.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/issue-miri-1050-2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr deleted file mode 100644 index beb712388f91f..0000000000000 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got 0x4[noalloc] which is a dangling pointer (it has no provenance) - --> RUSTLIB/alloc/src/boxed.rs:LL:CC - | -LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here - | - = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior - = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: stack backtrace: - 0: std::boxed::Box::from_raw_in - at RUSTLIB/alloc/src/boxed.rs:LL:CC - 1: std::boxed::Box::from_raw - at RUSTLIB/alloc/src/boxed.rs:LL:CC - 2: main - at tests/fail/both_borrows/issue-miri-1050-2.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/load_invalid_shr.rs b/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.rs index 2e0f14e32dbc9..c6bed6b97603b 100644 --- a/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.rs +++ b/src/tools/miri/tests/fail/both_borrows/load_invalid_shr.rs @@ -1,7 +1,5 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -// Make sure we catch this even without validation -//@compile-flags: -Zmiri-disable-validation // Make sure that we cannot load from memory a `&` that got already invalidated. fn main() { diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr index c5b8de9563c39..c93e72ffc2323 100644 --- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_option.stack.stderr @@ -4,8 +4,8 @@ error: Undefined Behavior: trying to retag from for SharedReadOnly permiss LL | foo(some_xref); | ^^^^^^^^^ | | - | this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x0..0x4] - | errors for retagging in fields are fairly new; please reach out to us (e.g. at ) if you find this error troubling + | this error occurs as part of retag at ALLOC[0x0..0x4] + | while retagging field ..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 diff --git a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr index fd5ca73a7afdc..c9acb6910c3e6 100644 --- a/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/pass_invalid_shr_tuple.stack.stderr @@ -4,8 +4,8 @@ error: Undefined Behavior: trying to retag from for SharedReadOnly permiss LL | foo(pair_xref); | ^^^^^^^^^ | | - | this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x0..0x4] - | errors for retagging in fields are fairly new; please reach out to us (e.g. at ) if you find this error troubling + | this error occurs as part of retag at ALLOC[0x0..0x4] + | while retagging field .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 diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr index 94d538072ae07..b028504fc2da6 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_option.stack.stderr @@ -4,8 +4,8 @@ error: Undefined Behavior: trying to retag from for SharedReadOnly permiss LL | ret | ^^^ | | - | this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x4..0x8] - | errors for retagging in fields are fairly new; please reach out to us (e.g. at ) if you find this error troubling + | this error occurs as part of retag at ALLOC[0x4..0x8] + | while retagging field ..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 diff --git a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr index ffe673e1bcf9b..f2bd4077fefd9 100644 --- a/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/return_invalid_shr_tuple.stack.stderr @@ -4,8 +4,8 @@ error: Undefined Behavior: trying to retag from for SharedReadOnly permiss LL | ret | ^^^ | | - | this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x4..0x8] - | errors for retagging in fields are fairly new; please reach out to us (e.g. at ) if you find this error troubling + | this error occurs as part of retag at ALLOC[0x4..0x8] + | while retagging field .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 diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs index 9646cdb206591..3c121d11827e6 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs @@ -8,7 +8,7 @@ fn direct_raw(x: *const (i32, i32)) -> *const i32 { // reference, we catch that. (Just in case someone decides to // desugar this differently or so.) fn via_ref(x: *const (i32, i32)) -> *const i32 { - unsafe { &(*x).0 as *const i32 } //~ERROR: dangling pointer + unsafe { &(*x).0 as *const i32 } //~ERROR: dangling reference } fn main() { diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr index feff143cba66c..433053ca8ffaa 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got 0x10[noalloc] which is a dangling pointer (it has no provenance) +error: Undefined Behavior: constructing invalid value of type &i32: encountered a dangling reference (0x10[noalloc] has no provenance) --> tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs:LL:CC | LL | unsafe { &(*x).0 as *const i32 } diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.rs b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.rs index 57e95ef19dc99..92289db69f107 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.rs @@ -3,5 +3,5 @@ fn main() { let x = 16usize as *const u32; - let _y = unsafe { &*x as *const u32 }; //~ ERROR: is a dangling pointer + let _y = unsafe { *(&*x as *const u32) }; //~ ERROR: is a dangling pointer } diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr index 21808abc5a424..50f041931aea9 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got 0x10[noalloc] which is a dangling pointer (it has no provenance) +error: Undefined Behavior: memory access failed: attempting to access 4 bytes, but got 0x10[noalloc] which is a dangling pointer (it has no provenance) --> tests/fail/dangling_pointers/deref-invalid-ptr.rs:LL:CC | -LL | let _y = unsafe { &*x as *const u32 }; - | ^^^ Undefined Behavior occurred here +LL | let _y = unsafe { *(&*x as *const u32) }; + | ^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs index f434928680108..7dbe040baedb1 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs +++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.rs @@ -10,7 +10,8 @@ fn fill(v: &mut i32) { } fn evil() { - let _ref = unsafe { &mut *(LEAK as *mut i32) }; //~ ERROR: is a dangling pointer + let _x = unsafe { *&mut *(LEAK as *mut i32) }; //~ ERROR: is a dangling pointer + } fn main() { diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr index 67b60e6bca41c..dc3565ce399be 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) +error: Undefined Behavior: memory access failed: attempting to access 4 bytes, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) --> tests/fail/dangling_pointers/storage_dead_dangling.rs:LL:CC | -LL | let _ref = unsafe { &mut *(LEAK as *mut i32) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here +LL | let _x = unsafe { *&mut *(LEAK as *mut i32) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/erroneous_const2.stderr b/src/tools/miri/tests/fail/erroneous_const2.stderr index d9074e6e2498b..7cd641b4ce1e9 100644 --- a/src/tools/miri/tests/fail/erroneous_const2.stderr +++ b/src/tools/miri/tests/fail/erroneous_const2.stderr @@ -24,6 +24,14 @@ note: erroneous constant encountered LL | println!("{}", FOO); | ^^^ +note: erroneous constant encountered + --> tests/fail/erroneous_const2.rs:LL:CC + | +LL | println!("{}", FOO); + | ^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`. diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs index 1fb597fdc02af..3f6cd583aaff0 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs @@ -2,8 +2,6 @@ //! live in memory. //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -// Validation forces more things into memory, which we can't have here. -//@compile-flags: -Zmiri-disable-validation #![feature(custom_mir, core_intrinsics)] diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs index b3d43ca63cb07..2b6649b346e57 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs @@ -2,8 +2,6 @@ //! they do not live in memory. //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -// Validation forces more things into memory, which we can't have here. -//@compile-flags: -Zmiri-disable-validation #![feature(custom_mir, core_intrinsics)] use std::intrinsics::mir::*; diff --git a/src/tools/miri/tests/fail/provenance/mix-ptrs1.stderr b/src/tools/miri/tests/fail/provenance/mix-ptrs1.stderr index e1d4b7d95f664..bba4705f1c90a 100644 --- a/src/tools/miri/tests/fail/provenance/mix-ptrs1.stderr +++ b/src/tools/miri/tests/fail/provenance/mix-ptrs1.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) +error: Undefined Behavior: constructing invalid value of type &i32: encountered a dangling reference ($HEX[noalloc] has no provenance) --> tests/fail/provenance/mix-ptrs1.rs:LL:CC | LL | assert_eq!(*strange_ptr.with_addr(ptr.addr()), 0); diff --git a/src/tools/miri/tests/fail/provenance/mix-ptrs2.stderr b/src/tools/miri/tests/fail/provenance/mix-ptrs2.stderr index a77f73f81e5fa..86ad72f0e19d6 100644 --- a/src/tools/miri/tests/fail/provenance/mix-ptrs2.stderr +++ b/src/tools/miri/tests/fail/provenance/mix-ptrs2.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: pointer not dereferenceable: pointer must be dereferenceable for 4 bytes, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) +error: Undefined Behavior: constructing invalid value of type &i32: encountered a dangling reference ($HEX[noalloc] has no provenance) --> tests/fail/provenance/mix-ptrs2.rs:LL:CC | LL | assert_eq!(*ptr, 42); diff --git a/src/tools/miri/tests/fail/rc_as_ptr.stderr b/src/tools/miri/tests/fail/rc_as_ptr.stderr index d97878f815cc5..42bf8637e0da8 100644 --- a/src/tools/miri/tests/fail/rc_as_ptr.stderr +++ b/src/tools/miri/tests/fail/rc_as_ptr.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: pointer not dereferenceable: ALLOC has been freed, so this pointer is dangling +error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling --> tests/fail/rc_as_ptr.rs:LL:CC | LL | assert_eq!(42, **unsafe { &*Weak::as_ptr(&weak) }); 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 cffa175569506..0970b4e2354b1 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 @@ -4,7 +4,7 @@ error: Undefined Behavior: trying to retag from for Unique permission at A LL | / pub const unsafe fn drop_in_place(to_drop: *mut T) LL | | where LL | | T: [const] Destruct, - | |________________________^ this error occurs as part of retag at ALLOC[0x0..0x1] + | |________________________^ this error occurs as part of function-entry retag at ALLOC[0x0..0x1] | = 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 diff --git a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.rs b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.rs index 5c99c82da6d6a..c03410edd9ed1 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/load_invalid_mut.rs @@ -1,6 +1,3 @@ -// Make sure we catch this even without validation -//@compile-flags: -Zmiri-disable-validation - // Make sure that we cannot load from memory a `&mut` that got already invalidated. fn main() { let x = &mut 42; diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr index 5ccb09c7fd844..7874f1fdd0073 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr @@ -4,8 +4,8 @@ error: Undefined Behavior: trying to retag from for Unique permission at A LL | ret | ^^^ | | - | this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x4..0x8] - | errors for retagging in fields are fairly new; please reach out to us (e.g. at ) if you find this error troubling + | this error occurs as part of retag at ALLOC[0x4..0x8] + | while retagging field ..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 diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr index eb68a637c2297..02041054fe97d 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr @@ -4,8 +4,8 @@ error: Undefined Behavior: trying to retag from for Unique permission at A LL | ret | ^^^ | | - | this error occurs as part of retag (of a reference/box inside this compound value) at ALLOC[0x4..0x8] - | errors for retagging in fields are fairly new; please reach out to us (e.g. at ) if you find this error troubling + | this error occurs as part of retag at ALLOC[0x4..0x8] + | while retagging field .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 diff --git a/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.rs b/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.rs index 84d7878b264e5..53819ee36cdcd 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.rs +++ b/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.rs @@ -3,6 +3,6 @@ static X: usize = 5; #[allow(mutable_transmutes)] fn main() { let _x = unsafe { - std::mem::transmute::<&usize, &mut usize>(&X) //~ ERROR: writing to alloc1 which is read-only + std::mem::transmute::<&usize, &mut usize>(&X) //~ ERROR: mutable reference pointing to read-only memory }; } diff --git a/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.stderr b/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.stderr index bca5daa73d701..d43998ae2f434 100644 --- a/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.stderr +++ b/src/tools/miri/tests/fail/stacked_borrows/static_memory_modification.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: writing to ALLOC which is read-only +error: Undefined Behavior: constructing invalid value of type &mut usize: encountered mutable reference pointing to read-only memory --> tests/fail/stacked_borrows/static_memory_modification.rs:LL:CC | LL | std::mem::transmute::<&usize, &mut usize>(&X) diff --git a/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr index efad61c14fb80..28609ddec6a11 100644 --- a/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr +++ b/src/tools/miri/tests/fail/uninit/uninit_alloc_diagnostic_with_provenance.stderr @@ -18,10 +18,10 @@ Uninitialized memory occurred at ALLOC[0x4..0x8], in this allocation: ALLOC (Rust heap, size: 16, align: 8) { ╾42[ALLOC] (ptr fragment 0)╼ 12 13 ╾43[ALLOC] (ptr fragment 1)╼ __ __ __ __ __ __ __ __ __ __ __ __ │ ━..━░░░░░░░░░░░░ } -ALLOC (global (static or const), size: 1, align: 1) { +ALLOC (unchanged global, size: 1, align: 1) { 2a │ * } -ALLOC (global (static or const), size: 1, align: 1) { +ALLOC (unchanged global, size: 1, align: 1) { 00 │ . } diff --git a/src/tools/miri/tests/fail/validity/recursive-validity-box-bool.rs b/src/tools/miri/tests/fail/validity/recursive-validity-box-bool.rs index dee2c9aad2c7d..a726c1b404071 100644 --- a/src/tools/miri/tests/fail/validity/recursive-validity-box-bool.rs +++ b/src/tools/miri/tests/fail/validity/recursive-validity-box-bool.rs @@ -1,8 +1,8 @@ //@compile-flags: -Zmiri-recursive-validation fn main() { - let x = 3u8; - let xref = &x; + let mut x = 3u8; + let xref = &mut x; let xref_wrong_type: Box = unsafe { std::mem::transmute(xref) }; //~ERROR: encountered 0x03, but expected a boolean let _val = *xref_wrong_type; } diff --git a/src/tools/miri/tests/pass/adjacent-allocs.rs b/src/tools/miri/tests/pass/adjacent-allocs.rs index 711c54fd68ad5..17bd40f342724 100644 --- a/src/tools/miri/tests/pass/adjacent-allocs.rs +++ b/src/tools/miri/tests/pass/adjacent-allocs.rs @@ -1,4 +1,5 @@ -//@compile-flags: -Zmiri-permissive-provenance +// We have to disable `RemoveStorageMarkers` as that kills re-allocating the local in the loop. +//@compile-flags: -Zmiri-permissive-provenance -Zmir-enable-passes=-RemoveStorageMarkers fn ensure_allocs_can_be_adjacent() { for _ in 0..512 { 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 115e232dde4c2..5b455a7042a3a 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 @@ -26,6 +26,7 @@ fn main() { box_into_raw_allows_interior_mutable_alias(); cell_inside_struct(); zst(); + mut_derefer(); } // Make sure that reading from an `&mut` does, like reborrowing to `&`, @@ -317,3 +318,13 @@ fn zst() { with_protector(&mut *ptr.cast::<()>(), ptr, l); } } + +fn mut_derefer() { + // The nested derefs get adjusted by the derefer pass, ensure we handle + // the resulting MIR correctly. + let x = &mut &mut (1, 2); + let l = &mut x.0; + *l += 1; + let _r = &mut x.1; + *l += 1; +} diff --git a/src/tools/miri/tests/pass/both_borrows/interior_mutability.rs b/src/tools/miri/tests/pass/both_borrows/interior_mutability.rs index f095e215e0043..01c5dd9659707 100644 --- a/src/tools/miri/tests/pass/both_borrows/interior_mutability.rs +++ b/src/tools/miri/tests/pass/both_borrows/interior_mutability.rs @@ -17,6 +17,7 @@ fn main() { ref_mut_protector(); rust_issue_68303(); two_phase(); + box_derefer(); } fn aliasing_mut_and_shr() { @@ -208,3 +209,13 @@ fn two_phase() { x.get() + l.get() }); } + +fn box_derefer() { + // This fails if we accidentally retag the copies introduced by the derefer pass. + let mut cell = std::cell::RefCell::new(0); + let b = Box::new(&mut cell); + let mut mutref = b.borrow_mut(); + *mutref += 1; + b.try_borrow().unwrap_err(); + *mutref += 1; +} diff --git a/src/tools/miri/tests/pass/issues/issue-miri-1050-1.rs b/src/tools/miri/tests/pass/issues/issue-miri-1050-1.rs new file mode 100644 index 0000000000000..852b13f12ec9d --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-miri-1050-1.rs @@ -0,0 +1,11 @@ +//@compile-flags: -Zmiri-disable-validation -Zmiri-ignore-leaks +// This used to cause ICEs in the aliasing model before validation existed. Now that aliasing checks +// are only triggered by validation, that configuration is no longer possible but we keep the test +// around just in case. + +fn main() { + unsafe { + let ptr = Box::into_raw(Box::new(0u16)); + std::mem::forget(Box::from_raw(ptr as *mut u32)); + } +} diff --git a/src/tools/miri/tests/pass/issues/issue-miri-1050-2.rs b/src/tools/miri/tests/pass/issues/issue-miri-1050-2.rs new file mode 100644 index 0000000000000..0e93c1c1aee46 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-miri-1050-2.rs @@ -0,0 +1,12 @@ +//@compile-flags: -Zmiri-disable-validation +// This used to cause ICEs in the aliasing model before validation existed. Now that aliasing checks +// are only triggered by validation, that configuration is no longer possible but we keep the test +// around just in case. +use std::ptr::NonNull; + +fn main() { + unsafe { + let ptr = NonNull::::dangling(); + std::mem::forget(Box::from_raw(ptr.as_ptr())); + } +} diff --git a/tests/mir-opt/building/custom/references.immut_ref.built.after.mir b/tests/mir-opt/building/custom/references.immut_ref.built.after.mir index d1e1aab99d180..efec19eba6e02 100644 --- a/tests/mir-opt/building/custom/references.immut_ref.built.after.mir +++ b/tests/mir-opt/building/custom/references.immut_ref.built.after.mir @@ -7,7 +7,6 @@ fn immut_ref(_1: &i32) -> &i32 { bb0: { _2 = &raw const (*_1); _0 = &(*_2); - Retag(_0); return; } } diff --git a/tests/mir-opt/building/custom/references.mut_ref.built.after.mir b/tests/mir-opt/building/custom/references.mut_ref.built.after.mir index c82cb3274d607..32c2208af0359 100644 --- a/tests/mir-opt/building/custom/references.mut_ref.built.after.mir +++ b/tests/mir-opt/building/custom/references.mut_ref.built.after.mir @@ -7,7 +7,6 @@ fn mut_ref(_1: &mut i32) -> &mut i32 { bb0: { _2 = &raw mut (*_1); _0 = &mut (*_2); - Retag(_0); return; } } diff --git a/tests/mir-opt/building/custom/references.rs b/tests/mir-opt/building/custom/references.rs index 7ea8f8b4c156d..63f2a26487532 100644 --- a/tests/mir-opt/building/custom/references.rs +++ b/tests/mir-opt/building/custom/references.rs @@ -13,7 +13,6 @@ pub fn mut_ref(x: &mut i32) -> &mut i32 { { t = addr_of_mut!(*x); RET = &mut *t; - Retag(RET); Return() } } @@ -27,7 +26,6 @@ pub fn immut_ref(x: &i32) -> &i32 { { t = addr_of!(*x); RET = & *t; - Retag(RET); Return() } } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 132dfd3d8178a..fa74e494f4675 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -112,16 +112,16 @@ StorageDead(_10); StorageLive(_14); _14 = const {ALLOC0: &&SmallStruct}; - _31 = copy (*_14); + _31 = no_retag copy (*_14); StorageLive(_11); - _32 = copy (*_14); + _32 = no_retag copy (*_14); - _11 = copy ((*_32).0: f32); + _11 = const 9f32; StorageLive(_12); - _33 = copy (*_14); + _33 = no_retag copy (*_14); _12 = copy ((*_33).1: std::option::Option); StorageLive(_13); - _34 = copy (*_14); + _34 = no_retag copy (*_14); _13 = copy ((*_34).2: &[f32]); StorageDead(_14); StorageLive(_15); @@ -149,16 +149,16 @@ StorageDead(_22); StorageLive(_26); _26 = const {ALLOC1: &&BigStruct}; - _35 = copy (*_26); + _35 = no_retag copy (*_26); StorageLive(_23); - _36 = copy (*_26); + _36 = no_retag copy (*_26); - _23 = copy ((*_36).0: f32); + _23 = const 82f32; StorageLive(_24); - _37 = copy (*_26); + _37 = no_retag copy (*_26); _24 = copy ((*_37).1: std::option::Option); StorageLive(_25); - _38 = copy (*_26); + _38 = no_retag copy (*_26); _25 = copy ((*_38).2: &[f32]); StorageDead(_26); StorageLive(_27); diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index 0f3e6f0cb17f7..351a71ce245e6 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -112,16 +112,16 @@ StorageDead(_10); StorageLive(_14); _14 = const {ALLOC0: &&SmallStruct}; - _31 = copy (*_14); + _31 = no_retag copy (*_14); StorageLive(_11); - _32 = copy (*_14); + _32 = no_retag copy (*_14); - _11 = copy ((*_32).0: f32); + _11 = const 9f32; StorageLive(_12); - _33 = copy (*_14); + _33 = no_retag copy (*_14); _12 = copy ((*_33).1: std::option::Option); StorageLive(_13); - _34 = copy (*_14); + _34 = no_retag copy (*_14); _13 = copy ((*_34).2: &[f32]); StorageDead(_14); StorageLive(_15); @@ -149,16 +149,16 @@ StorageDead(_22); StorageLive(_26); _26 = const {ALLOC1: &&BigStruct}; - _35 = copy (*_26); + _35 = no_retag copy (*_26); StorageLive(_23); - _36 = copy (*_26); + _36 = no_retag copy (*_26); - _23 = copy ((*_36).0: f32); + _23 = const 82f32; StorageLive(_24); - _37 = copy (*_26); + _37 = no_retag copy (*_26); _24 = copy ((*_37).1: std::option::Option); StorageLive(_25); - _38 = copy (*_26); + _38 = no_retag copy (*_26); _25 = copy ((*_38).2: &[f32]); StorageDead(_26); StorageLive(_27); diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff deleted file mode 100644 index ab74d2411bb10..0000000000000 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.retags.DeadStoreElimination-initial.diff +++ /dev/null @@ -1,14 +0,0 @@ -- // MIR for `retags` before DeadStoreElimination-initial -+ // MIR for `retags` after DeadStoreElimination-initial - - fn retags(_1: &mut i32) -> () { - debug _r => _1; - let mut _0: (); - - bb0: { - Retag([fn entry] _1); - _0 = const (); - return; - } - } - diff --git a/tests/mir-opt/dead-store-elimination/provenance_soundness.rs b/tests/mir-opt/dead-store-elimination/provenance_soundness.rs index b2523684a09e6..56758883d1224 100644 --- a/tests/mir-opt/dead-store-elimination/provenance_soundness.rs +++ b/tests/mir-opt/dead-store-elimination/provenance_soundness.rs @@ -1,6 +1,5 @@ // Test that we don't remove pointer to int casts or retags //@ test-mir-pass: DeadStoreElimination-initial -//@ compile-flags: -Zmir-emit-retag // EMIT_MIR provenance_soundness.pointer_to_int.DeadStoreElimination-initial.diff fn pointer_to_int(p: *mut i32) { @@ -11,13 +10,6 @@ fn pointer_to_int(p: *mut i32) { let _y = p as isize; } -// EMIT_MIR provenance_soundness.retags.DeadStoreElimination-initial.diff -fn retags(_r: &mut i32) { - // CHECK-LABEL: fn retags( - // CHECK: Retag([fn entry] _1); -} - fn main() { pointer_to_int(&mut 5 as *mut _); - retags(&mut 5); } diff --git a/tests/mir-opt/dead-store-elimination/ref.tuple.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/ref.tuple.DeadStoreElimination-initial.diff index 3e677d13b89c1..e44371a442bf1 100644 --- a/tests/mir-opt/dead-store-elimination/ref.tuple.DeadStoreElimination-initial.diff +++ b/tests/mir-opt/dead-store-elimination/ref.tuple.DeadStoreElimination-initial.diff @@ -13,10 +13,10 @@ bb0: { - StorageLive(_2); -- _3 = copy (_1.1: &Foo); +- _3 = no_retag copy (_1.1: &Foo); - _2 = &((*_3).2: i32); + // DBG: _2 = &((*_3).2: i32); - _4 = copy (_1.1: &Foo); + _4 = no_retag copy (_1.1: &Foo); _0 = copy ((*_4).0: i32); - StorageDead(_2); return; diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff index 9a354fc005ed5..b13c11266317c 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff @@ -53,7 +53,7 @@ StorageDead(_2); - StorageLive(_5); + nop; - _10 = copy (*_1); + _10 = no_retag copy (*_1); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _5 = &raw const (*_11); - StorageLive(_6); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff index 9a354fc005ed5..b13c11266317c 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff @@ -53,7 +53,7 @@ StorageDead(_2); - StorageLive(_5); + nop; - _10 = copy (*_1); + _10 = no_retag copy (*_1); _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _5 = &raw const (*_11); - StorageLive(_6); diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index c8b516c14987b..af472c9a6b6fd 100644 --- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -76,7 +76,7 @@ _4 = (move _5, move _6); StorageDead(_6); StorageDead(_5); - _34 = copy (_4.0: &ViewportPercentageLength); + _34 = no_retag copy (_4.0: &ViewportPercentageLength); _11 = discriminant((*_34)); switchInt(move _11) -> [0: bb2, 1: bb3, 2: bb4, 3: bb5, otherwise: bb12]; } @@ -92,35 +92,35 @@ } bb2: { - _35 = copy (_4.1: &ViewportPercentageLength); + _35 = no_retag copy (_4.1: &ViewportPercentageLength); _7 = discriminant((*_35)); switchInt(move _7) -> [0: bb9, otherwise: bb1]; } bb3: { - _36 = copy (_4.1: &ViewportPercentageLength); + _36 = no_retag copy (_4.1: &ViewportPercentageLength); _8 = discriminant((*_36)); switchInt(move _8) -> [1: bb8, otherwise: bb1]; } bb4: { - _37 = copy (_4.1: &ViewportPercentageLength); + _37 = no_retag copy (_4.1: &ViewportPercentageLength); _9 = discriminant((*_37)); switchInt(move _9) -> [2: bb7, otherwise: bb1]; } bb5: { - _38 = copy (_4.1: &ViewportPercentageLength); + _38 = no_retag copy (_4.1: &ViewportPercentageLength); _10 = discriminant((*_38)); switchInt(move _10) -> [3: bb6, otherwise: bb1]; } bb6: { StorageLive(_27); - _39 = copy (_4.0: &ViewportPercentageLength); + _39 = no_retag copy (_4.0: &ViewportPercentageLength); _27 = copy (((*_39) as Vmax).0: f32); StorageLive(_28); - _40 = copy (_4.1: &ViewportPercentageLength); + _40 = no_retag copy (_4.1: &ViewportPercentageLength); _28 = copy (((*_40) as Vmax).0: f32); StorageLive(_29); StorageLive(_30); @@ -139,10 +139,10 @@ bb7: { StorageLive(_22); - _41 = copy (_4.0: &ViewportPercentageLength); + _41 = no_retag copy (_4.0: &ViewportPercentageLength); _22 = copy (((*_41) as Vmin).0: f32); StorageLive(_23); - _42 = copy (_4.1: &ViewportPercentageLength); + _42 = no_retag copy (_4.1: &ViewportPercentageLength); _23 = copy (((*_42) as Vmin).0: f32); StorageLive(_24); StorageLive(_25); @@ -161,10 +161,10 @@ bb8: { StorageLive(_17); - _43 = copy (_4.0: &ViewportPercentageLength); + _43 = no_retag copy (_4.0: &ViewportPercentageLength); _17 = copy (((*_43) as Vh).0: f32); StorageLive(_18); - _44 = copy (_4.1: &ViewportPercentageLength); + _44 = no_retag copy (_4.1: &ViewportPercentageLength); _18 = copy (((*_44) as Vh).0: f32); StorageLive(_19); StorageLive(_20); @@ -183,10 +183,10 @@ bb9: { StorageLive(_12); - _45 = copy (_4.0: &ViewportPercentageLength); + _45 = no_retag copy (_4.0: &ViewportPercentageLength); _12 = copy (((*_45) as Vw).0: f32); StorageLive(_13); - _46 = copy (_4.1: &ViewportPercentageLength); + _46 = no_retag copy (_4.1: &ViewportPercentageLength); _13 = copy (((*_46) as Vw).0: f32); StorageLive(_14); StorageLive(_15); diff --git a/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff index ab81f0a67e4eb..3166031928ae0 100644 --- a/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff @@ -16,7 +16,7 @@ } bb1: { - _4 = copy (((*_1) as Some).0: &E<'_>); + _4 = no_retag copy (((*_1) as Some).0: &E<'_>); _2 = discriminant((*_4)); switchInt(move _2) -> [1: bb2, 0: bb3, otherwise: bb5]; } diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff index cf850351c1d62..9d58d7f284b81 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.32bit.diff @@ -36,10 +36,10 @@ StorageDead(_3); - _1 = move _2; + StorageLive(_4); -+ _4 = const [2_usize, 8197_usize]; ++ _4 = no_retag const [2_usize, 8197_usize]; + _5 = discriminant(_2); + _6 = copy _5 as usize (IntToInt); -+ _7 = copy _4[_6]; ++ _7 = no_retag copy _4[_6]; + _8 = &raw mut _1; + _9 = copy _8 as *mut u8 (PtrToPtr); + _10 = &raw const _2; @@ -50,10 +50,10 @@ StorageDead(_2); - _0 = move _1; + StorageLive(_12); -+ _12 = const [2_usize, 8197_usize]; ++ _12 = no_retag const [2_usize, 8197_usize]; + _13 = discriminant(_1); + _14 = copy _13 as usize (IntToInt); -+ _15 = copy _12[_14]; ++ _15 = no_retag copy _12[_14]; + _16 = &raw mut _0; + _17 = copy _16 as *mut u8 (PtrToPtr); + _18 = &raw const _1; diff --git a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff index dc5ea1add0005..95fb2b06c95f6 100644 --- a/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.cand.EnumSizeOpt.64bit.diff @@ -36,10 +36,10 @@ StorageDead(_3); - _1 = move _2; + StorageLive(_4); -+ _4 = const [2_usize, 8197_usize]; ++ _4 = no_retag const [2_usize, 8197_usize]; + _5 = discriminant(_2); + _6 = copy _5 as usize (IntToInt); -+ _7 = copy _4[_6]; ++ _7 = no_retag copy _4[_6]; + _8 = &raw mut _1; + _9 = copy _8 as *mut u8 (PtrToPtr); + _10 = &raw const _2; @@ -50,10 +50,10 @@ StorageDead(_2); - _0 = move _1; + StorageLive(_12); -+ _12 = const [2_usize, 8197_usize]; ++ _12 = no_retag const [2_usize, 8197_usize]; + _13 = discriminant(_1); + _14 = copy _13 as usize (IntToInt); -+ _15 = copy _12[_14]; ++ _15 = no_retag copy _12[_14]; + _16 = &raw mut _0; + _17 = copy _16 as *mut u8 (PtrToPtr); + _18 = &raw const _1; diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff index 3cd2e74a0db6f..3b34039ab1696 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.32bit.diff @@ -36,10 +36,10 @@ StorageDead(_3); - _1 = move _2; + StorageLive(_4); -+ _4 = const [8197_usize, 1_usize]; ++ _4 = no_retag const [8197_usize, 1_usize]; + _5 = discriminant(_2); + _6 = copy _5 as usize (IntToInt); -+ _7 = copy _4[_6]; ++ _7 = no_retag copy _4[_6]; + _8 = &raw mut _1; + _9 = copy _8 as *mut u8 (PtrToPtr); + _10 = &raw const _2; @@ -50,10 +50,10 @@ StorageDead(_2); - _0 = move _1; + StorageLive(_12); -+ _12 = const [8197_usize, 1_usize]; ++ _12 = no_retag const [8197_usize, 1_usize]; + _13 = discriminant(_1); + _14 = copy _13 as usize (IntToInt); -+ _15 = copy _12[_14]; ++ _15 = no_retag copy _12[_14]; + _16 = &raw mut _0; + _17 = copy _16 as *mut u8 (PtrToPtr); + _18 = &raw const _1; diff --git a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff index 10b0ec5a63fa4..68e0bb4b0f859 100644 --- a/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff +++ b/tests/mir-opt/enum_opt.unin.EnumSizeOpt.64bit.diff @@ -36,10 +36,10 @@ StorageDead(_3); - _1 = move _2; + StorageLive(_4); -+ _4 = const [8197_usize, 1_usize]; ++ _4 = no_retag const [8197_usize, 1_usize]; + _5 = discriminant(_2); + _6 = copy _5 as usize (IntToInt); -+ _7 = copy _4[_6]; ++ _7 = no_retag copy _4[_6]; + _8 = &raw mut _1; + _9 = copy _8 as *mut u8 (PtrToPtr); + _10 = &raw const _2; @@ -50,10 +50,10 @@ StorageDead(_2); - _0 = move _1; + StorageLive(_12); -+ _12 = const [8197_usize, 1_usize]; ++ _12 = no_retag const [8197_usize, 1_usize]; + _13 = discriminant(_1); + _14 = copy _13 as usize (IntToInt); -+ _15 = copy _12[_14]; ++ _15 = no_retag copy _12[_14]; + _16 = &raw mut _0; + _17 = copy _16 as *mut u8 (PtrToPtr); + _18 = &raw const _1; diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff index 22b62171d4cb6..1f7cd453b1120 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff @@ -82,7 +82,7 @@ + nop; _8 = copy ((_6 as Some).0: usize); StorageLive(_9); - _9 = copy _1; + _9 = no_retag copy _1; StorageLive(_10); _10 = copy _2; StorageLive(_11); @@ -115,7 +115,7 @@ bb6: { StorageLive(_16); - _16 = copy _1; + _16 = no_retag copy _1; StorageLive(_17); _17 = copy _2; StorageLive(_18); diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff index e58545fa9fcc1..f5b40c72b8790 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff @@ -82,7 +82,7 @@ + nop; _8 = copy ((_6 as Some).0: usize); StorageLive(_9); - _9 = copy _1; + _9 = no_retag copy _1; StorageLive(_10); _10 = copy _2; StorageLive(_11); @@ -115,7 +115,7 @@ bb6: { StorageLive(_16); - _16 = copy _1; + _16 = no_retag copy _1; StorageLive(_17); _17 = copy _2; StorageLive(_18); diff --git a/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff index 2eeeff56cc778..ddce439f19a48 100644 --- a/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff +++ b/tests/mir-opt/gvn_copy_aggregate.all_copy_2.GVN.diff @@ -26,15 +26,15 @@ bb0: { - StorageLive(_2); + nop; - _8 = copy (*_1); + _8 = no_retag copy (*_1); _2 = copy ((*_8).0: i32); - StorageLive(_3); + nop; - _9 = copy (*_1); + _9 = no_retag copy (*_1); _3 = copy ((*_9).1: u64); - StorageLive(_4); + nop; - _10 = copy (*_1); + _10 = no_retag copy (*_1); _4 = copy ((*_10).2: [i8; 3]); StorageLive(_5); _5 = copy _2; diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff index 50136ae8766b2..469d2ef000c5c 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff @@ -22,7 +22,7 @@ + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); -+ _7 = copy (((*_3).0: std::ptr::Unique>).0: std::ptr::NonNull>); ++ _7 = no_retag copy (((*_3).0: std::ptr::Unique>).0: std::ptr::NonNull>); + _6 = copy _7 as *const dyn std::ops::FnMut (Transmute); + _5 = &mut (*_6); + _0 = as FnMut>::call_mut(move _5, move _4) -> [return: bb4, unwind: bb2]; diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff index 3b18052616e2f..bb24c02f3578b 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff @@ -23,7 +23,7 @@ + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); -+ _7 = copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); ++ _7 = no_retag copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); + _6 = copy _7 as *const dyn std::ops::Fn(i32) (Transmute); + _5 = &(*_6); + _2 = >::call(move _5, move _4) -> [return: bb4, unwind: bb2]; diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index 17e6e39a86bc7..38d9fc4cfd567 100644 --- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -41,10 +41,10 @@ fn foo(_1: T, _2: i32) -> (i32, T) { StorageLive(_10); StorageLive(_12); StorageLive(_11); - _10 = copy ((*_6).0: &i32); + _10 = no_retag copy ((*_6).0: &i32); _11 = copy (*_10); StorageLive(_13); - _12 = copy ((*_6).1: &T); + _12 = no_retag copy ((*_6).1: &T); _13 = copy (*_12); _0 = (move _11, move _13); StorageDead(_13); diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir deleted file mode 100644 index 9a256ea19496a..0000000000000 --- a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ /dev/null @@ -1,59 +0,0 @@ -// MIR for `bar` after Inline - -fn bar() -> bool { - let mut _0: bool; - let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; - let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; - let mut _3: &i32; - let _4: &i32; - let _5: i32; - let mut _6: &i32; - let _7: &i32; - let _8: i32; - scope 1 { - debug f => _1; - let mut _9: &i32; - let mut _10: &i32; - scope 2 (inlined foo) { - debug x => _3; - debug y => _6; - let mut _11: i32; - let mut _12: i32; - } - } - - bb0: { - StorageLive(_1); - _1 = foo; - StorageLive(_2); - _2 = copy _1; - StorageLive(_3); - StorageLive(_4); - _10 = const bar::promoted[1]; - Retag(_10); - _4 = copy _10; - _3 = copy _4; - StorageLive(_6); - StorageLive(_7); - _9 = const bar::promoted[0]; - Retag(_9); - _7 = copy _9; - _6 = copy _7; - Retag(_3); - Retag(_6); - StorageLive(_11); - _11 = copy (*_3); - StorageLive(_12); - _12 = copy (*_6); - _0 = Eq(move _11, move _12); - StorageDead(_12); - StorageDead(_11); - StorageDead(_6); - StorageDead(_3); - StorageDead(_2); - StorageDead(_1); - StorageDead(_7); - StorageDead(_4); - return; - } -} diff --git a/tests/mir-opt/inline/inline_retag.rs b/tests/mir-opt/inline/inline_retag.rs deleted file mode 100644 index 81e636378879d..0000000000000 --- a/tests/mir-opt/inline/inline_retag.rs +++ /dev/null @@ -1,29 +0,0 @@ -//@ compile-flags: -Z span_free_formats -Z mir-emit-retag -C debuginfo=full - -// Tests that MIR inliner fixes up `Retag`'s `fn_entry` flag - -fn main() { - println!("{}", bar()); -} - -// EMIT_MIR inline_retag.bar.Inline.after.mir -fn bar() -> bool { - // CHECK-LABEL: fn bar( - // CHECK: (inlined foo) - // CHECK: debug x => [[x:_.*]]; - // CHECK: debug y => [[y:_.*]]; - // CHECK: bb0: { - // CHECK: Retag - // CHECK: Retag - // CHECK: Retag([[x]]); - // CHECK: Retag([[y]]); - // CHECK: return; - // CHECK-NEXT: } - let f = foo; - f(&1, &-1) -} - -#[inline(always)] -fn foo(x: &i32, y: &i32) -> bool { - *x == *y -} diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir index a48a9a0bb0c46..b28c2b851cc93 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir @@ -14,7 +14,7 @@ fn a(_1: &mut [T]) -> &mut [T] { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = copy _1; + _4 = no_retag copy _1; _3 = copy _4; _2 = copy _3; StorageDead(_4); diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 688e6967c2f85..0445a476c5cc9 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -16,10 +16,10 @@ fn b(_1: &mut Box) -> &mut T { StorageLive(_2); StorageLive(_3); StorageLive(_4); - _4 = copy _1; + _4 = no_retag copy _1; StorageLive(_5); StorageLive(_6); - _6 = copy (((*_4).0: std::ptr::Unique).0: std::ptr::NonNull); + _6 = no_retag copy (((*_4).0: std::ptr::Unique).0: std::ptr::NonNull); _5 = copy _6 as *const T (Transmute); _3 = &mut (*_5); StorageDead(_6); diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index 663741c62fb84..38076dc14b6a1 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -17,7 +17,7 @@ fn d(_1: &Box) -> &T { _3 = copy _1; StorageLive(_4); StorageLive(_5); - _5 = copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); + _5 = no_retag copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); _4 = copy _5 as *const T (Transmute); _2 = &(*_4); StorageDead(_5); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index f4efcc6c8c62f..019f8f70633d5 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -117,7 +117,7 @@ StorageLive(_8); _8 = move _4; StorageLive(_9); - _10 = copy (_1.1: &mut std::task::Context<'_>); + _10 = no_retag copy (_1.1: &mut std::task::Context<'_>); _9 = &mut (*_10); - _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5]; + StorageLive(_16); @@ -208,7 +208,7 @@ + StorageLive(_40); + _40 = &raw mut _19; + _39 = copy _40 as *mut std::pin::helper::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); -+ _37 = copy ((*_39).0: &mut std::future::Ready<()>); ++ _37 = no_retag copy ((*_39).0: &mut std::future::Ready<()>); + StorageDead(_40); + StorageLive(_42); + _42 = Option::<()>::None; diff --git a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff index 71d91fed63075..39330ef808243 100644 --- a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff @@ -231,8 +231,8 @@ _10 = &(*_21); StorageLive(_27); StorageLive(_28); - _27 = copy (*_8); - _28 = copy (*_10); + _27 = no_retag copy (*_8); + _28 = no_retag copy (*_10); StorageLive(_29); StorageLive(_30); StorageLive(_31); @@ -295,8 +295,8 @@ _17 = &(*_20); StorageLive(_47); StorageLive(_48); - _47 = copy (*_15); - _48 = copy (*_17); + _47 = no_retag copy (*_15); + _48 = no_retag copy (*_17); StorageLive(_49); StorageLive(_50); StorageLive(_51); diff --git a/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff index 597d93926f169..bc36a2a11d6e4 100644 --- a/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff @@ -39,12 +39,14 @@ - bb1: { - _2 = const true; - _3 = const false; +- _4 = const false; +- _5 = const true; + StorageLive(_11); -+ _11 = copy _1; ++ _11 = no_retag copy _1; + _2 = Ne(copy _11, const 7_i32); + _3 = Eq(copy _11, const 7_i32); - _4 = const false; - _5 = const true; ++ _4 = no_retag const false; ++ _5 = no_retag const true; _6 = (); - goto -> bb3; - } diff --git a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff index 3ce82fd0d476e..0555e63c09662 100644 --- a/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff @@ -15,7 +15,7 @@ _3 = discriminant(_1); - switchInt(move _3) -> [0: bb2, otherwise: bb1]; + StorageLive(_4); -+ _4 = move _3; ++ _4 = no_retag move _3; + _2 = Eq(copy _4, const 0_isize); + StorageDead(_4); + switchInt(move _2) -> [0: bb2, otherwise: bb1]; diff --git a/tests/mir-opt/matches_reduce_branches.match_eq_bool.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_eq_bool.MatchBranchSimplification.diff index a896f66866e62..76c93158ea046 100644 --- a/tests/mir-opt/matches_reduce_branches.match_eq_bool.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_eq_bool.MatchBranchSimplification.diff @@ -20,7 +20,7 @@ - bb1: { - _2 = const true; + StorageLive(_4); -+ _4 = copy _1; ++ _4 = no_retag copy _1; + _2 = Ne(copy _4, const 7_i32); _3 = (); - goto -> bb4; diff --git a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff index cc7e863d13546..d20bd1ccced0f 100644 --- a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff @@ -38,7 +38,7 @@ - - bb6: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as u128 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff index e9143ef1636e6..d3d8d3b1ce0b6 100644 --- a/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff @@ -45,11 +45,11 @@ - - bb4: { + StorageLive(_7); -+ _7 = move _6; ++ _7 = no_retag move _6; + _5 = Ne(copy _7, const false); + StorageDead(_7); + StorageLive(_8); -+ _8 = move _5; ++ _8 = no_retag move _5; StorageDead(_6); - _4 = const true; - goto -> bb6; @@ -69,7 +69,7 @@ + _4 = Ne(copy _8, const false); + StorageDead(_8); + StorageLive(_9); -+ _9 = move _4; ++ _9 = no_retag move _4; StorageDead(_5); - _3 = const true; - goto -> bb9; @@ -89,7 +89,7 @@ + _3 = Ne(copy _9, const false); + StorageDead(_9); + StorageLive(_10); -+ _10 = move _3; ++ _10 = no_retag move _3; StorageDead(_4); StorageDead(_3); - _1 = const true; diff --git a/tests/mir-opt/matches_reduce_branches.match_option.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_option.MatchBranchSimplification.diff index 76148eb9bd436..ff524ec9026f1 100644 --- a/tests/mir-opt/matches_reduce_branches.match_option.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_option.MatchBranchSimplification.diff @@ -21,11 +21,12 @@ - } - - bb3: { - _0 = copy (*_1); +- _0 = copy (*_1); - goto -> bb4; - } - - bb4: { ++ _0 = no_retag copy (*_1); return; } } diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff index dbd26adc20f93..55252ed91610f 100644 --- a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff @@ -43,7 +43,7 @@ - - bb7: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as i16 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff index f273d5388350e..0752b9f987bfc 100644 --- a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff @@ -43,7 +43,7 @@ - - bb7: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as u16 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff index 6170cf13c0021..3e8487e588c65 100644 --- a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff @@ -68,7 +68,7 @@ - - bb12: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as i8 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff index c18719ebb55eb..5d2b2d72a86c4 100644 --- a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff @@ -68,7 +68,7 @@ - - bb12: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as u8 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff index 401049026f27b..171b691d04505 100644 --- a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff @@ -58,7 +58,7 @@ - - bb10: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as i8 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff index d4dafbd886fcb..900613cfe6eae 100644 --- a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff @@ -58,7 +58,7 @@ - - bb10: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as u8 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff index 5ab6f5eac84aa..fcc750e7f87f7 100644 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff @@ -38,7 +38,7 @@ - - bb6: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as i8 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff index f14b3af9660aa..386cb18ee69cc 100644 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff @@ -34,7 +34,7 @@ - _2 = const -1_i8; - _3 = const -1_i8; + StorageLive(_8); -+ _8 = move _5; ++ _8 = no_retag move _5; + _2 = copy _8 as i8 (IntToInt); + _3 = copy _8 as i8 (IntToInt); _4 = (); diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff index fdf83d91bbd38..b23e0f314b7a9 100644 --- a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff @@ -38,7 +38,7 @@ - - bb6: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as i16 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff index a888d247275fd..0e1bd57355bb4 100644 --- a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff @@ -38,7 +38,7 @@ - - bb6: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as u16 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.my_is_some.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.my_is_some.MatchBranchSimplification.diff index d255278ed300a..3cc43abccba45 100644 --- a/tests/mir-opt/matches_reduce_branches.my_is_some.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.my_is_some.MatchBranchSimplification.diff @@ -28,7 +28,7 @@ - - bb4: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = Ne(copy _3, const 0_isize); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs index 1766e77cf664b..b8caeddf4f4f0 100644 --- a/tests/mir-opt/matches_reduce_branches.rs +++ b/tests/mir-opt/matches_reduce_branches.rs @@ -679,7 +679,7 @@ fn match_i128_u128(i: EnumAi128) -> u128 { fn match_option(i: &Option) -> Option { // CHECK-LABEL: fn match_option( // CHECK-NOT: switchInt - // CHECK: _0 = copy (*_1); + // CHECK: _0 = no_retag copy (*_1); match i { Some(_) => *i, None => None, diff --git a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff index 99985b28382f5..fe7993c141edb 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff @@ -28,7 +28,7 @@ - - bb4: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as u8 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff index 0fc5032691fed..1f7f7fec630e2 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff @@ -28,7 +28,7 @@ - - bb4: { + StorageLive(_3); -+ _3 = move _2; ++ _3 = no_retag move _2; + _0 = copy _3 as i8 (IntToInt); + StorageDead(_3); return; diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs index 23ad0189a66de..17a873a1c05e7 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.rs +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.rs @@ -4,7 +4,7 @@ fn src(x: &&u8) -> bool { // CHECK-LABEL: fn src( // CHECK: debug y => [[Y:_.*]]; // CHECK: bb0: - // CHECK: [[BORROW_u8:_.*]] = copy (*_1); + // CHECK: [[BORROW_u8:_.*]] = no_retag copy (*_1); // CHECK: [[Y]] = copy (*[[BORROW_u8]]); // CHECK: bb1: // BORROW_u8 outside its lifetime in bb1. diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff index 9ce17342a445c..191059365f52f 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.GVN.panic-unwind.diff @@ -17,14 +17,14 @@ bb0: { - StorageLive(_2); + nop; - _6 = copy (*_1); + _6 = no_retag copy (*_1); _2 = copy (*_6); _3 = unknown() -> [return: bb1, unwind continue]; } bb1: { StorageLive(_4); - _7 = copy (*_1); + _7 = no_retag copy (*_1); _4 = copy (*_7); StorageLive(_5); _5 = copy _2; diff --git a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir index 4c01e9464bf49..20b96a320b16d 100644 --- a/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/deref_nested_borrows.src.PreCodegen.after.panic-unwind.mir @@ -13,14 +13,14 @@ fn src(_1: &&u8) -> bool { } bb0: { - _2 = copy (*_1); + _2 = no_retag copy (*_1); _3 = copy (*_2); _4 = unknown() -> [return: bb1, unwind continue]; } bb1: { StorageLive(_6); - _5 = copy (*_1); + _5 = no_retag copy (*_1); _6 = copy (*_5); _0 = Eq(move _6, copy _3); StorageDead(_6); diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index afac0d23115e6..690325d87936d 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -67,13 +67,13 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2 } bb0: { - _3 = copy (*_2); + _3 = no_retag copy (*_2); // DBG: _16 = &((*_3).0: usize); - _4 = copy (*_2); + _4 = no_retag copy (*_2); // DBG: _17 = &((*_4).1: usize); - _5 = copy (*_2); + _5 = no_retag copy (*_2); // DBG: _18 = &((*_5).2: usize); - _6 = copy (*_2); + _6 = no_retag copy (*_2); // DBG: _19 = &((*_6).3: usize); StorageLive(_9); // DBG: _20 = &_16; diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir index f93f7264dec20..afb64c08c1f94 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir @@ -21,13 +21,13 @@ fn variant_b::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:11:25: 11:41}, } bb0: { - _3 = copy (*_2); + _3 = no_retag copy (*_2); _4 = copy ((*_3).0: usize); - _5 = copy (*_2); + _5 = no_retag copy (*_2); _6 = copy ((*_5).1: usize); - _7 = copy (*_2); + _7 = no_retag copy (*_2); _8 = copy ((*_7).2: usize); - _9 = copy (*_2); + _9 = no_retag copy (*_2); _10 = copy ((*_9).3: usize); StorageLive(_11); _11 = Le(copy _4, copy _8); diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir deleted file mode 100644 index 910983ee79d35..0000000000000 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ /dev/null @@ -1,169 +0,0 @@ -// MIR for `array_casts` after SimplifyCfg-pre-optimizations - -fn array_casts() -> () { - let mut _0: (); - let mut _1: [usize; 2]; - let mut _3: *mut [usize; 2]; - let mut _4: &mut [usize; 2]; - let _5: (); - let mut _6: *mut usize; - let mut _7: *mut usize; - let mut _10: *const [usize; 2]; - let _11: &[usize; 2]; - let _12: (); - let mut _13: (&usize, &usize); - let mut _14: &usize; - let _15: usize; - let mut _16: *const usize; - let mut _17: *const usize; - let mut _18: &usize; - let _19: usize; - let mut _22: bool; - let mut _23: usize; - let mut _24: usize; - let mut _25: !; - let _27: !; - let mut _28: core::panicking::AssertKind; - let mut _29: &usize; - let _30: &usize; - let mut _31: &usize; - let _32: &usize; - let mut _33: std::option::Option>; - scope 1 { - debug x => _1; - let _2: *mut usize; - scope 2 { - debug p => _2; - let _8: [usize; 2]; - scope 3 { - debug x => _8; - let _9: *const usize; - scope 4 { - debug p => _9; - let _20: &usize; - let _21: &usize; - let mut _34: &usize; - scope 5 { - debug left_val => _20; - debug right_val => _21; - let _26: core::panicking::AssertKind; - scope 6 { - debug kind => _26; - } - } - } - } - } - } - - bb0: { - StorageLive(_1); - _1 = [const 0_usize, const 0_usize]; - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - _4 = &mut _1; - _3 = &raw mut (*_4); - _2 = move _3 as *mut usize (PtrToPtr); - StorageDead(_3); - StorageDead(_4); - StorageLive(_5); - StorageLive(_6); - StorageLive(_7); - _7 = copy _2; - _6 = std::ptr::mut_ptr::::add(move _7, const 1_usize) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_7); - (*_6) = const 1_usize; - StorageDead(_6); - _5 = const (); - StorageDead(_5); - StorageLive(_8); - _8 = [const 0_usize, const 1_usize]; - StorageLive(_9); - StorageLive(_10); - StorageLive(_11); - _11 = &_8; - _10 = &raw const (*_11); - _9 = move _10 as *const usize (PtrToPtr); - StorageDead(_10); - StorageDead(_11); - StorageLive(_12); - StorageLive(_13); - StorageLive(_14); - StorageLive(_15); - StorageLive(_16); - StorageLive(_17); - _17 = copy _9; - _16 = std::ptr::const_ptr::::add(move _17, const 1_usize) -> [return: bb2, unwind unreachable]; - } - - bb2: { - StorageDead(_17); - _15 = copy (*_16); - _14 = &_15; - StorageLive(_18); - _34 = const array_casts::promoted[0]; - Retag(_34); - _18 = &(*_34); - _13 = (move _14, move _18); - Retag(_13); - StorageDead(_18); - StorageDead(_14); - StorageLive(_20); - _20 = copy (_13.0: &usize); - Retag(_20); - StorageLive(_21); - _21 = copy (_13.1: &usize); - Retag(_21); - StorageLive(_22); - StorageLive(_23); - _23 = copy (*_20); - StorageLive(_24); - _24 = copy (*_21); - _22 = Eq(move _23, move _24); - switchInt(move _22) -> [0: bb4, otherwise: bb3]; - } - - bb3: { - StorageDead(_24); - StorageDead(_23); - _12 = const (); - StorageDead(_22); - StorageDead(_21); - StorageDead(_20); - StorageDead(_16); - StorageDead(_15); - StorageDead(_13); - StorageDead(_12); - _0 = const (); - StorageDead(_9); - StorageDead(_8); - StorageDead(_2); - StorageDead(_1); - return; - } - - bb4: { - StorageDead(_24); - StorageDead(_23); - StorageLive(_26); - _26 = core::panicking::AssertKind::Eq; - StorageLive(_27); - StorageLive(_28); - _28 = move _26; - StorageLive(_29); - StorageLive(_30); - _30 = &(*_20); - _29 = &(*_30); - StorageLive(_31); - StorageLive(_32); - _32 = &(*_21); - _31 = &(*_32); - StorageLive(_33); - _33 = Option::>::None; - _27 = core::panicking::assert_failed::(move _28, move _29, move _31, move _33) -> unwind unreachable; - } -} diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir deleted file mode 100644 index 8cc6bce0e6bd4..0000000000000 --- a/tests/mir-opt/retag.array_casts.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ /dev/null @@ -1,169 +0,0 @@ -// MIR for `array_casts` after SimplifyCfg-pre-optimizations - -fn array_casts() -> () { - let mut _0: (); - let mut _1: [usize; 2]; - let mut _3: *mut [usize; 2]; - let mut _4: &mut [usize; 2]; - let _5: (); - let mut _6: *mut usize; - let mut _7: *mut usize; - let mut _10: *const [usize; 2]; - let _11: &[usize; 2]; - let _12: (); - let mut _13: (&usize, &usize); - let mut _14: &usize; - let _15: usize; - let mut _16: *const usize; - let mut _17: *const usize; - let mut _18: &usize; - let _19: usize; - let mut _22: bool; - let mut _23: usize; - let mut _24: usize; - let mut _25: !; - let _27: !; - let mut _28: core::panicking::AssertKind; - let mut _29: &usize; - let _30: &usize; - let mut _31: &usize; - let _32: &usize; - let mut _33: std::option::Option>; - scope 1 { - debug x => _1; - let _2: *mut usize; - scope 2 { - debug p => _2; - let _8: [usize; 2]; - scope 3 { - debug x => _8; - let _9: *const usize; - scope 4 { - debug p => _9; - let _20: &usize; - let _21: &usize; - let mut _34: &usize; - scope 5 { - debug left_val => _20; - debug right_val => _21; - let _26: core::panicking::AssertKind; - scope 6 { - debug kind => _26; - } - } - } - } - } - } - - bb0: { - StorageLive(_1); - _1 = [const 0_usize, const 0_usize]; - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - _4 = &mut _1; - _3 = &raw mut (*_4); - _2 = move _3 as *mut usize (PtrToPtr); - StorageDead(_3); - StorageDead(_4); - StorageLive(_5); - StorageLive(_6); - StorageLive(_7); - _7 = copy _2; - _6 = std::ptr::mut_ptr::::add(move _7, const 1_usize) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageDead(_7); - (*_6) = const 1_usize; - StorageDead(_6); - _5 = const (); - StorageDead(_5); - StorageLive(_8); - _8 = [const 0_usize, const 1_usize]; - StorageLive(_9); - StorageLive(_10); - StorageLive(_11); - _11 = &_8; - _10 = &raw const (*_11); - _9 = move _10 as *const usize (PtrToPtr); - StorageDead(_10); - StorageDead(_11); - StorageLive(_12); - StorageLive(_13); - StorageLive(_14); - StorageLive(_15); - StorageLive(_16); - StorageLive(_17); - _17 = copy _9; - _16 = std::ptr::const_ptr::::add(move _17, const 1_usize) -> [return: bb2, unwind continue]; - } - - bb2: { - StorageDead(_17); - _15 = copy (*_16); - _14 = &_15; - StorageLive(_18); - _34 = const array_casts::promoted[0]; - Retag(_34); - _18 = &(*_34); - _13 = (move _14, move _18); - Retag(_13); - StorageDead(_18); - StorageDead(_14); - StorageLive(_20); - _20 = copy (_13.0: &usize); - Retag(_20); - StorageLive(_21); - _21 = copy (_13.1: &usize); - Retag(_21); - StorageLive(_22); - StorageLive(_23); - _23 = copy (*_20); - StorageLive(_24); - _24 = copy (*_21); - _22 = Eq(move _23, move _24); - switchInt(move _22) -> [0: bb4, otherwise: bb3]; - } - - bb3: { - StorageDead(_24); - StorageDead(_23); - _12 = const (); - StorageDead(_22); - StorageDead(_21); - StorageDead(_20); - StorageDead(_16); - StorageDead(_15); - StorageDead(_13); - StorageDead(_12); - _0 = const (); - StorageDead(_9); - StorageDead(_8); - StorageDead(_2); - StorageDead(_1); - return; - } - - bb4: { - StorageDead(_24); - StorageDead(_23); - StorageLive(_26); - _26 = core::panicking::AssertKind::Eq; - StorageLive(_27); - StorageLive(_28); - _28 = move _26; - StorageLive(_29); - StorageLive(_30); - _30 = &(*_20); - _29 = &(*_30); - StorageLive(_31); - StorageLive(_32); - _32 = &(*_21); - _31 = &(*_32); - StorageLive(_33); - _33 = Option::>::None; - _27 = core::panicking::assert_failed::(move _28, move _29, move _31, move _33) -> unwind continue; - } -} diff --git a/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-abort.mir deleted file mode 100644 index 4861abead2f32..0000000000000 --- a/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ /dev/null @@ -1,17 +0,0 @@ -// MIR for `box_to_raw_mut` after SimplifyCfg-pre-optimizations - -fn box_to_raw_mut(_1: &mut Box) -> *mut i32 { - debug x => _1; - let mut _0: *mut i32; - let mut _2: std::boxed::Box; - let mut _3: *const i32; - - bb0: { - Retag([fn entry] _1); - _2 = copy (*_1); - _3 = copy ((_2.0: std::ptr::Unique).0: std::ptr::NonNull) as *const i32 (Transmute); - _0 = &raw mut (*_3); - Retag([raw] _0); - return; - } -} diff --git a/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-unwind.mir deleted file mode 100644 index 4861abead2f32..0000000000000 --- a/tests/mir-opt/retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ /dev/null @@ -1,17 +0,0 @@ -// MIR for `box_to_raw_mut` after SimplifyCfg-pre-optimizations - -fn box_to_raw_mut(_1: &mut Box) -> *mut i32 { - debug x => _1; - let mut _0: *mut i32; - let mut _2: std::boxed::Box; - let mut _3: *const i32; - - bb0: { - Retag([fn entry] _1); - _2 = copy (*_1); - _3 = copy ((_2.0: std::ptr::Unique).0: std::ptr::NonNull) as *const i32 (Transmute); - _0 = &raw mut (*_3); - Retag([raw] _0); - return; - } -} diff --git a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir deleted file mode 100644 index 8e47aabb9b9f3..0000000000000 --- a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir +++ /dev/null @@ -1,23 +0,0 @@ -// MIR for `std::ptr::drop_in_place` after SimplifyCfg-make_shim - -fn drop_in_place(_1: *mut Test) -> () { - let mut _0: (); - let mut _2: &mut Test; - let mut _3: &mut Test; - let mut _4: (); - - bb0: { - _2 = &mut (*_1); - Retag([fn entry] _2); - _3 = &mut (*_2); - _4 = ::drop(move _3) -> [return: bb2, unwind: bb1]; - } - - bb1 (cleanup): { - resume; - } - - bb2: { - return; - } -} diff --git a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir deleted file mode 100644 index 2457405d9969a..0000000000000 --- a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir +++ /dev/null @@ -1,19 +0,0 @@ -// MIR for `std::ptr::drop_in_place` after SimplifyCfg-make_shim - -fn drop_in_place(_1: *mut Test) -> () { - let mut _0: (); - let mut _2: &mut Test; - let mut _3: &mut Test; - let mut _4: (); - - bb0: { - _2 = &mut (*_1); - Retag([fn entry] _2); - _3 = &mut (*_2); - _4 = ::drop(move _3) -> [return: bb1, unwind continue]; - } - - bb1: { - return; - } -} diff --git a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-abort.mir deleted file mode 100644 index 63b32ceb5c059..0000000000000 --- a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ /dev/null @@ -1,21 +0,0 @@ -// MIR for `main::{closure#0}` after SimplifyCfg-pre-optimizations - -fn main::{closure#0}(_1: &{closure@main::{closure#0}}, _2: &i32) -> &i32 { - debug x => _2; - let mut _0: &i32; - let _3: &i32; - scope 1 { - debug _y => _3; - } - - bb0: { - Retag([fn entry] _1); - Retag([fn entry] _2); - StorageLive(_3); - _3 = copy _2; - Retag(_3); - _0 = &(*_2); - StorageDead(_3); - return; - } -} diff --git a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-unwind.mir deleted file mode 100644 index 63b32ceb5c059..0000000000000 --- a/tests/mir-opt/retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ /dev/null @@ -1,21 +0,0 @@ -// MIR for `main::{closure#0}` after SimplifyCfg-pre-optimizations - -fn main::{closure#0}(_1: &{closure@main::{closure#0}}, _2: &i32) -> &i32 { - debug x => _2; - let mut _0: &i32; - let _3: &i32; - scope 1 { - debug _y => _3; - } - - bb0: { - Retag([fn entry] _1); - Retag([fn entry] _2); - StorageLive(_3); - _3 = copy _2; - Retag(_3); - _0 = &(*_2); - StorageDead(_3); - return; - } -} diff --git a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir deleted file mode 100644 index cca2b3ae188c3..0000000000000 --- a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ /dev/null @@ -1,168 +0,0 @@ -// MIR for `main` after SimplifyCfg-pre-optimizations - -fn main() -> () { - let mut _0: (); - let mut _1: i32; - let _2: (); - let mut _4: &Test; - let _5: Test; - let mut _6: &mut i32; - let mut _7: &mut i32; - let mut _9: &mut i32; - let mut _12: *mut i32; - let mut _14: {closure@main::{closure#0}}; - let mut _16: for<'a> fn(&'a i32) -> &'a i32; - let mut _17: &i32; - let _18: &i32; - let _19: &i32; - let mut _20: &Test; - let _21: Test; - let mut _22: &i32; - let _23: &i32; - let _24: i32; - let mut _26: *const i32; - let _27: (); - scope 1 { - debug x => _1; - let _3: &mut i32; - let _13: for<'a> fn(&'a i32) -> &'a i32; - scope 2 { - debug v => _3; - let _8: &mut i32; - scope 3 { - debug w => _8; - let _10: &mut i32; - scope 4 { - debug w => _10; - let _11: *mut i32; - scope 5 { - debug _w => _11; - } - } - } - } - scope 6 { - debug c => _13; - let _15: &i32; - scope 7 { - debug _w => _15; - let _25: *const i32; - let mut _28: &i32; - scope 8 { - debug _w => _25; - } - } - } - } - - bb0: { - StorageLive(_1); - _1 = const 0_i32; - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); - _5 = Test(const 0_i32); - _4 = &_5; - StorageLive(_6); - StorageLive(_7); - _7 = &mut _1; - _6 = &mut (*_7); - _3 = Test::foo(move _4, move _6) -> [return: bb1, unwind unreachable]; - } - - bb1: { - Retag(_3); - StorageDead(_6); - StorageDead(_4); - StorageDead(_7); - drop(_5) -> [return: bb2, unwind unreachable]; - } - - bb2: { - StorageDead(_5); - StorageLive(_8); - StorageLive(_9); - _9 = move _3; - Retag(_9); - _8 = &mut (*_9); - StorageDead(_9); - StorageLive(_10); - _10 = move _8; - Retag(_10); - StorageLive(_11); - StorageLive(_12); - _12 = &raw mut (*_10); - _11 = copy _12; - StorageDead(_12); - _2 = const (); - StorageDead(_11); - StorageDead(_10); - StorageDead(_8); - StorageDead(_3); - StorageDead(_2); - StorageLive(_13); - StorageLive(_14); - _14 = {closure@main::{closure#0}}; - Retag(_14); - _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Safe), Implicit)); - StorageDead(_14); - StorageLive(_15); - StorageLive(_16); - _16 = copy _13; - StorageLive(_17); - StorageLive(_18); - _18 = &_1; - _17 = &(*_18); - _15 = move _16(move _17) -> [return: bb3, unwind unreachable]; - } - - bb3: { - Retag(_15); - StorageDead(_17); - StorageDead(_16); - StorageDead(_18); - StorageLive(_19); - StorageLive(_20); - StorageLive(_21); - _21 = Test(const 0_i32); - _20 = &_21; - StorageLive(_22); - StorageLive(_23); - _28 = const main::promoted[0]; - Retag(_28); - _23 = &(*_28); - _22 = &(*_23); - _19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind unreachable]; - } - - bb4: { - Retag(_19); - StorageDead(_22); - StorageDead(_20); - StorageDead(_23); - drop(_21) -> [return: bb5, unwind unreachable]; - } - - bb5: { - StorageDead(_21); - StorageDead(_19); - StorageLive(_25); - StorageLive(_26); - _26 = &raw const (*_15); - _25 = copy _26; - StorageDead(_26); - StorageLive(_27); - _27 = array_casts() -> [return: bb6, unwind unreachable]; - } - - bb6: { - StorageDead(_27); - _0 = const (); - StorageDead(_25); - StorageDead(_15); - StorageDead(_13); - StorageDead(_1); - return; - } -} diff --git a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir deleted file mode 100644 index bcd3a47ac04fb..0000000000000 --- a/tests/mir-opt/retag.main.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ /dev/null @@ -1,180 +0,0 @@ -// MIR for `main` after SimplifyCfg-pre-optimizations - -fn main() -> () { - let mut _0: (); - let mut _1: i32; - let _2: (); - let mut _4: &Test; - let _5: Test; - let mut _6: &mut i32; - let mut _7: &mut i32; - let mut _9: &mut i32; - let mut _12: *mut i32; - let mut _14: {closure@main::{closure#0}}; - let mut _16: for<'a> fn(&'a i32) -> &'a i32; - let mut _17: &i32; - let _18: &i32; - let _19: &i32; - let mut _20: &Test; - let _21: Test; - let mut _22: &i32; - let _23: &i32; - let _24: i32; - let mut _26: *const i32; - let _27: (); - scope 1 { - debug x => _1; - let _3: &mut i32; - let _13: for<'a> fn(&'a i32) -> &'a i32; - scope 2 { - debug v => _3; - let _8: &mut i32; - scope 3 { - debug w => _8; - let _10: &mut i32; - scope 4 { - debug w => _10; - let _11: *mut i32; - scope 5 { - debug _w => _11; - } - } - } - } - scope 6 { - debug c => _13; - let _15: &i32; - scope 7 { - debug _w => _15; - let _25: *const i32; - let mut _28: &i32; - scope 8 { - debug _w => _25; - } - } - } - } - - bb0: { - StorageLive(_1); - _1 = const 0_i32; - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); - _5 = Test(const 0_i32); - _4 = &_5; - StorageLive(_6); - StorageLive(_7); - _7 = &mut _1; - _6 = &mut (*_7); - _3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; - } - - bb1: { - Retag(_3); - StorageDead(_6); - StorageDead(_4); - StorageDead(_7); - drop(_5) -> [return: bb2, unwind: bb9]; - } - - bb2: { - StorageDead(_5); - StorageLive(_8); - StorageLive(_9); - _9 = move _3; - Retag(_9); - _8 = &mut (*_9); - StorageDead(_9); - StorageLive(_10); - _10 = move _8; - Retag(_10); - StorageLive(_11); - StorageLive(_12); - _12 = &raw mut (*_10); - _11 = copy _12; - StorageDead(_12); - _2 = const (); - StorageDead(_11); - StorageDead(_10); - StorageDead(_8); - StorageDead(_3); - StorageDead(_2); - StorageLive(_13); - StorageLive(_14); - _14 = {closure@main::{closure#0}}; - Retag(_14); - _13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (PointerCoercion(ClosureFnPointer(Safe), Implicit)); - StorageDead(_14); - StorageLive(_15); - StorageLive(_16); - _16 = copy _13; - StorageLive(_17); - StorageLive(_18); - _18 = &_1; - _17 = &(*_18); - _15 = move _16(move _17) -> [return: bb3, unwind continue]; - } - - bb3: { - Retag(_15); - StorageDead(_17); - StorageDead(_16); - StorageDead(_18); - StorageLive(_19); - StorageLive(_20); - StorageLive(_21); - _21 = Test(const 0_i32); - _20 = &_21; - StorageLive(_22); - StorageLive(_23); - _28 = const main::promoted[0]; - Retag(_28); - _23 = &(*_28); - _22 = &(*_23); - _19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; - } - - bb4: { - Retag(_19); - StorageDead(_22); - StorageDead(_20); - StorageDead(_23); - drop(_21) -> [return: bb5, unwind: bb9]; - } - - bb5: { - StorageDead(_21); - StorageDead(_19); - StorageLive(_25); - StorageLive(_26); - _26 = &raw const (*_15); - _25 = copy _26; - StorageDead(_26); - StorageLive(_27); - _27 = array_casts() -> [return: bb6, unwind continue]; - } - - bb6: { - StorageDead(_27); - _0 = const (); - StorageDead(_25); - StorageDead(_15); - StorageDead(_13); - StorageDead(_1); - return; - } - - bb7 (cleanup): { - drop(_21) -> [return: bb9, unwind terminate(cleanup)]; - } - - bb8 (cleanup): { - drop(_5) -> [return: bb9, unwind terminate(cleanup)]; - } - - bb9 (cleanup): { - resume; - } -} diff --git a/tests/mir-opt/retag.rs b/tests/mir-opt/retag.rs deleted file mode 100644 index 001c559913839..0000000000000 --- a/tests/mir-opt/retag.rs +++ /dev/null @@ -1,74 +0,0 @@ -// skip-filecheck -//@ test-mir-pass: AddRetag -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// ignore-tidy-linelength -//@ compile-flags: -Z mir-emit-retag -Z mir-opt-level=0 -Z span_free_formats - -#![allow(unused)] - -struct Test(i32); - -// EMIT_MIR retag.{impl#0}-foo.SimplifyCfg-pre-optimizations.after.mir -// EMIT_MIR retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.mir -impl Test { - // Make sure we run the pass on a method, not just on bare functions. - fn foo<'x>(&self, x: &'x mut i32) -> &'x mut i32 { - x - } - fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 { - x - } -} - -// EMIT_MIR core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir - -impl Drop for Test { - fn drop(&mut self) {} -} - -// EMIT_MIR retag.main.SimplifyCfg-pre-optimizations.after.mir -// EMIT_MIR retag.main-{closure#0}.SimplifyCfg-pre-optimizations.after.mir -pub fn main() { - let mut x = 0; - { - let v = Test(0).foo(&mut x); // just making sure we do not panic when there is a tuple struct ctor - let w = { v }; // assignment - let w = w; // reborrow - // escape-to-raw (mut) - let _w = w as *mut _; - } - - // Also test closures - let c: fn(&i32) -> &i32 = |x: &i32| -> &i32 { - let _y = x; - x - }; - let _w = c(&x); - - // need to call `foo_shr` or it doesn't even get generated - Test(0).foo_shr(&0); - - // escape-to-raw (shr) - let _w = _w as *const _; - - array_casts(); -} - -/// Casting directly to an array should also go through `&raw` and thus add appropriate retags. -// EMIT_MIR retag.array_casts.SimplifyCfg-pre-optimizations.after.mir -fn array_casts() { - let mut x: [usize; 2] = [0, 0]; - let p = &mut x as *mut usize; - unsafe { - *p.add(1) = 1; - } - - let x: [usize; 2] = [0, 1]; - let p = &x as *const usize; - assert_eq!(unsafe { *p.add(1) }, 1); -} - -// EMIT_MIR retag.box_to_raw_mut.SimplifyCfg-pre-optimizations.after.mir -fn box_to_raw_mut(x: &mut Box) -> *mut i32 { - std::ptr::addr_of_mut!(**x) -} diff --git a/tests/mir-opt/retag.{impl#0}-foo.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.{impl#0}-foo.SimplifyCfg-pre-optimizations.after.panic-abort.mir deleted file mode 100644 index b656656919e1f..0000000000000 --- a/tests/mir-opt/retag.{impl#0}-foo.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ /dev/null @@ -1,18 +0,0 @@ -// MIR for `::foo` after SimplifyCfg-pre-optimizations - -fn ::foo(_1: &Test, _2: &mut i32) -> &mut i32 { - debug self => _1; - debug x => _2; - let mut _0: &mut i32; - let mut _3: &mut i32; - - bb0: { - Retag([fn entry] _1); - Retag([fn entry] _2); - StorageLive(_3); - _3 = &mut (*_2); - _0 = &mut (*_3); - StorageDead(_3); - return; - } -} diff --git a/tests/mir-opt/retag.{impl#0}-foo.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.{impl#0}-foo.SimplifyCfg-pre-optimizations.after.panic-unwind.mir deleted file mode 100644 index b656656919e1f..0000000000000 --- a/tests/mir-opt/retag.{impl#0}-foo.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ /dev/null @@ -1,18 +0,0 @@ -// MIR for `::foo` after SimplifyCfg-pre-optimizations - -fn ::foo(_1: &Test, _2: &mut i32) -> &mut i32 { - debug self => _1; - debug x => _2; - let mut _0: &mut i32; - let mut _3: &mut i32; - - bb0: { - Retag([fn entry] _1); - Retag([fn entry] _2); - StorageLive(_3); - _3 = &mut (*_2); - _0 = &mut (*_3); - StorageDead(_3); - return; - } -} diff --git a/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-abort.mir b/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-abort.mir deleted file mode 100644 index b873c5aabbfc3..0000000000000 --- a/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-abort.mir +++ /dev/null @@ -1,15 +0,0 @@ -// MIR for `::foo_shr` after SimplifyCfg-pre-optimizations - -fn ::foo_shr(_1: &Test, _2: &i32) -> &i32 { - debug self => _1; - debug x => _2; - let mut _0: &i32; - - bb0: { - Retag([fn entry] _1); - Retag([fn entry] _2); - _0 = copy _2; - Retag(_0); - return; - } -} diff --git a/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-unwind.mir b/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-unwind.mir deleted file mode 100644 index b873c5aabbfc3..0000000000000 --- a/tests/mir-opt/retag.{impl#0}-foo_shr.SimplifyCfg-pre-optimizations.after.panic-unwind.mir +++ /dev/null @@ -1,15 +0,0 @@ -// MIR for `::foo_shr` after SimplifyCfg-pre-optimizations - -fn ::foo_shr(_1: &Test, _2: &i32) -> &i32 { - debug self => _1; - debug x => _2; - let mut _0: &i32; - - bb0: { - Retag([fn entry] _1); - Retag([fn entry] _2); - _0 = copy _2; - Retag(_0); - return; - } -} diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff index f9965a529ebc6..87340ebf0b90f 100644 --- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff +++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff @@ -115,8 +115,8 @@ StorageLive(_15); StorageLive(_16); StorageLive(_17); -- _24 = copy (_12.0: &std::boxed::Box); -+ _24 = copy _32; +- _24 = no_retag copy (_12.0: &std::boxed::Box); ++ _24 = no_retag copy _32; _17 = &(*_24); _16 = core::fmt::rt::Argument::<'_>::new_display::>(move _17) -> [return: bb3, unwind unreachable]; } @@ -125,8 +125,8 @@ StorageDead(_17); StorageLive(_18); StorageLive(_19); -- _25 = copy (_12.1: &u32); -+ _25 = copy _33; +- _25 = no_retag copy (_12.1: &u32); ++ _25 = no_retag copy _33; _19 = &(*_25); _18 = core::fmt::rt::Argument::<'_>::new_display::(move _19) -> [return: bb4, unwind unreachable]; } diff --git a/tests/ui-fulldeps/rustc_public/check_allocation.rs b/tests/ui-fulldeps/rustc_public/check_allocation.rs index 580ce98329dc7..356ea64729cb7 100644 --- a/tests/ui-fulldeps/rustc_public/check_allocation.rs +++ b/tests/ui-fulldeps/rustc_public/check_allocation.rs @@ -175,7 +175,7 @@ pub fn collect_consts(body: &Body) -> HashMap { .iter() .flat_map(|block| block.statements.iter()) .filter_map(|statement| { - let StatementKind::Assign(place, Rvalue::Use(Operand::Constant(const_op))) = + let StatementKind::Assign(place, Rvalue::Use(Operand::Constant(const_op), _)) = &statement.kind else { return None; diff --git a/tests/ui-fulldeps/rustc_public/check_transform.rs b/tests/ui-fulldeps/rustc_public/check_transform.rs index 000f1f4cb365a..17b9612db3067 100644 --- a/tests/ui-fulldeps/rustc_public/check_transform.rs +++ b/tests/ui-fulldeps/rustc_public/check_transform.rs @@ -61,7 +61,7 @@ fn check_msg(body: &Body, expected: &str) { .find_map(|stmt| match &stmt.kind { StatementKind::Assign( destination, - Rvalue::Use(Operand::Constant(msg_const)), + Rvalue::Use(Operand::Constant(msg_const), _), ) if destination == place => Some(msg_const), _ => None, }) diff --git a/tests/ui-fulldeps/rustc_public/projections.rs b/tests/ui-fulldeps/rustc_public/projections.rs index e864bb9648db5..50bc7467ef3d3 100644 --- a/tests/ui-fulldeps/rustc_public/projections.rs +++ b/tests/ui-fulldeps/rustc_public/projections.rs @@ -73,7 +73,7 @@ fn test_place_projections() -> ControlFlow<()> { Rvalue::Use(rustc_public::mir::Operand::Copy(rustc_public::mir::Place { local: _, projection: r_proj, - })), + }), _), ) => { // We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier // since we'd then have to add in the expected local values instead of matching on diff --git a/tests/ui/rustc_public-ir-print/async-closure.stdout b/tests/ui/rustc_public-ir-print/async-closure.stdout index 8df31e2f680aa..3aca86ae66935 100644 --- a/tests/ui/rustc_public-ir-print/async-closure.stdout +++ b/tests/ui/rustc_public-ir-print/async-closure.stdout @@ -28,7 +28,7 @@ fn foo::{closure#0}(_1: &{async closure@$DIR/async-closure.rs:9:13: 9:21}) -> {a debug y => (*((*_1).0: &i32)); bb0: { StorageLive(_2); - _3 = ((*_1).0: &i32); + _3 = no_retag ((*_1).0: &i32); _2 = &(*_3); _0 = {coroutine@$DIR/async-closure.rs:9:22: 11:6}(move _2); StorageDead(_2); @@ -52,7 +52,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo } bb1: { StorageLive(_3); - _4 = ((*_7).0: &i32); + _4 = no_retag ((*_7).0: &i32); _3 = (*_4); _5 = (); StorageDead(_3); @@ -84,7 +84,7 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c } bb1: { StorageLive(_3); - _4 = ((*_7).0: &i32); + _4 = no_retag ((*_7).0: &i32); _3 = (*_4); _5 = (); StorageDead(_3);