-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider removing ProjectionElem::Index
#71265
Comments
This has come up before, at least as early as last year's allhands. |
👍, I have this in my todo list. May end tackling it very soon if nobody beats me to do it 😄. |
One challenge here is that the borrow checker is kind of smart. For example, this code compiles (playground): struct Foo {
x: u32,
y: u32
}
fn main() {
let foos: &mut [Foo] = &mut [Foo { x: 0, y: 0 }, Foo { x: 0, y: 0 }];
let p = &mut foos[0].x;
let q = &mut foos[0].y;
*q += 1;
*p += 1;
} The challenge here is that
because then it would conflict with the later access to This leads us back to that design I was pushing for earlier of having a notion of "place values" that we build up bit-by-bit and "finalize" to actually do a borrow. |
Considering that #![feature(raw_ref_op)]
struct Foo {
x: u32,
y: u32
}
fn main() {
unsafe {
let foos: &mut [Foo] = &mut [Foo { x: 0, y: 0 }, Foo { x: 0, y: 0 }];
let p = &raw mut foos[0];
let p = &raw mut (*p).x;
let q = &raw mut foos[0].y;
*q += 1;
*p += 1;
}
} is legal in stacked borrows (at least miri happily evaluates this cc @RalfJung ), would it make sense to teach borrowck about struct Foo {
x: u32,
y: u32
}
fn main() {
let foos: &mut [Foo] = &mut [Foo { x: 0, y: 0 }, Foo { x: 0, y: 0 }];
let p = &mut foos[0];
let r = &mut p.x;
let q = &mut foos[0].y;
*q += 1;
*r += 1;
} which could be fine since |
Yeah that first example seems fine in terms of Stacked Borrows -- since everything is raw pointers, there are no aliasing requirements. I think Stacked Borrows would also accept the second example if it was accepted by the borrow checker; it is basically equivalent to struct Foo {
x: u32,
y: u32
}
fn main() {
let foos: &mut [Foo] = &mut [Foo { x: 0, y: 0 }, Foo { x: 0, y: 0 }];
let r = &mut foos[0].x;
let q = &mut foos[0].y;
*q += 1;
*r += 1;
} The fact that |
I'm not necessarily opposed to extending the borrow checker here, but I don't immediately see how to do it. We're also still in the midst of transitioning to polonius -- I guess I would want to make this change in that context. Currently what happens is that we get a relation Right now, the borrow checker doesn't really know that So I guess we'd be looking at some sort of rule that tries to specialize this case -- reborrowing a singleton set -- and handle it in some other way. Anyway, TL;DR, seems plausible but complicated. To recall, my current plan was to have "place temporaries" for use when building up paths like |
Yes that's what @spastorino and I talked about, when the scheme explained in my previous comment came up. We'll look into implementing the place temporaries scheme. I have some ideas how to do this in a way so we can switch between the current scheme and the new scheme on the fly via a |
I think an MCP would be appropriate to describe the plan. |
It is the only projection element that uses another local besides the place's base local, and requires special care in many circumstances. All other
ProjectionElem
s perform static operations that do not depend on runtime values.In #71003, I initially did not handle this special case, which would have resulted in an unsound optimization. The visitor logic for them was also broken (fixed in #71013) because it was missing a special case.
I'm not sure what to adequately replace them with. It seems like
Rvalue::Index
would be a reasonable choice, but it might have other drawbacks.cc @rust-lang/wg-mir-opt
The text was updated successfully, but these errors were encountered: