Description
One of the biggest "tuning knobs" we have in Stacked Borrows is tdefining when and where exactly retagging happens. Currently we have a rather crude 'add retags' MIR pass, which is unsatisfying for several reasons:
- technically this is a MIR pass that adds UB, which is bad
- the actual aliasing assumptions made by codegen are completely disconnected from these retags
- while we generally insert a retag after every assignment that involves references, we avoid doing that in cases like
*ptr = ...
since I was worried that the assignment itself might change where that pointer points to
So, we want something nicer and more principled, I think. For MiniRust I am considering making the AssumeFullyInit
statement (that was also discussed for MIR) do retagging; we'd want such statements (explicitly or implicitly) at the beginning of every function and after every local variable is initialized and probably on the return value of every callee, so that would cover a lot of it. And then maybe the only other place where we really need retags are the &
/&mut
operators, i.e., (re)borrowing? However, this has the unfortunate side-effect that generic code behaves slightly different from manually monomorphized code:
fn id<T>(x: T) -> T { x }
fn id_mutref<T>(x: &mut T) -> &mut T { x }
The 2nd function has a reborrow in the MIR, but the first does not.
There's also the question of what to do with 'raw retagging', which we currently (try to) insert on all reference-to-raw-ptr casts -- but here my hope is that we just won't need them at all in the future.