Proposal: Deref is not a Projection

Motivation

The MIR uses Place to refer to memory locations. A Place consists of a base, either a static or a local, and a series of projections starting from that base. With one exception, these projections are merely refinements of the base: they specify a field, an array element, or the portion of memory corresponding to a given enum variant. However, the Deref projection is unique in that the target of the  Place refers to a completely different region of memory than the base. As a result, several analyses must iterate over each place to see whether that place contains a Deref. This proposal considers removing Deref from the list of projections, instead making it an Rvalue.

This idea originates from +Topic: MIR 2.0 and MIR Optimizations. Search for “instead of embedding” and legal in MIR right now”.

Constraints

Avoid extra copies

The current scheme lets us avoid copying the target of a Deref into a Local if all we want is a projection. For example, if x is a pointer to a large array, the assignment y = (*x)[0] copies only the first element of  *x

Place is used as an argument for most Rvalue variants either directly or via an Operand. If we stop encoding Derefs as part of a Place, we will need to create a new local to hold that target before passing it to the Rvalue. We should try to avoid unnecessary copies in this case as well.

Efficiently encode reborrows

At the moment, several passes special-case reborrows (&*x and &mut *x) to be more like a copy of a reference.  If we were to split Deref into its own Rvalue (and stop there), code would have to keep track of multiple statements to see if a Ref constituted a reborrow or not. This would complicate mir::Visitors significantly.

Design

This proposal would add two Rvalue variants, DerefBase(Place<'tcx>) and ReborrowBase(Region<'tcx>, BorrowKind, Place<'tcx>). DerefBase would dereference the base of a place, then apply any projections like so (*base).field[idx], and ReborrowBase would do the same but with a reborrow of the place base instead of a dereference ((&*base).field[idx]).

This design does not address how to pass a Place with Deref projections as an argument to an  Rvalue. We will need to come up with a solution for this, or at least a way to prevent any additional copies here. 

Implementation

TODO