)]}'
{
  "commit": "20de910db49d3476ccf49ea79a4b22e2b5dface0",
  "tree": "0d53894915e70ea920780e8f1715a688d052c3b8",
  "parents": [
    "3d5dfdc29f0e3ba6e0d31d1cd39bf2beac4ce4b4",
    "e402c1edf047a23b0cfef40c6097d1caa294050b"
  ],
  "author": {
    "name": "bors",
    "email": "bors@rust-lang.org",
    "time": "Sat May 02 17:42:41 2026 +0000"
  },
  "committer": {
    "name": "bors",
    "email": "bors@rust-lang.org",
    "time": "Sat May 02 17:42:41 2026 +0000"
  },
  "message": "Auto merge of #154341 - RalfJung:retag-on-typed-copy, r\u003doli-obk\n\nMake retags an implicit part of typed copies\n\n\r\n\r\nEver since Stacked Borrows was first implemented in Miri, that was done with `Retag` statements: given a place (usually a local variable), those statements find all references stored inside the place and refresh their tags to ensure the aliasing requirements are upheld. However, this is a somewhat unsatisfying approach for multiple reasons:\r\n- It leaves open the [question](https://github.com/rust-lang/unsafe-code-guidelines/issues/371) of where to even put `Retag` statements. Over time, the AddRetag pass settled on one possible answer to this, but it wasn\u0027t very canonical.\r\n- For assignments of the form `*ptr \u003d expr`, if the assignment involves copying a reference, we probably want to do a retag -- but if we do a `Retag(*ptr)` as the next instruction, it can be non-trivial to argue that this even retags the right value, so we refrained from doing retags in that case. This has [come up](https://github.com/llvm/llvm-project/pull/160913#issuecomment-3341908717) as a potential issue for Rust making better use of LLVM \"captures\" annotations. (That said, there might be [other ways](https://github.com/rust-lang/unsafe-code-guidelines/issues/593#issuecomment-4328112031) to obtain this desired optimization.)\r\n- Normal compilation avoids generating retags, but we still generate LLVM IR with `noalias`. What does that even mean? How do MIR optimization passes interact with retags? These are questions we have to figure out to make better use of aliasing information, but currently we can\u0027t even really ask such questions.\r\n\r\nI think we should resolve all that by making retags part of what happens during a typed copy (a concept and interpreter infrastructure that did not exist yet when retags were initially introduced). Under this proposal, when executing a MIR assignment statement, what conceptually happens is as follows:\r\n- We evaluate the LHS to a place.\r\n- We evaluate the RHS to a value. This does a typed load from memory if needed, raising UB if memory does not contain a valid representation of the assignment\u0027s type.\r\n- We walk that value, identify all references inside of it, and retag them. If this happens as part of passing a function argument, this is a protecting retag.\r\n- We store (a representation of) the value into the place.\r\n\r\nHowever, this semantics doesn\u0027t fully work: there\u0027s a mandatory MIR pass that turns expressions like `\u0026mut ***ptr` into intermediate deref\u0027s. Those must *not* do any retags. So far this happened because the AddRetag pass did not add retags for assignments to deref temporaries, but that information is not recorded in cross-crate MIR. Therefore I instead added a field to `Rvalue::Use` to indicate whether this value should be retagged or not. A non-retagging copy seems like a sufficiently canonical primitive that we should be able to express it. Dealing with the fallout from that is a large chunk of the overall diff. (I also considered adding this field to `StatementKind::Assign` instead, but decided against that as we only actually need it for `Rvalue::Use`. I am not sure if this was the right call...)\r\n\r\nThis neatly answers the question of when retags should occur, and handles cases like `*ptr \u003d expr`. It avoids traversing values twice in Miri. It makes codegen\u0027s use of `noalias` sound wrt the actual MIR that it is working on. It also gives us a target semantics to evaluate MIR opts against. However, I did not carefully check all MIR opts -- in particular, GVN needs a thorough look under the new semantics; it currently can turn alias-correct code into alias-incorrect code. (But this PR doesn\u0027t make things any worse for normal compilation where the retag indicator is anyway ignored.)\r\n\r\nAnother side-effect of this PR is that `-Zmiri-disable-validation` now also disables alias checking. It\u0027d be nicer to keep them orthogonal but I find this an acceptable price to pay.\r\n\r\n- [rustc benchmark results](https://github.com/rust-lang/rust/pull/154341#issuecomment-4125313290)\r\n- [miri benchmark results](https://github.com/rust-lang/rust/pull/154341#issuecomment-4129840926)",
  "tree_diff": []
}
