-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
nll part 5 #46733
nll part 5 #46733
Conversation
☔ The latest upstream changes (presumably #46537) made this pull request unmergeable. Please resolve the merge conflicts. |
Before, we would always have a `Some` ClosureRegionRequirements if we were inferring values for a closure. Now we only do is it has a non-empty set of outlives requirements.
This allows us to re-use the `normalize` method on `TypeCheck`, which is important since normalization may create fresh region variables. This is not an ideal solution, though, since the current representation of "liveness constraints" (a vector of (region, point) pairs) is rather inefficient. Could do somewhat better by converting to indices, but it'd still be less good than the older code. Unclear how important this is.
In the future, `check_type_tests` will also potentially propagate constriants to its caller.
The existing flags did not consider `'static` to be "free". This then fed into what was "erasable" -- but `'static` is most certainly erasable.
Currently, we only propagate type tests that exclude all regions from the type.
This is needed to allow the `ClosureRegionRequirements` to capture types that include regions.
The input/output types found in `UniversalRegions` are not normalized. The old code used to assign them directly into the MIR, which would lead to errors when there was a projection in a argument or return type. This also led to some special cases in the `renumber` code. We now renumber uniformly but then pass the input/output types into the MIR type-checker, which equates them with the types found in MIR. This allows us to normalize at the same time.
Turns out this works but we had no test targeting it.
744846a
to
0f8ef0c
Compare
The prior messages were not stable across platforms.
/// checks that they meet certain extra criteria. If not, an error | ||
/// can be issued. | ||
/// | ||
/// One reason for this is that these type tests always boil down to a |
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 is not quite correct - consider <&'α T as Foo>::Bar: 'x
where 'α
is an inference variable. IIRC at least AST borrowck will convert this to 'α: 'x
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. When I was writing this, I thought I remembered that we always issued hard region constraints in that case (over-constrained). But I remembered later that we do not. Still not crazy about this behavior, but the right fix is a pain of course. =) (For later...)
/// Once regions have been propagated, this method is used to see | ||
/// whether any of the constraints were too strong. In particular, | ||
/// we want to check for a case where a universally quantified | ||
/// region exceeded its bounds. Consider: |
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.
Wrong comment: this code is about type tests - T: 'a
- not region tests ('a: 'b
).
@@ -64,12 +69,14 @@ pub struct UniversalRegions<'tcx> { | |||
/// closure type, but for a top-level function it's the `TyFnDef`. | |||
pub defining_ty: Ty<'tcx>, | |||
|
|||
/// The return type of this function, with all regions replaced | |||
/// by their universal `RegionVid` equivalents. | |||
/// The return type of this function, with all regions replaced by |
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 think you mean "This type contains explicit free regions" ? Nope, this means "this type might contain associated types".
/// extern. This is an important category, because these regions | ||
/// can be referenced in `ClosureRegionRequirements`. | ||
pub fn is_non_local_free_region(&self, r: RegionVid) -> bool { | ||
self.region_classification(r) == Some(RegionClassification::Local) |
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.
is there a missing !
here?
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 -- but this also appears to be dead-code. I thought I remembered finding (and fixing...) this particular bug, but I can't seem to find that in my other branches now. Anyway, I will remove these bits of dead code I think.
Only `is_local_free_region` is used.
Pushed various commits to address the bits of feedback. |
// - `'static: 'a` | ||
// - `'static: 'b` | ||
// | ||
// First, let's assume that `r` is some existential |
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.
Isn't the inferred value of a region required to be closed under the subregion relationship? I mean, semantically it is (i.e. the included value can't be 'static
without including all other free regions) but this talks as if structurally it is not.
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.
That would mean an inferred value of {'a, 'static}
does not make sense.
Also, we only care about the state of the inference variable right after the closure returns, so CFG nodes - which here come from within the closure, since that is what we are type-checking - are not important, because they are "in our past".
// | ||
// Now let's consider the inferred value `{'a, 'b}`. This | ||
// means `r` is effectively `'a | 'b`. I'm not sure if | ||
// this can come about, actually, but assuming it did, we |
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.
Uselessly, you could have something like this:
fn foo<'a, 'b, 'c>(x: Cell<&'a u8>, y: Cell<&'b u8>) -> Option<Cell<&'c u8>>
where 'c: 'a, 'c: 'b
{
None
}
So I think the Therefore, |
📌 Commit 1816ede has been approved by |
⌛ Testing commit 1816ede with merge dbe91562a03fdcab13bd1170c589d38de7442a3e... |
💔 Test failed - status-travis |
Huh. The failure seems to be:
|
@bors p=1 -- NLL is super high priority |
⌛ Testing commit 1816ede with merge 46833922ac11fdcf82ca4c31ac0948a819783dcd... |
💔 Test failed - status-appveyor |
cc @rust-lang/infra -- I can't quite tell why the appveyor failed, but the log seems to mysteriously stop at 2 hour 58 minutes. Is there a 3h timeout? Is there a possibility that this is within standard variation? (Or perhaps the PR adds new tests or otherwise slows things down?) |
@bors: retry Yeah we've got a 3 hour time limit on AppVeyor, sometimes it just seems to randomly slow down. Let's see if it happens again. |
…ielb1 nll part 5 Next round of changes from the nll-master branch. Extensions: - we now propagate ty-region-outlives constraints out of closures and into their creator when necessary - we fix a few ICEs that can occur by doing liveness analysis (and the resulting normalization) during type-checking - we handle the implicit region bound that assumes that each type `T` outlives the fn body - we handle normalization of inputs/outputs in fn signatures Not included in this PR (will come next): - handling `impl Trait` - tracking causal information - extended errors r? @arielb1
☀️ Test successful - status-appveyor, status-travis |
Next round of changes from the nll-master branch.
Extensions:
T
outlives the fn bodyNot included in this PR (will come next):
impl Trait
r? @arielb1