Skip to content

Commit b85485e

Browse files
committed
Auto merge of #114011 - RalfJung:place-projection, r=oli-obk
interpret: Unify projections for MPlaceTy, PlaceTy, OpTy For ~forever, we didn't really have proper shared code for handling projections into those three types. This is mostly because `PlaceTy` projections require `&mut self`: they might have to `force_allocate` to be able to represent a project part-way into a local. This PR finally fixes that, by enhancing `Place::Local` with an `offset` so that such an optimized place can point into a part of a place without having requiring an in-memory representation. If we later write to that place, we will still do `force_allocate` -- for now we don't have an optimized path in `write_immediate` that would avoid allocation for partial overwrites of immediately stored locals. But in `write_immediate` we have `&mut self` so at least this no longer pollutes all our type signatures. (Ironically, I seem to distantly remember that many years ago, `Place::Local` *did* have an `offset`, and I removed it to simplify things. I guess I didn't realize why it was so useful... I am also not sure if this was actually used to achieve place projection on `&self` back then.) The `offset` had type `Option<Size>`, where `None` represent "no projection was applied". This is needed because locals *can* be unsized (when they are arguments) but `Place::Local` cannot store metadata: if the offset is `None`, this refers to the entire local, so we can use the metadata of the local itself (which must be indirect); if a projection gets applied, since the local is indirect, it will turn into a `Place::Ptr`. (Note that even for indirect locals we can have `Place::Local`: when the local appears in MIR, we always start with `Place::Local`, and only check `frame.locals` later. We could eagerly normalize to `Place::Ptr` but I don't think that would actually simplify things much.) Having done all that, we can finally properly abstract projections: we have a new `Projectable` trait that has the basic methods required for projecting, and then all projection methods are implemented for anything that implements that trait. We can even implement it for `ImmTy`! (Not that we need that, but it seems neat.) The visitor can be greatly simplified; it doesn't need its own trait any more but it can use the `Projectable` trait. We also don't need the separate `Mut` visitor any more; that was required only to reflect that projections on `PlaceTy` needed `&mut self`. It is possible that there are some more `&mut self` that can now become `&self`... I guess we'll notice that over time. r? `@oli-obk`
2 parents 2675180 + 1231655 commit b85485e

File tree

2 files changed

+4
-4
lines changed

2 files changed

+4
-4
lines changed

tests/ui/self_assignment.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub fn positives(mut a: usize, b: &mut u32, mut s: S) {
1414
*b = *b;
1515
s = s;
1616
s.a = s.a;
17-
s.b[10] = s.b[5 + 5];
17+
s.b[9] = s.b[5 + 4];
1818
s.c[0][1] = s.c[0][1];
1919
s.b[a] = s.b[a];
2020
*s.e = *s.e;

tests/ui/self_assignment.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ error: self-assignment of `s.a` to `s.a`
2424
LL | s.a = s.a;
2525
| ^^^^^^^^^
2626

27-
error: self-assignment of `s.b[5 + 5]` to `s.b[10]`
27+
error: self-assignment of `s.b[5 + 4]` to `s.b[9]`
2828
--> $DIR/self_assignment.rs:17:5
2929
|
30-
LL | s.b[10] = s.b[5 + 5];
31-
| ^^^^^^^^^^^^^^^^^^^^
30+
LL | s.b[9] = s.b[5 + 4];
31+
| ^^^^^^^^^^^^^^^^^^^
3232

3333
error: self-assignment of `s.c[0][1]` to `s.c[0][1]`
3434
--> $DIR/self_assignment.rs:18:5

0 commit comments

Comments
 (0)