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

d5c3f45
Opened by Niko Matsakis at 2022-03-22 07:48:36

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.

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

    Álvaro Cuesta at 2014-11-02 01:58:59

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

    Sean McArthur at 2015-04-22 04:15:34

  3. Triage: @seanmonstar s playpen still fails today.

    Steve Klabnik at 2016-11-29 19:23:35

  4. Triage: no change

    Steve Klabnik at 2018-09-24 17:31:18

  5. Triage: no change

    Maayan Hanin at 2022-03-22 07:48:36