Skip to content

The "type_alias_impl_trait" feature has problems handling lifetime parameters. #69137

Open
@steffahn

Description

@steffahn

I was starting with this function (which does compile on nightly):

#![feature(unboxed_closures)]
#![feature(type_alias_impl_trait)]
fn curry<'a, A: 'a, B, C, F: Fn(A, B) -> C> (f: &'a F)
    -> impl Fn<(A,), Output = impl FnOnce(B) -> C + 'a> + 'a
{
    move |a| move |b| f(a,b)
}

and wanted to give a name to its return type.
The straightforward approach seems to be (please correct me if the "right" way to do this is different):

#![feature(unboxed_closures)]
#![feature(type_alias_impl_trait)]
type Curried<'a, A: 'a, B, C, F: Fn(A, B) -> C>
 = impl Fn<(A,), Output = impl FnOnce(B) -> C + 'a> + 'a;

fn curry<'a, A: 'a, B, C, F: Fn(A, B) -> C> (f: &'a F)
    -> Curried<'a, A, B, C, F>
{
    move |a| move |b| f(a,b)
}

But the compiler is currently unhappy with the lifetimes. I'm getting the following.

error: cannot infer an appropriate lifetime
  --> src/main.rs:11:5
   |
6  |  = impl Fn<(A,), Output = impl FnOnce(B) -> C + 'a> + 'a;
   |                           ------------------------ this return type evaluates to the `'static` lifetime...
...
11 |     move |a| move |b| f(a,b)
   |     ^^^^^^^^^^^^^^^^^^^^^^^^ ...but this borrow...
   |
note: ...can't outlive the lifetime `'a` as defined on the function body at 8:10
  --> src/main.rs:8:10
   |
8  | fn curry<'a, A: 'a, B, C, F: Fn(A, B) -> C> (f: &'a F)
   |          ^^
help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 8:10
   |
9  |     -> Curried<'a, A, B, C, F> + '_
   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: cannot infer an appropriate lifetime
  --> src/main.rs:11:14
   |
6  |  = impl Fn<(A,), Output = impl FnOnce(B) -> C + 'a> + 'a;
   |                           ------------------------ this return type evaluates to the `'static` lifetime...
...
11 |     move |a| move |b| f(a,b)
   |              ^^^^^^^^^^^^^^^ ...but this borrow...
   |
note: ...can't outlive the lifetime `'a` as defined on the function body at 8:10
  --> src/main.rs:8:10
   |
8  | fn curry<'a, A: 'a, B, C, F: Fn(A, B) -> C> (f: &'a F)
   |          ^^
help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 8:10
   |
9  |     -> Curried<'a, A, B, C, F> + '_
   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

It works without the lifetimes (i.e. after removing parametrization over 'a and replacing all occurrences of 'a with 'static), like this:

#![feature(unboxed_closures)]
#![feature(type_alias_impl_trait)]
type Curried<A: 'static, B, C, F: Fn(A, B) -> C>
 = impl Fn<(A,), Output = impl FnOnce(B) -> C + 'static> + 'static;

fn curry<A: 'static, B, C, F: Fn(A, B) -> C> (f: &'static F)
    -> Curried<A, B, C, F>
{
    move |a| move |b| f(a,b)
}

use std::ops::Add;
fn main() {
    let x = curry(&i32::add)(1)(2);
    println!("{}", x); // prints "3"
}

Meta

Current behavior only since #67844 was fixed (after nightly-2020-02-14). Before that, this code triggered an ICE.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.F-type_alias_impl_trait`#[feature(type_alias_impl_trait)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    Status

    Can do after stabilization

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions