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

Extend two-phase borrows to apply to method receiver autorefs #49348

Merged
merged 4 commits into from
Apr 3, 2018

Conversation

sapphire-arches
Copy link
Contributor

Fixes #48598 by permitting two-phase borrows on the autorefs created when functions and methods.

This is required to compile things like

src/test/ui/borrowck/two-phase-method-receivers.rs
@rust-highfive
Copy link
Collaborator

r? @nikomatsakis

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

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Mar 25, 2018
Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

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

Looks great! Left a nit, what do you think?

@@ -751,13 +760,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn try_coerce(&self,
expr: &hir::Expr,
expr_ty: Ty<'tcx>,
target: Ty<'tcx>)
target: Ty<'tcx>,
allow_two_phase: bool)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: maybe we can make a wrapper? I don't like the way "random bool parameters" read in the surrounding code. Maybe something like:

fn try_coerce(...) {
    self.try_coerce_full(..., false)
}

fn try_coerce_with_two_phase_borrow(...) {
    self.try_coerce_full(..., true)
}

fn try_coerce_full(...) { // as today
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Alternatively, since I see that the bool parameter propagates elsewhere, can we make it a newtype'd bool?

struct TwoPhase(bool);

so that callers look like:

self.try_coerce(..., TwoPhase(false))

This also gives us a central place to write docs that talk about 2-phase borrowing...

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 also wasn't super enthused about leaking that parameter everywhere. I think I'll take the newtype'd bool approach here and try to do a bit of a writeup. I think it makes sense to push that newtype through all the way until it's consumed in MIR borrwck which is going to touch a bit more code. I'll put that in a separate commit in case we want to back it out later.

Because more type safe is more better, and random boolean parameters everywhere
were not the greatest thing.
For consistency, use AllowTwoPhase everywhere between the frontend and MIR.
@sapphire-arches
Copy link
Contributor Author

Oops, failed tidy. I've added a pre-commit hook to my local working trees to prevent that in the future, and pushed a fix.

Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

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

This is great.

/// is more than one use of a mutable borrow, and we don't want to accept too much
/// new code via two-phase borrows, so we try to limit where we create two-phase
/// capable mutable borrows.
/// See #49434 for tracking.
Copy link
Contributor

Choose a reason for hiding this comment

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

lovin' the comments <3

match *self {
AutoBorrowMutability::Mutable { allow_two_phase_borrow } =>
BorrowKind::Mut { allow_two_phase_borrow },
BorrowKind::Mut { allow_two_phase_borrow: match allow_two_phase_borrow {
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe we should propagate the AllowTwoPhase type here, instead of converting to bool?

/// but we do need two-phase borrows for function argument reborrows.
/// See #47489 and #48598
/// See docs on the "AllowTwoPhase" type for a more detailed discussion
allow_two_phase: AllowTwoPhase,
Copy link
Contributor

Choose a reason for hiding this comment

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

Again, lovin' the comments

@@ -123,10 +130,13 @@ fn success<'tcx>(adj: Vec<Adjustment<'tcx>>,
}

impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, cause: ObligationCause<'tcx>) -> Self {
fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: these days, I tend to move over to rustfmt style when changing a sig anyway

fn new(
    fcx: ...
    cause: ...
    allow_two_phase: ...,
) -> Self {

// Indexing can be desugared to a method call,
// so maybe we could use two-phase here.
// See the documentation of AllowTwoPhase for why that's
// not the case today.
Copy link
Contributor

Choose a reason for hiding this comment

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

are you just referring to our general desire for caution? (I didn't see any specific notes about indexing)

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Apr 2, 2018

📌 Commit d8352af has been approved by nikomatsakis

@bors bors 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-review Status: Awaiting review from the assignee but also interested parties. labels Apr 2, 2018
@kennytm
Copy link
Member

kennytm commented Apr 3, 2018

@bors p=9

@bors
Copy link
Contributor

bors commented Apr 3, 2018

⌛ Testing commit d8352af with merge b12af86...

bors added a commit that referenced this pull request Apr 3, 2018
Extend two-phase borrows to apply to method receiver autorefs

Fixes #48598 by permitting two-phase borrows on the autorefs created when functions and methods.
@bors
Copy link
Contributor

bors commented Apr 3, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: nikomatsakis
Pushing b12af86 to master...

@bors bors merged commit d8352af into rust-lang:master Apr 3, 2018
bors added a commit that referenced this pull request Apr 7, 2018
…tsakis

two-phase borrows: support multiple activations in one statement

The need for this has arisen since the introduction of two-phase borrows on
method autorefs in #49348. r'ing @pnkfelix to keep things off Niko's plate so he can make this redundant, and @pnkfelix is familiar with the code.

Fixes #49635
Fixes #49662

r? @pnkfelix
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.

5 participants