Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upIncomprehensible error message when inference fails for closure #24680
Comments
This comment has been minimized.
This comment has been minimized.
|
cc @aturon @nikomatsakis do you think it would be feasible to fix this by the 1.0 release? It's a pretty unfortunate papercut for both iron and hyper. I remember I recently helped @brson with this problem when he was using iron. |
steveklabnik
added
A-typesystem
A-closures
labels
Apr 22, 2015
This comment has been minimized.
This comment has been minimized.
|
Very similar case based on nickel's usage of hyper: #[allow(dead_code)]
struct Bar<'a, 'b> {
a: &'a (),
b: &'b ()
}
#[allow(dead_code)]
struct Qux<'a> {
a: &'a ()
}
#[allow(dead_code)]
struct Foo<'a> {
a: &'a ()
}
trait Handler {
fn handle<'a, 'k>(&'a self, Bar<'a, 'k>, Qux<'a>) -> Foo<'a>;
}
impl<F> Handler for F where F: for<'a, 'k> Fn(Bar<'a, 'k>, Qux<'a>) -> Foo<'a> + Sync + Send {
fn handle<'a, 'k>(&'a self, req: Bar<'a, 'k>, res: Qux<'a>) -> Foo<'a> {
self(req, res)
}
}
fn call_handler<H: Handler>(h: H) {
println!("call_handler");
h.handle(Bar { a: &(), b: &() }, Qux { a: &() });
}
fn call_closure<F: for<'a, 'k> Fn(Bar<'a, 'k>, Qux<'a>) -> Foo<'a> + Sync + Send>(f: F) {
println!("call_closure");
f(Bar { a: &(), b: &() }, Qux { a: &() });
}
fn wrapped_call_handler<F: for<'a, 'k> Fn(Bar<'a, 'k>, Qux<'a>) -> Foo<'a> + Sync + Send>(f: F) {
println!("wrapped_call_handler");
call_handler(f)
}
fn main() {
// These work
call_closure(|_bar, qux| Foo { a: qux.a });
wrapped_call_handler(|_bar, qux| Foo { a: qux.a });
// These fail
// 'Type must be known'
//call_handler(|_bar, qux| Foo { a: qux.a });
// error: type mismatch resolving `for<'a,'k> <[closure <anon>:52:18: 52:57] as core::ops::FnOnce<(Bar<'a, 'k>, Qux<'a>)>>::Output == Foo<'a>`:
// expected bound lifetime parameter 'a
//call_handler(|_bar: Bar, qux: Qux| Foo { a: qux.a });
}
Playpen: http://is.gd/OEkSd4 The fact that it works with a wrapping function means it's possible to get things done with convenience macros, which suggests the compiler is at least able to reason about this at some level. |
Ryman
referenced this issue
Apr 23, 2015
Merged
feat(unboxed_closures): allow unboxed closures for handlers and error handlers #197
brson
added
the
I-nominated
label
Apr 23, 2015
This comment has been minimized.
This comment has been minimized.
|
Nominating because I hit this quickly trying to use Iron, the error was impenetrable and I had to ask for help. |
This comment has been minimized.
This comment has been minimized.
|
Accidentally duped this bug, but not before coming up with a more minimal test case: trait Foo {}
impl<T: Fn(&())> Foo for T {}
fn baz<T: Foo>(_: T) {}
fn main() {
baz(|_| ());
} |
nikomatsakis
changed the title
Inference fails for closure
Incomprehensible error message when inference fails for closure
Apr 23, 2015
This comment has been minimized.
This comment has been minimized.
|
I updated the title to reflect the fact that the error message is really bad here. It'd be nice to improve the inference, but in short term error message is priority. |
This comment has been minimized.
This comment has been minimized.
|
P-high : provide better feedback in the error message to guide the user towards adding type annotations on the closure arguments. |
pnkfelix
added
P-high
and removed
I-nominated
labels
Apr 23, 2015
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis Should I open another issue for the example I added? I don't know of any syntax available for type annotating the return type with lifetime requirements other than wrapping with a function? |
This comment has been minimized.
This comment has been minimized.
|
@Ryman I'm not sure whether opening a separate issue is necessary, as long as we make sure not to close this one with whatever error message improvements we land to address the P-high part of this. |
nikomatsakis
self-assigned this
Apr 30, 2015
KyleMayes
referenced this issue
May 20, 2015
Open
Cannot call a Box<FnBox(_)> with a reference parameter #25647
seanmonstar
referenced this issue
Jul 28, 2015
Closed
Incorrect lifetime inferred for closure #26937
This comment has been minimized.
This comment has been minimized.
|
I've ran into this with: fn main() {
let head = [(1,2), (3,4)];
let tail = [(4,5), (6,7)];
// missing .cloned()
let _:Vec<_> = head.iter().chain(tail.iter().map(|x|{(x.0+1,x.1+1)})).collect();
}
To Rust's credit "expected tuple, found &-ptr" was a good hint, but the error as a whole—with anon closure and iterator's guts—looks rather scary. |
This comment has been minimized.
This comment has been minimized.
|
Just ran into this while using hyper. It's completely incomprehensible and obscure. Is there a general fix to it? |
This comment has been minimized.
This comment has been minimized.
|
cc @brson is this roughly the case you were talking about today as well? |
This comment has been minimized.
This comment has been minimized.
|
Why does @bstrie's example give a better error message on stable than on beta and nightly? Neither beta nor nightly mention "type X implements Fn(...) but Fn(...) is required" |
This comment has been minimized.
This comment has been minimized.
|
I think there are two separable (and important) steps to take here---
|
nikomatsakis
referenced this issue
May 16, 2016
Closed
Error message for wrong number of arguments to a closure is bad #21857
This comment has been minimized.
This comment has been minimized.
|
cc @jonathandturner :) |
nikomatsakis
added
the
A-diagnostics
label
May 16, 2016
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis do you think that #26937 is a duplicate? |
This comment has been minimized.
This comment has been minimized.
|
@shepmaster well my feeling is that there are various intersecting problems here. First off, our output is pretty hard to read in general (because we don't do a good job "desugaring" the fn traits and so forth). Second, we don't handle higher-ranked messages very well. Finally, and least likely to be fixed, the inference has some limitations. So probably the answer is "yes", but maybe the right thing is to try and separate out the various problems into distinct issues that are more specific. |
brson
added
the
P-medium
label
Jun 23, 2016
This comment has been minimized.
This comment has been minimized.
|
triage: Dropped to P-medium just because the impact is relatively low. |
brson
removed
the
P-high
label
Jun 23, 2016
This comment has been minimized.
This comment has been minimized.
sanmai-NL
commented
Oct 22, 2016
|
@brson: I remember a forum thread on the future priorities for Rust, which I couldn't find back now. It referred to the 2016 survey that found that the biggest challenge for Rust adoption in the eyes of the users is the learning curve. I think there is a connection between learnability and how easily developers understand error messages. |
This comment has been minimized.
This comment has been minimized.
|
@sanmai-NL - absolutely error messages are an important part of learnability/usability. Here, I think priorities above medium mean that this bug severely impacts the correctness of code or stability of the compiler (crashing the compiler, for example). We're doing on-going work to address error messages holistically (eg #35233 as one example), so as a whole improving errors is a high priority for us, but as far as bug triage goes, individual bugs fall closer to the medium priority when weighed against much worse experiences (like compiler crashes or bad code) |
This comment has been minimized.
This comment has been minimized.
|
Yesterday, I answered a question on Stack Overflow about this issue. I tried to come up with an explanation for the error message, in the hope that it would provide some insight on how to fix the issue in the compiler. (I didn't debug the compiler compiling the code below or even read the compiler's source code to validate any of this, so my analysis could be completely wrong!) In case the above link becomes broken in the future, I'm reproducing parts of the question (from Jacob Brown) and of my answer below. The code that triggers the issue is this:
This code raises the following compiler errors:
What seems to happen is that the compiler implements I tried to replicate the error by defining a struct by hand (using unstable features). First, I defined the struct the correct way:
This Then, I broke it:
What I've done here is that I've removed the This fails to compile with the following errors:
The first error is the same, but instead of an internal name like The second error is different but means pretty much the same thing. |
This comment has been minimized.
This comment has been minimized.
|
I just hit this again in a new crate, which made me decide to make the generic be |
Deewiant
referenced this issue
Mar 10, 2017
Closed
Type inference falls over on lifetime-generic (HRTB) closures #39706
MortimerGoro
referenced this issue
Mar 31, 2017
Merged
Fix eglGetProcAddress for core OpenGL entrypoints #94
gmorenz
referenced this issue
Apr 15, 2017
Open
Confusing type error due to strange inferred type for a closure argument #41078
This comment has been minimized.
This comment has been minimized.
|
Closing in favor of #41078. |
seanmonstar commentedApr 22, 2015
Gives:
Playpen: http://is.gd/E7sskd
Couldn't tell if this was #16473, @reem thinks it might be different. Either way, this hurts using hyper's server easily:
Server::http(|req, res| {}).listen(8080).