Uh oh!
There was an error while loading. Please reload this page.
NLL: Limit two-phase borrows to autoref-introduced borrows - #47489
Conversation
rust-highfive
commented
Jan 16, 2018
(rust_highfive has picked a reviewer for you, use r? to override) |
pnkfelix
commented
Jan 16, 2018
(Incidentally, I keep toying with the idea of adding an opt-in way to write MIR directly, something analogous to how asm.js lets one write low-level operations using Javascript syntax.) |
pnkfelix
commented
Jan 16, 2018
bors
commented
Jan 16, 2018
☔ The latest upstream changes (presumably #47209) made this pull request unmergeable. Please resolve the merge conflicts. |
There was a problem hiding this comment.
I think I expected us to push these flags even further back, to type check. I'm a bit wary that we may introduce adjustments for reasons that are not "autoref-autoderef in conjunction with method calls".
For example, does this type-check?
fnfoo(x:&mutu32,y:u32){*x += y;}fnbar(x:&mutu32){foo(x,*x)}I think it might, because we get an implicit &mut *x on the call, and that might be treated as two-phase. Similarly let x: &mut u32 = x or something like that.
There was a problem hiding this comment.
(Actually, I suppose we could conceivably thread a bit of state down during HAIR lowering to indicate whether the expression being coerced is in receiver position.)
There was a problem hiding this comment.
I will figure out how to tighten the restriction. (As you have pointed out there may be different paths to getting there.)
There was a problem hiding this comment.
(Also that example you have does leak through in the current state of this PR, so I will also add it as a compile-fail test)
There was a problem hiding this comment.
(Though of course the example you give is sound; its just code that might surprise some if it passes, right? And anyway I agree that for our first deployment we should reject it)
There was a problem hiding this comment.
bikeshed: name looks confusing, I would prefer BorrowMutability.
There was a problem hiding this comment.
(Hey look who it is!)
will do!
There was a problem hiding this comment.
bikeshed: I would prefer the "operational" always_allow_2phi to the descriptive introduced_via_autoref.
There was a problem hiding this comment.
please call it "two phase", but yes that's a good point. Operational is often better.
There was a problem hiding this comment.
okay, this distinction doesn't matter to me, so I'll make this change.
pnkfelix
commented
Jan 23, 2018
(sorry this is taking so long; I keep hitting #47381 and so that is slowing my progress |
kennytm
commented
Jan 31, 2018
Marking as blocked by #47381. |
pnkfelix
commented
Jan 31, 2018
(I'm hoping that now that I've rebased atop a |
pnkfelix
commented
Feb 6, 2018
@shepmaster I assume that you switched it from S-waiting-on-author to S-blocked because of #47381 ? Just wanted to confirm, as after rebasing atop newer master, that bug is no longer blocking me. (And thus I am now switching it back to S-waiting-on-author) |
shepmaster
commented
Feb 6, 2018
That's right! |
5154cc0 to
0c108b1Comparenikomatsakis
commented
Feb 6, 2018
@pnkfelix at first glance, changes look good but appveyor won't run because of the merge conflict |
0c108b1 to
a9af49eCompareThere was a problem hiding this comment.
heh I guess I should address this FIXME now that I have this working again
There was a problem hiding this comment.
(I think the test illustrates the kind of code that is being filtered out by not allowing two-phase borrows for index operators... I'll leave another comment with my thoughts on that test itself.)
There was a problem hiding this comment.
Important: even the generalized form tested by g2p/-Z two-phase-beyond-autoref (thus no longer connected to autoref) is still rejecting this example. Compare that against deref_coercion above...
There was a problem hiding this comment.
so the generalized (non-autoref-connected) g2p form starts allowing things like i[i[3]] = ...;
I don't know about other people, but I think ... that seems okay to allow...? (As in, it seems like a reasonable extension to consider, if not in the immediate release of two-phase borrows, then at some point in the future?)
There was a problem hiding this comment.
It works for normal slices, so it seems ok to me.
028ca2b to
5c8ff83Comparepnkfelix
commented
Feb 8, 2018
(skimming over the commit series, I realize now that some of the last minute refactorings I did yesterday brought the code into a state where I could get the diff much smaller. I'll take care of that now.) |
…o autoref. This is foundation for issue 46747 (limit two-phase borrows to method-call autorefs).
Added `-Z two-phase-beyond-autoref` to bring back old behavior (mainly to allow demonstration of desugared examples). Updated tests to use aforementioned flag when necessary. (But in each case where I added the flag, I made sure to also include a revision without the flag so that one can readily see what the actual behavior we expect is for the initial deployment of NLL.)
…se borrow info too. Namely, the mutable borrows also carries a flag indicating whether they should support two-phase borrows. This allows us to thread down, from the point of the borrow's introduction, whether the particular adjustment that created it is one that yields two-phase mutable borrows.
5c8ff83 to
b55cd8cComparepnkfelix
commented
Feb 8, 2018
@nikomatsakis okay I am done polishing; you should be safe to do a review without me |
nikomatsakis
commented
Feb 8, 2018
@bors r+ |
bors
commented
Feb 8, 2018
📌 Commit b55cd8c has been approved by |
bors
commented
Feb 9, 2018
NLL: Limit two-phase borrows to autoref-introduced borrows This imposes a restriction on two-phase borrows so that it only applies to autoref-introduced borrows. The goal is to ensure that our initial deployment of two-phase borrows is very conservative. We want it to still cover the `v.push(v.len());` example, but we do not want it to cover cases like `let imm = &v; let mu = &mut v; mu.push(imm.len());` (Why do we want it to be conservative? Because when you are not conservative, then the results you get, at least with the current analysis, are tightly coupled to details of the MIR construction that we would rather remain invisible to the end user.) Fix#46747 I decided, for this PR, to add a debug-flag `-Z two-phase-beyond-autoref`, to re-enable the more general approach. But my intention here is *not* that we would eventually turn on that debugflag by default; the main reason I added it was that I thought it was useful for writing tests to be able to write source that looks like desugared MIR.
bors
commented
Feb 9, 2018
☀️ Test successful - status-appveyor, status-travis |
This imposes a restriction on two-phase borrows so that it only applies to autoref-introduced borrows.
The goal is to ensure that our initial deployment of two-phase borrows is very conservative. We want it to still cover the
v.push(v.len());example, but we do not want it to cover cases likelet imm = &v; let mu = &mut v; mu.push(imm.len());(Why do we want it to be conservative? Because when you are not conservative, then the results you get, at least with the current analysis, are tightly coupled to details of the MIR construction that we would rather remain invisible to the end user.)
Fix#46747
I decided, for this PR, to add a debug-flag
-Z two-phase-beyond-autoref, to re-enable the more general approach. But my intention here is not that we would eventually turn on that debugflag by default; the main reason I added it was that I thought it was useful for writing tests to be able to write source that looks like desugared MIR.