-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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 error on closure, but not on equivalent function #55526
Comments
Using the above playground:
Attempting to then use
|
I am curious whether the lifetime elision rules are part of the reason we see the discrepancy here. |
(though my personal suspicion is that NLL is buggy and ignoring the constraint that the the input and the output types on the closure are supposed to use the same lifetime.) |
e..g this does compile under NLL: fn _v_closure<'a: 'b, 'b>(_: &'b (), _: &'a ()) {
let _v_lambda = |v: &'a Vec<String>| -> Vec<&'b String> {
v.iter().chain(v.iter()).collect::<Vec<&String>>()
};
} |
and, just in case someone wants a potentially more useful workaround, this also compiles today under NLL: fn _v_closure<'a, 'b>(_: &'b (), _: &'a ())
-> impl Fn(&'a Vec<String>) -> Vec<&'b String>
where 'a: 'b
{
|v| { v.iter().chain(v.iter()).collect::<Vec<&String>>() }
} |
triage: P-high (because this looks annoying and perhaps very misleading/frustrating to end users), but not Release milestone. I'm opting to not put it on the Release milestone because I do not think we would need to back port a hypothetical fix for this to the beta channel; this is an instance where the NLL migration mode saves us from that pain. |
triage: assigning to self to look at either Friday or Monday. |
I didn't get a chance to look at this (before I go on leave for ~2 weeks tomorrow). Its still P-high, but it bears repeating that NLL migration gives us breathing room here (i.e. other P-high items should probably be P-higher) |
triage: no change since last week |
triage: no change since last week (its continues to be the case that NLL migration gives us breathing room here). I'm now back from PTO and have thus self-assigned this. |
FYI the problem even arises with a trivialized example like this: fn main() {
let _v_lambda = |v: &str| -> &str { v };
}
fn _v_fn(v: &str) -> &str {
v
} |
Ah, its also worth noting that the following take-away from @memoryruins 's comment above: Even with AST-borrowck, you cannot use the I'm in the process of teasing out what our region-inference is supposed to do in this case. What it seems we do is just plug a region-inference variable into the return type (I think this makes sense, since we cannot apply the same lifetime elision rules here that we do to fn _two_arg<'a, 'b>(a: &'a str, b: &'b str) -> &'b str {
let _has_free = |_x: &str| b;
_has_free(a)
} ) |
Update: this comment and the two following it are based on a flawed testing methodology. Don't believe them. Original comment follows As an experiment, I decided to check if this case has always been failing for NLL. It turns out that we used to accept the closure written here, back in rustc 1.27.0-nightly (7360d6d 2018-04-15). And then it breaks in rustc 1.27.0-nightly (65d201f 2018-04-18) The changes there are captured by this series of bors merges: % git log 7360d6d..65d201f --format=oneline --author=bors |
Okay I have now confirmed that this bug was injected by PR #49836. (Which is odd because I believe that was intended to be a pure refactoring, and indeed my informal review of its commits, at least based on their log messages, reinforces that belief...) |
In fact the bug was specifically injected by commit 45d281d (!), which definitely sounded trivial to me. This is actually great news, since it increases the likelihood that I'll be able to identify the source of the regression and find a smallish fix. |
Ugh, I just realized: my testing methodology was flawed. I was using But PR #49836 specifically switched the way you opt into NLL. Prior to that PR, you needed to pass So of course my (flawed) testing was claiming that PR #49836 injected the bug. 😞 (I have since confirmed that this bug appears to have always been present as part of NLL.) |
@Avi-D-coder can you share information about the original code where you encountered this regression? In particular, based on my investigation of what the AST-borrowck actually does for a case like this, it is not clear to me whether it is ever going to produce a case where you can actually call the (That is, even though it seems like |
@pnkfelix I didn't want to write an extremely long type signature for a locally scoped function, so I used a closure. Since your work around exists, this is not the most important issue. When I came across it seemed extremely counter intuitive, especially given how trivial code giving rise to variants of this issue can be. I still feel this is counter intuitive. Perhaps function inference rules could be applied where the closure does not capture. If not a specialized error would be useful. |
@Avi-D-coder ah I see. So if I understand you correctly, you were experimenting with the change to a closure rather than a locally-scoped fn (and were using NLL at the time), but you never had with a complete piece of example code that 1. included a call to the introduced closure and 2. compiled and run properly under AST-borrowck. Is that right? I agree the case is counter-intuitive, and I would like to do better here (either in terms of providing better diagnostic feedback, or simply accepting the code as written, at least with no calls to the closure). But I just wanted to know how dire the underlying problem might be, in terms of whether we might be breaking code where the closure in question is actually being called. |
Discussed quite a bit with @nikomatsakis on zulip The main takeaways we have currently:
|
I'm going to demote this to P-medium. The short-term plan is not to make NLL accept this code with no return type annotation (i.e. |
Update: I closed issue #56537 because it is not as trivially actionable as I had originally thought (see the comment thread there for an explanation why). I now think the clearest path forward here is the following suggestion (taken from #56537 (comment)):
|
also, given that @nikomatsakis believes that the best way to synchronize behavior between AST-borrowck and NLL for the original example from the description on this issue (#55526) is to change AST-borrowck (see PR #55988), I think that means this is not actually an NLL-complete issue... (That is, It is either an issue we should just close, perhaps as "wontfix"/"notabug", or at least tag as NLL-deferred.) I'm going to change the label for NLL-deferred for now. |
triaging for #56754. leaving as P-medium. Looping in T-lang. |
Triage: The AST borrow checker has been removed. Closing. |
With the 2018 edition on nightly or
#![feature(nll)]
:(Playground)
Errors:
The text was updated successfully, but these errors were encountered: