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

enable non-lexical lifetimes in the MIR borrow checker #45538

Merged
merged 33 commits into from
Nov 1, 2017

Conversation

nikomatsakis
Copy link
Contributor

@nikomatsakis nikomatsakis commented Oct 25, 2017

This PR, joint work with @spastorino, fills out the NLL infrastructure and integrates it with the borrow checker. Don't get too excited: it includes still a number of hacks (the subtyping code is particularly hacky). However, it does kinda' work. =)

The final commit demonstrates this by including a test that -- with both the AST borrowck and MIR borrowck -- reports an error by default. But if you pass -Znll, you only get an error from the AST borrowck, demonstrating that the integration succeeds:

struct MyStruct {
    field: String
}

fn main() {
    let mut my_struct = MyStruct { field: format!("Hello") };

    let value = &my_struct.field;
    if value.is_empty() {
        my_struct.field.push_str("Hello, world!");
        //~^ ERROR cannot borrow (Ast)
    }
}

@rust-highfive
Copy link
Collaborator

r? @pnkfelix

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

@aturon
Copy link
Member

aturon commented Oct 26, 2017

Congrats, both of you! Been awesome seeing you power through this.

@kennytm kennytm added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Oct 26, 2017
@@ -0,0 +1,89 @@
use super::RegionIndex;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tidy error 😏

[00:03:02] tidy error: /checkout/src/librustc_mir/transform/nll/subtype.rs: incorrect license
[00:03:02] tidy error: /checkout/src/test/mir-opt/nll/region-liveness-drop-no-may-dangle.rs:48: line longer than 100 chars
[00:03:03] some tidy checks failed

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kennytm I've already fixed this in my local machine, will push in a while :)


// END RUST SOURCE
// START rustc.node12.nll.0.mir
// | R4: {bb1[3], bb1[4], bb1[5], bb2[0], bb2[1], bb2[2], bb3[0], bb4[0], bb4[1], bb4[2], bb6[0], bb7[0], bb7[1], bb8[0]}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs // ignore-tidy-linelength.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this.

LvalueContext::Store |

// We let Call defined the result in both the success and unwind cases.
// This may not be right.
// We let Call defined the result in both the success and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: should be "we let Call define the result"

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 26, 2017
}

///////////////////////////////////////////////////////////////////////////
// DROP USES

// We consider drops to always be uses of locals.
// Drop eloboration should be run before this analysis otherwise
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This note about when drop "eloboration" should run (which came from cbdb186) ... it applied to @Zoxc's move analysis, but does it apply to our uses here for NLL? I ask because I am pretty sure we want borrowck to run before drop elaboration ...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is really kind of outdated. We do not want to run drop elaboration before the check -- and we are ok with drops being considered uses.


// END RUST SOURCE
// START rustc.node12.nll.0.mir
// | R0: {bb1[1], bb2[0], bb2[1]}
Copy link
Member

@pnkfelix pnkfelix Oct 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it be better to print the region identifiers here as: _#0r:, _#2r:, _#3r: (or some uniform suffix of those) to make more clear the correspondence with their appearances in the borrows?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, at the beginning I have a hard time figuring this output out, so ... maybe going through this and making it more clear is a good things to do. /cc @nikomatsakis

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that. I guess we might as well adopt the existing _#0r, even though it's horrible.


// END RUST SOURCE
// START rustc.node12.nll.0.mir
// | R0: {bb1[1], bb1[2], bb1[3], bb1[4], bb1[5], bb1[6], bb2[0], bb2[1]}
Copy link
Member

@pnkfelix pnkfelix Oct 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, do we not have an explicit notation for where R0 (aka '_#0r, right?) arises, somewhere in the MIR dump?

}

#[allow(dead_code)]
pub struct MirBorrowckCtxt<'c, 'b, 'a: 'b+'c, 'gcx: 'a+'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'gcx>,
mir: &'b Mir<'gcx>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

niko can i bribe you with some halloween candy to break out this semi-mechanical lifetime-parameter refactoring (or generalization, if you prefer) into a separate commit? This commt is pretty hard to digest the way it is currently set up...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Twix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done btw.

@pnkfelix
Copy link
Member

This is epic!

🥇

@pnkfelix pnkfelix 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-review Status: Awaiting review from the assignee but also interested parties. labels Oct 26, 2017
@pnkfelix
Copy link
Member

my questions and nits are all pretty minor.

It might be a good idea to see if @arielb1 wants to take a look too, but he might be on vacation

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 27, 2017
@nikomatsakis
Copy link
Contributor Author

@pnkfelix addressed feedback. I also rebased and cleaned up the history, incorporating a number of changes from @spastorino. Have to figure out those travis failures though.

@spastorino
Copy link
Member

@nikomatsakis some of my commits are lost, related to the tests and fixes we were doing last night. Is that included in the code you've pushed? should I push that again?.

@nikomatsakis
Copy link
Contributor Author

@spastorino I don't believe they were lost, rather I merged them into the appropriate places.

@nikomatsakis
Copy link
Contributor Author

Those travis failures are curious. I don't see them locally, on mac or linux. :/

This will be important in next commit, since the input types will be
tagged not with `'gcx` but rather `'tcx`. Also, using the region-erased,
lifted types enables better caching.
Also, factor out `do_mir_borrowck`, which is the code that actually
performs the MIR borrowck from within the scope of an inference context.

This change should be a pure refactoring.
The macro now takes a format string. It no longer defaults to using the
type name. Didn't seem worth going through contortions to maintain.  I
also changed most of the debug formats to be `foo[N]` instead of `fooN`.
@nikomatsakis
Copy link
Contributor Author

@bors r=pnkfelix

I'm going to go ahead and land this so as to unblock further work. It ought not to deeply interact with any "enabled by default" code, so it's low risk.

@bors
Copy link
Contributor

bors commented Oct 31, 2017

📌 Commit aae3e74 has been approved by pnkfelix

@badboy
Copy link
Member

badboy commented Oct 31, 2017

@spastorino Wuhu! Congrats on pushing this through!

@kennytm kennytm 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 Nov 1, 2017
@bors
Copy link
Contributor

bors commented Nov 1, 2017

⌛ Testing commit aae3e74 with merge 2be4cc0...

bors added a commit that referenced this pull request Nov 1, 2017
enable non-lexical lifetimes in the MIR borrow checker

This PR, joint work with @spastorino, fills out the NLL infrastructure and integrates it with the borrow checker. **Don't get too excited:** it includes still a number of hacks (the subtyping code is particularly hacky). However, it *does* kinda' work. =)

The final commit demonstrates this by including a test that -- with both the AST borrowck and MIR borrowck -- reports an error by default. But if you pass `-Znll`, you only get an error from the AST borrowck, demonstrating that the integration succeeds:

```
struct MyStruct {
    field: String
}

fn main() {
    let mut my_struct = MyStruct { field: format!("Hello") };

    let value = &my_struct.field;
    if value.is_empty() {
        my_struct.field.push_str("Hello, world!");
        //~^ ERROR cannot borrow (Ast)
    }
}
```
@bors
Copy link
Contributor

bors commented Nov 1, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: pnkfelix
Pushing 2be4cc0 to master...

@mgattozzi
Copy link
Contributor

It's finally here! :D Well part of it but still! :D

bors added a commit that referenced this pull request Nov 6, 2017
extend NLL with preliminary support for free regions on functions

This PR extends #45538 with support for free regions. This is pretty preliminary and will no doubt want to change in various ways, particularly as we add support for closures, but it's enough to get the basic idea in place:

- We now create specific regions to represent each named lifetime declared on the function.
- Region values can contain references to these regions (represented for now as a `BTreeSet<RegionIndex>`).
- If we wind up trying to infer that `'a: 'b` must hold, but no such relationship was declared, we report an error.

It also does a number of drive-by refactorings.

r? @arielb1

cc @spastorino
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