Skip to content

Incomprehensible error message when inference fails for closure #24680

Closed
@seanmonstar

Description

@seanmonstar
Contributor
struct Foo<'a> {
    _s: &'a str
}

struct Bar<H: Handler> {
    handler: H
}

trait Handler {
    fn handle<'a>(&'a self, foo: Foo<'a>);
}

impl<F> Handler for F where F: Fn(Foo) {
    fn handle<'a>(&'a self, foo: Foo<'a>) {
        self(foo)
    }
}

fn main() {
    let foo = Foo { _s: "foo" };
    let bar = Bar { handler: |_f /*: Foo*/| {} }; // uncomment to work
    (bar.handler)(foo);
}

Gives:

error: type mismatch: the type `[closure test.rs:8:23: 20:6]` implements the trait `core::ops::Fn<(_, _)>`, but the trait `for<'r,'r,'r> core::ops::Fn<(hyper::server::request::Request
<'r, 'r>, hyper::server::response::Response<'r>)>` is required (expected concrete lifetime, found bound lifetime parameter ) [E0281]

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).

Activity

reem

reem commented on Apr 22, 2015

@reem
Contributor

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.

Ryman

Ryman commented on Apr 23, 2015

@Ryman
Contributor

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.

brson

brson commented on Apr 23, 2015

@brson
Contributor

Nominating because I hit this quickly trying to use Iron, the error was impenetrable and I had to ask for help.

bstrie

bstrie commented on Apr 23, 2015

@bstrie
Contributor

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(|_| ());
}
changed the title [-]Inference fails for closure[/-] [+]Incomprehensible error message when inference fails for closure[/+] on Apr 23, 2015
nikomatsakis

nikomatsakis commented on Apr 23, 2015

@nikomatsakis
Contributor

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.

pnkfelix

pnkfelix commented on Apr 23, 2015

@pnkfelix
Member

P-high : provide better feedback in the error message to guide the user towards adding type annotations on the closure arguments.

Ryman

Ryman commented on Apr 23, 2015

@Ryman
Contributor

@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?

28 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-closuresArea: Closures (`|…| { … }`)A-diagnosticsArea: Messages for errors, warnings, and lintsA-type-systemArea: Type systemP-mediumMedium priority

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @steveklabnik@seanmonstar@kornelski@brson@nikomatsakis

      Issue actions

        Incomprehensible error message when inference fails for closure · Issue #24680 · rust-lang/rust