Skip to content

Nested impl Trait for higher-order functions #76410

@nwtgck

Description

@nwtgck

Hi!

It will be nice to use impl Trait with higher-order functions like the following. But it occurs a compile error at impl Iterator<Item=u32>.

fn f1<F: FnMut(u32) -> u32>(a: u32) -> impl FnOnce(F) -> impl Iterator<Item=u32> /* <- compile error! */ {
    move |f: F| {
        (0..a).map(f)
    }
}

fn main() {
    let iter = f1(10)(|b| b * 2);
    for x in iter {
        println!("{:}", x);
    }
}

Nested impl Trait: https://doc.rust-lang.org/error-index.html#E0666

expected behavior/work around

Here is an expected behavior and a work around. We need to write the type explicitly like std::iter::Map<std::ops::Range<u32>, F> instead of impl Iterator<Item=u32>.

fn f1_with_explicit_type<F: FnMut(u32) -> u32>(a: u32) -> impl FnOnce(F) -> std::iter::Map<std::ops::Range<u32>, F> {
    move |f: F| {
        (0..a).map(f)
    }
}

fn main() {
    let iter = f1_with_explicit_type(10)(|b| b * 2);
    for x in iter {
        println!("{:}", x);
    }
}

Rust Playground

The output should be the following.

0
2
4
6
8
10
12
14
16
18

It will be harder to write and read the return type when we append other methods after the .map(f).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.C-feature-requestCategory: A feature request, i.e: not implemented / a PR.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions