Skip to content

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

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.

Activity

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

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

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions