-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Evaluate place expression in PlaceMention
#104844
Conversation
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt Some changes occurred to the CTFE / Miri engine cc @rust-lang/miri Some changes occurred in src/tools/clippy cc @rust-lang/clippy Some changes occurred in compiler/rustc_codegen_cranelift cc @bjorn3 This PR changes MIR cc @oli-obk, @RalfJung, @JakobDegen, @davidtwco, @celinval, @vakaras The Miri subtree was changed cc @rust-lang/miri |
// Evaluate the place expression, without reading from it. | ||
PlaceMention(box place) | AscribeUserType(box (place, _), _) => { | ||
let _ = self.eval_place(*place)?; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, AscribeUserType also does this? That is slightly surprising.
Is it possible to add tests to Miri that hit both of these cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should always be a PlaceMention
before an AscribeUserType
, so theoretically AscribeUserType
can never fail. So I don't really know if we should check both, or just PlaceMention
.
/// binding. This is especially useful for `let _ = PLACE;` bindings that desugar to a single | ||
/// `PlaceMention(PLACE)`. | ||
/// | ||
/// When executed at runtime this is a nop. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be updated.
/// When executed at runtime this is a nop. | |
/// When executed at runtime, this computes the given place, but then discards | |
/// it without doing a load. It is UB if the place is not pointing to live memory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AscribeUserType would probably need something similar, judging from the case you added in Miri?
// `PlaceMention` and `AscribeUserType` both evaluate the place, which must not | ||
// contain dangling references. | ||
PlaceContext::NonUse(NonUseContext::PlaceMention) | | ||
PlaceContext::NonUse(NonUseContext::AscribeUserTy) | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know borrowck, so someone else will have to review this part.
But doesn't this do a check that the place is actually initialized? Just to avoid UB it would be sufficient to check that the place is live, but maybe borrowck does not have such a check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking that the place is initialized will break a lot of code, because we allow binding moved-from places to _
. For instance in test src/test/ui/binding/issue-53114-borrow-checks.rs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes an init check is not needed. I just thought DefUse::Use
does an init check (since usually when we use a place, we load from it, and it must be init). But it seems I am wrong about that?
cb4b8f8
to
4316315
Compare
This comment was marked as resolved.
This comment was marked as resolved.
PlaceMention
and AscribeUserType
PlaceMention
4316315
to
9a98a1b
Compare
This comment was marked as resolved.
This comment was marked as resolved.
Marking as blocked on #102256 |
9a98a1b
to
35b3b3f
Compare
7c62ed8
to
fd1a0fc
Compare
This comment was marked as resolved.
This comment was marked as resolved.
fd1a0fc
to
e533dca
Compare
This comment has been minimized.
This comment has been minimized.
e533dca
to
c3c6a86
Compare
This comment was marked as resolved.
This comment was marked as resolved.
47557ee
to
2eaf600
Compare
37219ed
to
ac2ba0e
Compare
This comment was marked as resolved.
This comment was marked as resolved.
e15e203
to
cfcfbe6
Compare
☔ The latest upstream changes (presumably #110477) made this pull request unmergeable. Please resolve the merge conflicts. |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
cfcfbe6
to
2870d26
Compare
@bors r=jackh726,RalfJung |
☀️ Test successful - checks-actions |
Finished benchmarking commit (21fab43): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
|
…726,RalfJung Evaluate place expression in `PlaceMention` rust-lang#102256 introduces a `PlaceMention(place)` MIR statement which keep trace of `let _ = place` statements from surface rust, but without semantics. This PR proposes to change the behaviour of `let _ =` patterns with respect to the borrow-checker to verify that the bound place is live. Specifically, consider this code: ```rust let _ = { let a = 5; &a }; ``` This passes borrowck without error on stable. Meanwhile, replacing `_` by `_: _` or `_p` errors with "error[E0597]: `a` does not live long enough", [see playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c448d25a7c205dc95a0967fe96bccce8). This PR *does not* change how `_` patterns behave with respect to initializedness: it remains ok to bind a moved-from place to `_`. The relevant test is `tests/ui/borrowck/let_underscore_temporary.rs`. Crater check found no regression. For consistency, this PR changes miri to evaluate the place found in `PlaceMention`, and report eventual dangling pointers found within it. r? `@RalfJung`
…RalfJung Allow partially moved values in match This PR attempts to unify the behaviour between `let _ = PLACE`, `let _: TY = PLACE;` and `match PLACE { _ => {} }`. The logical conclusion is that the `match` version should not check for uninitialised places nor check that borrows are still live. The `match PLACE {}` case is handled by keeping a `FakeRead` in the unreachable fallback case to verify that `PLACE` has a legal value. Schematically, `match PLACE { arms }` in surface rust becomes in MIR: ```rust PlaceMention(PLACE) match PLACE { // Decision tree for the explicit arms arms, // An extra fallback arm _ => { FakeRead(ForMatchedPlace, PLACE); unreachable } } ``` `match *borrow { _ => {} }` continues to check that `*borrow` is live, but does not read the value. `match *borrow {}` both checks that `*borrow` is live, and fake-reads the value. Continuation of ~rust-lang#102256 ~rust-lang#104844 Fixes rust-lang#99180 rust-lang#53114
Allow partially moved values in match This PR attempts to unify the behaviour between `let _ = PLACE`, `let _: TY = PLACE;` and `match PLACE { _ => {} }`. The logical conclusion is that the `match` version should not check for uninitialised places nor check that borrows are still live. The `match PLACE {}` case is handled by keeping a `FakeRead` in the unreachable fallback case to verify that `PLACE` has a legal value. Schematically, `match PLACE { arms }` in surface rust becomes in MIR: ```rust PlaceMention(PLACE) match PLACE { // Decision tree for the explicit arms arms, // An extra fallback arm _ => { FakeRead(ForMatchedPlace, PLACE); unreachable } } ``` `match *borrow { _ => {} }` continues to check that `*borrow` is live, but does not read the value. `match *borrow {}` both checks that `*borrow` is live, and fake-reads the value. Continuation of ~rust-lang/rust#102256 ~rust-lang/rust#104844 Fixes rust-lang/rust#99180 rust-lang/rust#53114
#102256 introduces a
PlaceMention(place)
MIR statement which keep trace oflet _ = place
statements from surface rust, but without semantics.This PR proposes to change the behaviour of
let _ =
patterns with respect to the borrow-checker to verify that the bound place is live.Specifically, consider this code:
This passes borrowck without error on stable. Meanwhile, replacing
_
by_: _
or_p
errors with "error[E0597]:a
does not live long enough", see playground.This PR does not change how
_
patterns behave with respect to initializedness: it remains ok to bind a moved-from place to_
.The relevant test is
tests/ui/borrowck/let_underscore_temporary.rs
. Crater check found no regression.For consistency, this PR changes miri to evaluate the place found in
PlaceMention
, and report eventual dangling pointers found within it.r? @RalfJung