Repository navigation
NLL accepts higher-ranked subtype that non-NLL rejects #57642
Copy link
Copy link
Closed
Labels
A-NLLArea: Non-lexical lifetimes (NLL)Area: Non-lexical lifetimes (NLL)A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.Call for participation: An issue has been fixed and does not reproduce, but no test has been added.P-mediumMedium priorityMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
The following code example (playground)
// #![feature(nll)]
trait X {
type G;
fn make_g() -> Self::G;
}
impl<'a> X for fn(&'a ()) {
type G = &'a ();
fn make_g() -> Self::G {
&()
}
}
trait Y {
type F;
fn make_f() -> Self::F;
}
impl<T> Y for fn(T) {
type F = fn(T);
fn make_f() -> Self::F {
|_| {}
}
}
// Always an error, but the message is bad
fn higher_ranked_region_has_lost_its_binder() {
let x = <fn (&())>::make_g();
}
// Works, but only with feature(nll)
fn magical() {
let x = <fn (&())>::make_f();
}produces the output
Details
error[E0308]: mismatched types
--> src/lib.rs:31:13
|
31 | let x = <fn (&())>::make_g();
| ^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected type `X`
found type `X`
error[E0308]: mismatched types
--> src/lib.rs:36:13
|
36 | let x = <fn (&())>::make_f();
| ^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected type `Y`
found type `Y`
The second example also unexpectedly compiles in full NLL mode.
Metadata
Metadata
Assignees
Labels
A-NLLArea: Non-lexical lifetimes (NLL)Area: Non-lexical lifetimes (NLL)A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.Call for participation: An issue has been fixed and does not reproduce, but no test has been added.P-mediumMedium priorityMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Activity
[-]Unclear errors when higher ranked lifetime escapes its binder[/-][+]NLL accepts higher-ranked subtype that non-NLL rejects[/+]nikomatsakis commentedon Jan 17, 2019
I renamed the title to focus on the part I would most like to investigate, which is why this function works but only with feature-nll:
That seems like a blocker to disabling migration mode.
pnkfelix commentedon Feb 27, 2019
cc #58781
pnkfelix commentedon Feb 27, 2019
marking P-medium to reflect that this is solely about
#![feature(nll)], not migration mode (#58781). When the latter becomes higher priority, this will likewise be raised up.matthewjasper commentedon Mar 27, 2019
Update: this is only an issue now with
-Zno-leak-checkpnkfelix commentedon Mar 29, 2019
ccblocks #594901 remaining item
oli-obk commentedon May 24, 2019
Diagnostics triage: this is not a diagnostics issue
Aaron1011 commentedon Aug 16, 2019
This is now a compiler error with
-Z no-leak-check:matthewjasper commentedon Aug 16, 2019
Yes, but it should be two compiler errors, one in make_f and one on make_g.
Aaron1011 commentedon Aug 18, 2019
Looking at this further - why don't we want
magicalto compile? It looks perfectly correct to me.nikomatsakis commentedon Oct 9, 2019
Running this example with my branch from #65232 yields, among some other errors:
This error seems correct. If I had to guess the problem with NLL, though, I would guess that this is working because of the
'emptyrule -- in other words, we are inferringYto be implemented forfn(&'empty ())and we are (not incorrectly) deducing thatfn(&'empty()) = fn(&()). My branch rejects this because I specifically tried to disallow that. I am not entirely convinced that we should disallow this -- it's just that'emptydoesn't have a very natural analog in polonius (though you can make it make sense). In fact, the idea of'emptyis kind of useful, or could be, so it may be that we want to accept it.If we want to disallow this example, I think we'll have to extend NLL to have a similarly "graded" notion of
'empty. I imagine the way to do this would be to extend the set of elements to include "empty" elements in each universe we create, and then permit these empty elements get added to all the "free regions" in the root universe.Aaron1011 commentedon May 27, 2020
On the latest nightly, passing
-Z borrowck=mir -Z no-leak-checkcauseshigher_ranked_region_has_lost_its_binderandmagicalto producehigher-ranked subtype error.I think this is now purely a diagnostic issue, rather than a soundness issue.
Add test for bad NLL higher-ranked subtype
Rollup merge of rust-lang#78298 - Aaron1011:fix/nll-ranked-test, r=Ma…