Skip to content

Region inference fails for closure parameter #17004

Closed
@bkoropoff

Description

@bkoropoff

Test

enum Chain<'a:'b, 'b> {
    Base(&'a int),
    Rec(&'a int, &'b Chain<'a,'b>)
}

fn call_with_rec<'a, 'b>(c: Chain<'a, 'b>,
                         x: &'a int,
                         f: <'c>|Chain<'a, 'c>|) {
    f(Rec(x, &c))
}

fn main() {
    let x = 0i;
    let y = 0i;

    call_with_rec(Base(&x), &y, |mut inner| {
        loop {
            match inner {
                Base(&x) => {
                    println!("Base({})", x);
                    break;
                },
                Rec(&x, &p) => {
                    println!("Rec({})", x);
                    inner = p;
                }
            }
        }
    });
}

Output

test.rs:18:19: 18:24 error: cannot infer an appropriate lifetime due to conflicting requirements
test.rs:18             match inner {
                             ^~~~~
test.rs:18:19: 18:24 note: first, the lifetime cannot outlive the expression at 18:18...
test.rs:18             match inner {
                             ^~~~~
test.rs:18:19: 18:24 note: ...so type `Chain<'_,'_>` of expression is valid during the expression
test.rs:18             match inner {
                             ^~~~~
test.rs:16:45: 29:6 note: but, the lifetime must be valid for an anonymous lifetime defined on the block at 16:44...
test.rs:16     call_with_rec(Base(&x), &y, |mut inner| {
test.rs:17         loop {
test.rs:18             match inner {
test.rs:19                 Base(&x) => {
test.rs:20                     println!("Base({})", x);
test.rs:21                     break;
           ...
test.rs:25:21: 25:26 note: ...so that the reference type `Chain<'_,'_>` does not outlive the data it points at
test.rs:25                     inner = p;
                               ^~~~~

Workaround

The program compiles successfully if the closure is converted into a named function.

enum Chain<'a:'b, 'b> {
    Base(&'a int),
    Rec(&'a int, &'b Chain<'a,'b>)
}

fn call_with_rec<'a, 'b>(c: Chain<'a, 'b>,
                         x: &'a int,
                         f: <'c>|Chain<'a, 'c>|) {
    f(Rec(x, &c))
}

fn helper<'a, 'b>(mut inner: Chain<'a, 'b>) {
    loop {
        match inner {
            Base(&x) => {
                println!("Base({})", x);
                break;
            },
            Rec(&x, &p) => {
                println!("Rec({})", x);
                inner = p;
            }
        }
    }
}

fn main() {
    let x = 0i;
    let y = 0i;

    call_with_rec(Base(&x), &y, helper);
}

cc @nikomatsakis

I'm not sure if inference is intended to work in this scenario. It's not particularly serious since there's an easy workaround.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions