Skip to content
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

Fix end region emission order #44129

Merged
merged 4 commits into from
Sep 13, 2017

Conversation

pnkfelix
Copy link
Member

Fix #43481

@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

(rust_highfive has picked a reviewer for you, use r? to override)

@arielb1
Copy link
Contributor

arielb1 commented Aug 28, 2017

Can you have a test that shows how this fits with the destruction code extent? Maybe even in the same test?

It should be

endregion for 'rce
drop/storagedead - 'dce is live here
endregion for 'dce

@nikomatsakis
Copy link
Contributor

r=me modulo @arielb1's concern

@carols10cents carols10cents added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Aug 28, 2017
@bors
Copy link
Contributor

bors commented Aug 28, 2017

☔ The latest upstream changes (presumably #43076) made this pull request unmergeable. Please resolve the merge conflicts.

@pnkfelix pnkfelix force-pushed the fix-end-region-emission-order branch from 369e87d to 96e4f35 Compare August 29, 2017 08:48
@pnkfelix
Copy link
Member Author

pnkfelix commented Aug 30, 2017

Sorry its taking me so long to finish this off. I spent a while trying to create a case matching @arielb1's expectation. Now I think I have one, but I also am not sure whether the outline @arielb1 gave is what we should actually want to see in practice.

Here is some input code I've come up with:

fn main() {
    // This case illustrates one particular ordering of interest:
    D1(&S1("tmp"));
}

#[derive(Debug)]
struct S1(&'static str);

#[derive(Debug)]
struct D1<'a>(&'a S1);

impl<'a> Drop for D1<'a> {
    fn drop(&mut self) {
        println!("D1({:?})", self.0); 
    }
}

Here is the output MIR (compiled via: ./build/x86_64-apple-darwin/stage1/bin/rustc -Z identify_regions -Z span_free_formats -Z dump-mir=main ../src/test/mir-opt/end_region_destruction_extents_1.rs):

// MIR for `main`
// source = Fn(NodeId(4))
// pass_name = SimplifyCfg-initial
// disambiguator = after

fn main() -> () {
    let mut _0: ();
    let mut _1: D1<'160dce>;
    let mut _2: &'160dce S1;
    let mut _3: &'160dce S1;
    let mut _4: S1;

    bb0: {
        StorageLive(_2);
        StorageLive(_3);
        StorageLive(_4);
        _4 = S1::{{constructor}}(const "tmp",);
        _3 = &'160dce _4;
        _2 = &'160dce (*_3);
        _1 = D1<'160dce>::{{constructor}}(_2,);
        drop(_1) -> bb1;
    }

    bb1: {
        StorageDead(_2);
        StorageDead(_3);
        StorageDead(_4);
        EndRegion('160dce);
        _0 = ();
        return;
    }
}

So, here's my problem: I agree that EndRegion('160dce) should come after the drop(_1) in the control flow (since we need that region to live across the destructor invocation).

But it should precede the StorageDead(_4), right?

...

(Also, I just realized that this code actually only started compiling relatively recently; on the current stable, it is rejected with a suggestion that the S1("tmp") doesn't live long enough. So maybe this is a case where EndRegion emission needs to account for r-value promotion, which, if fixed, would result in the ordering drop(_1); EndRegion('160dce); StorageDead(_4); ... maybe?

@nikomatsakis
Copy link
Contributor

(Also, I just realized that this code actually only started compiling relatively recently; on the current stable, it is rejected with a suggestion that the S1("tmp") doesn't live long enough. So maybe this is a case where EndRegion emission needs to account for r-value promotion, which, if fixed, would result in the ordering drop(_1); EndRegion('160dce); StorageDead(_4); ... maybe?

I think what I would expect is that we would run the qualification pass after construction, and hence wind up removing _4 in favor of a new static. In that case, the fact that StorageDead(_4) precedes EndRegion('160dce) wouldn't cause an error, because _4 is not being borrowed anymore.

@arielb1
Copy link
Contributor

arielb1 commented Aug 30, 2017

@pnkfelix

Your example only compiles because of rvalue promotion. An rvalue-promotion version (or this one, on stable) errors as it should - today's borrowck basically puts the 'dce endregion after all the drops.

fn main() {
    // This case illustrates one particular ordering of interest:
    let x = "tmp";
    D1(&S1(x)); //~ ERROR
}

#[derive(Debug)]
struct S1(&'static str);

#[derive(Debug)]
struct D1<'a>(&'a S1);

impl<'a> Drop for D1<'a> {
    fn drop(&mut self) {
        println!("D1({:?})", self.0); 
    }
}

Also, you can easily have drop -> storagedead -> drop -> storagedead orderings, as in:

fn main() {
    D1((&D1(&S1("red")), &S1("tmp"), &D1(&S1("herring"))).1);
}

In which case there is no "between the drop and storagedead" place.

Therefore, I prefer having the drop & storagedead as 1 unit and placing the EndRegion after them. I believe this should work for all code that does not exploit soundness issues in the borrow checker.

@arielb1
Copy link
Contributor

arielb1 commented Aug 30, 2017

I'll also note that moving the EndRegion to after the StorageDead can only make less code compile - you won't have any new "liveness" requirements (because StorageDead doesn't have any) but now the StorageDead can conflict with pre-existing borrows.

@pnkfelix
Copy link
Member Author

@arielb1 ... okay, but isn't that in conflict with the property (taken from #43481 (comment) ):

  • For all 'rgn, and all lval such that the code has borrow(s) of form &'rgn lval, whereever StorageDead(lval) occurs, the region 'rgn has already ended (via EndRegion('rgn)).

@pnkfelix
Copy link
Member Author

@arielb1 or maybe I misunderstand (once again)? Are you saying that we will enforce the property, because the compiler will reject such code?

@arielb1
Copy link
Contributor

arielb1 commented Aug 30, 2017

@pnkfelix

Thats... what the borrow-check does. Or at least what it's supposed to do. You can't have a live borrow to something while you EndRegion it.

@pnkfelix
Copy link
Member Author

@arielb1 okay, I was confused because I thought you were suggesting an ordering for {Drop,StorageDead,EndRegion} that you intended to be legal to the borrowck in cases like this.

@pnkfelix pnkfelix force-pushed the fix-end-region-emission-order branch from 96e4f35 to 4a7c28c Compare August 31, 2017 11:34
@pnkfelix
Copy link
Member Author

@bors r=nmatsakis

@bors
Copy link
Contributor

bors commented Aug 31, 2017

📌 Commit 4a7c28c has been approved by nmatsakis

@bors
Copy link
Contributor

bors commented Aug 31, 2017

⌛ Testing commit 4a7c28c9b1f956fb7577bd118adb9b2823f37bfe with merge 8318fdad5733a80e7d7449bfdbc08bd42cc0a47c...

@bors
Copy link
Contributor

bors commented Aug 31, 2017

💔 Test failed - status-travis

@kennytm
Copy link
Member

kennytm commented Aug 31, 2017

@bors retry

check i686-apple-darwin hung during doc test of libstd. Reason unknown.

[02:08:15] test collections/hash/set.rs - collections::hash::set::HashSet<T, S>::is_disjoint (line 542) ... ok
[02:08:15] test collections/hash/set.rs - collections::hash::set::HashSet<T, S>::is_empty (line 442) ... ok


No output has been received in the last 30m0s, this potentially indicates a stalled build or something wrong with the build itself.
Check the details on how to adjust your build configuration on: https://docs.travis-ci.com/user/common-build-problems/#Build-times-out-because-no-output-was-received

The build has been terminated

@bors
Copy link
Contributor

bors commented Aug 31, 2017

⌛ Testing commit 4a7c28c9b1f956fb7577bd118adb9b2823f37bfe with merge 19db440bb17f57e851875ab641283c24abc621f2...

@bors
Copy link
Contributor

bors commented Aug 31, 2017

💔 Test failed - status-travis

@kennytm
Copy link
Member

kennytm commented Aug 31, 2017

@bors retry #44221

check i686-apple-darwin stuck again.

[00:18:16]    Compiling rustc_llvm v0.0.0 (file:///Users/travis/build/rust-lang/rust/src/librustc_llvm)
[00:18:20]    Compiling flate2 v0.2.19
[00:18:20]    Compiling rustc_errors v0.0.0 (file:///Users/travis/build/rust-lang/rust/src/librustc_errors)
No output has been received in the last 30m0s, this potentially indicates a stalled build or something wrong with the build itself.
Check the details on how to adjust your build configuration on: https://docs.travis-ci.com/user/common-build-problems/#Build-times-out-because-no-output-was-received
The build has been terminated

@bors
Copy link
Contributor

bors commented Aug 31, 2017

⌛ Testing commit 4a7c28c9b1f956fb7577bd118adb9b2823f37bfe with merge 055f72be4a23c82a6a4d6278440439b1fa3a69f3...

@bors
Copy link
Contributor

bors commented Aug 31, 2017

💔 Test failed - status-travis

@bors
Copy link
Contributor

bors commented Sep 1, 2017

⌛ Testing commit 4a7c28c9b1f956fb7577bd118adb9b2823f37bfe with merge 05446c7ffd17549af517b5bed93fb5066910a430...

@bors
Copy link
Contributor

bors commented Sep 1, 2017

💔 Test failed - status-travis

@kennytm
Copy link
Member

kennytm commented Sep 1, 2017

@bors retry p=-1 p=0 #42117

[00:04:00] extracting /Users/travis/build/rust-lang/rust/build/cache/2017-07-18/cargo-beta-i686-apple-darwin.tar.gz
[00:04:01]     Updating registry `https://github.com/rust-lang/crates.io-index`
[00:05:16]     Updating git repository `https://github.com/rust-lang/cargo`

No output has been received in the last 30m0s, this potentially indicates a stalled build or something wrong with the build itself.
Check the details on how to adjust your build configuration on: https://docs.travis-ci.com/user/common-build-problems/#Build-times-out-because-no-output-was-received

The build has been terminated

(reduce priority because it has failed too many times, even if spurious.) (Restore priority as re-r+ is expected)

@bors
Copy link
Contributor

bors commented Sep 1, 2017

☔ The latest upstream changes (presumably #44171) made this pull request unmergeable. Please resolve the merge conflicts.

@nikomatsakis
Copy link
Contributor

@pnkfelix merge conflict :(

@bors
Copy link
Contributor

bors commented Sep 4, 2017

🔒 Merge conflict

@pnkfelix pnkfelix force-pushed the fix-end-region-emission-order branch from 4a7c28c to e2f00fc Compare September 5, 2017 13:13
@pnkfelix
Copy link
Member Author

pnkfelix commented Sep 5, 2017

@bors r=nmatsakis

@bors
Copy link
Contributor

bors commented Sep 5, 2017

📌 Commit e2f00fc has been approved by nmatsakis

@pnkfelix pnkfelix added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 5, 2017
@aidanhs
Copy link
Member

aidanhs commented Sep 7, 2017

@bors r-

Failure seems related?

Check compiletest suite=mir-opt mode=mir-opt (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
[00:49:22] 
[00:49:22] running 32 tests
[00:49:27] thread 'main' panicked at 'Some tests failed', /checkout/src/tools/compiletest/src/main.rs:323:21
[00:49:27] ..............F.F.F.............
[00:49:27] failures:
[00:49:27] 
[00:49:27] ---- [mir-opt] mir-opt/end_region_9.rs stdout ----
[00:49:27] 	thread '[mir-opt] mir-opt/end_region_9.rs' panicked at 'ran out of mir dump output to match against.
[00:49:27] Did not find expected line: "    let mut _4: &\'13_0rs i32;"

@aidanhs aidanhs added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Sep 7, 2017
@bors
Copy link
Contributor

bors commented Sep 7, 2017

☔ The latest upstream changes (presumably #44249) made this pull request unmergeable. Please resolve the merge conflicts.

…or a scope.

(The idea is that the StorageDead marks the point where the memory can
be deallocated, and the EndRegion is marking where borrows of that
memory can no longer legally exist.)
Driveby fix to end_region_9.rs; it was missing END marker and was
therefore always passing (regardless of output correctness).
@pnkfelix
Copy link
Member Author

Thanks @aidanhs sorry about that!

@pnkfelix
Copy link
Member Author

@bors r=nmatsakis

@bors
Copy link
Contributor

bors commented Sep 13, 2017

📌 Commit 5fa0b66 has been approved by nmatsakis

@pnkfelix pnkfelix added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 13, 2017
@bors
Copy link
Contributor

bors commented Sep 13, 2017

⌛ Testing commit 5fa0b66 with merge 539f208...

bors added a commit that referenced this pull request Sep 13, 2017
@bors
Copy link
Contributor

bors commented Sep 13, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: nmatsakis
Pushing 539f208 to master...

@bors bors merged commit 5fa0b66 into rust-lang:master Sep 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants