rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.92k stars 12.67k forks source link

Expected type for closure arguments not inferred through two nested func calls #16473

Open nikomatsakis opened 10 years ago

nikomatsakis commented 10 years ago

Test case:

struct Foo;

struct FooClosure<'a>(Option<|&mut Foo|:'a>);

fn foo(closure: |&mut Foo, &int|:'static, inputs: &[int]) {
    for input in inputs.iter() {
        FooClosure(Some(|f| closure(f, input)));
    }
}

fn main() {}

This yields an error:

/home/nmatsakis/tmp/foo.rs:7:20: 7:47 error: mismatched types: expected `core::option::Option<|&mut Foo|>` but found `core::option::Option<|&mut Foo|>` (expected concrete lifetime, but found bound lifetime parameter )                                                                                                                  

which occurs because we did not propagate the expected type and thus instantiated the type of the closure parameter with a fresh variable, rather than using a bound region. Another solution to this issue would be finding a better way to decide when we can generalize lifetimes in closure parameters, rather than relying on the closure type.

There is a workaround: just manually annotate the parameter type.

alvaro-cuesta commented 9 years ago

Found a similar bug, but wanted to check since I'm not sure if it's a simplified version of this issue or I should open a new one.

Test case (playpen):

fn process_123(processor: |&[u8]| -> Vec<u8>) -> Vec<u8> {
    processor(&[1, 2, 3])
}

fn main() {
    let make_vec = |input/*: &_*/| {  // UNCOMMENT THIS TO FIX
        let mut vector = Vec::new();
        vector.push_all(input);
        vector
    };

    assert_eq!(process_123(make_vec), vec![1, 2, 3]);
}

Yields error:

mismatched types: expected `|&[u8]| -> collections::vec::Vec<u8>`, found `|&[_]| -> collections::vec::Vec<_>` (expected concrete lifetime, found bound lifetime parameter )

As you can see, explicitly typing the closure param as &_ fixes the issue. My intuition is similar to yours: there's a problem when propagating the expected type.

seanmonstar commented 9 years ago

Assuming this is what is causing this playpen to fail: http://is.gd/E7sskd

This makes the easy case for a hyper Server fail, which would be a major bummer for those trying hyper at 1.0.0:

Server::http(|req, res| {

}).listen(8080);
steveklabnik commented 7 years ago

Triage: @seanmonstar s playpen still fails today.

steveklabnik commented 6 years ago

Triage: no change

Spoonbender commented 2 years ago

Triage: no change