ITIFTR and opaque type

I use Nightly Rust do this:

#![feature(impl_trait_in_fn_trait_return)]

fn curry<P1, P2, R>(f: impl FnOnce(P1, P2) -> R) -> impl FnOnce(P1) -> impl FnOnce(P2) -> R {
    |p1| |p2| f(p1, p2)
}

Getting error messages:

error: concrete type differs from previous defining opaque type use
 --> src/lib.rs:4:10
  |
4 |     |p1| |p2| f(p1, p2)
  |          ^^^^^^^^^^^^^^ expected `impl FnOnce(P2) -> R`, got `[closure@src/lib.rs:4:10: 4:14]`
  |
note: previous use here
 --> src/lib.rs:4:5
  |
4 |     |p1| |p2| f(p1, p2)
  |     ^^^^^^^^^^^^^^^^^^^

error[E0720]: cannot resolve opaque type
 --> src/lib.rs:3:72
  |
3 | fn curry<P1, P2, R>(f: impl FnOnce(P1, P2) -> R) -> impl FnOnce(P1) -> impl FnOnce(P2) -> R {
  |                                                                        ^^^^^^^^^^^^^^^^^^^^ cannot resolve opaque type

For more information about this error, try `rustc --explain E0720`.
error: could not compile `playground` due to 2 previous errors

When I first saw this feature, I thought it was used to do just that.

But this compilation error makes me not know what it is for, so I would like to ask you for advice.

1 Like

It could be possible that you discovered an error in the implementation of #99697. I experimented with your example and the moment I add generics to the curry function, compilation fails, even if I don't even use the generic type.

For example:

#![feature(impl_trait_in_fn_trait_return)]

fn curry() -> impl FnOnce(u8) -> impl FnOnce(u8) -> impl Copy {
    |r| |x| x
}

compiles, but:

#![feature(impl_trait_in_fn_trait_return)]

fn curry<T>() -> impl FnOnce(u8) -> impl FnOnce(u8) -> impl Copy {
    |r| |x| x
}

Fails.

Error message
  Compiling playground v0.0.1 (/playground)
error: concrete type differs from previous defining opaque type use
 --> src/lib.rs:4:9
  |
4 |     |r| |x| x
  |         ^^^^^ expected `impl FnOnce(u8) -> impl Copy`, got `[closure@src/lib.rs:4:9: 4:12]`
  |
note: previous use here
 --> src/lib.rs:4:5
  |
4 |     |r| |x| x
  |     ^^^^^^^^^

error[E0720]: cannot resolve opaque type
 --> src/lib.rs:3:37
  |
3 | fn curry<T>() -> impl FnOnce(u8) -> impl FnOnce(u8) -> impl Copy {
  |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot resolve opaque type

error: concrete type differs from previous defining opaque type use
 --> src/lib.rs:4:13
  |
4 |     |r| |x| x
  |             ^ expected `impl Copy`, got `u8`
  |
note: previous use here
 --> src/lib.rs:4:5
  |
4 |     |r| |x| x
  |     ^^^^^^^^^

error[E0720]: cannot resolve opaque type
 --> src/lib.rs:3:56
  |
3 | fn curry<T>() -> impl FnOnce(u8) -> impl FnOnce(u8) -> impl Copy {
  |                                                        ^^^^^^^^^ cannot resolve opaque type

For more information about this error, try `rustc --explain E0720`.
error: could not compile `playground` due to 4 previous errors
1 Like
#![feature(impl_trait_in_fn_trait_return)]

fn curry(f: impl FnOnce(u8, u8) -> u8) -> impl FnOnce(u8) -> impl FnOnce(u8) -> u8 {
    |u1| move |u2| f(u1, u2)
}

The above code does not compile.

Error Message
error: concrete type differs from previous defining opaque type use
 --> src/lib.rs:4:10
  |
4 |     |u1| move |u2| f(u1, u2)
  |          ^^^^^^^^^^^^^^^^^^^ expected `impl FnOnce(u8) -> u8`, got `[closure@src/lib.rs:4:10: 4:19]`
  |
note: previous use here
 --> src/lib.rs:4:5
  |
4 |     |u1| move |u2| f(u1, u2)
  |     ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0720]: cannot resolve opaque type
 --> src/lib.rs:3:62
  |
3 | fn curry(f: impl FnOnce(u8, u8) -> u8) -> impl FnOnce(u8) -> impl FnOnce(u8) -> u8 {
  |                                                              ^^^^^^^^^^^^^^^^^^^^^ cannot resolve opaque type

impl Trait in function arguments are anonymous type parameters and according to the book:

That is, impl Trait in argument position is syntactic sugar for a generic type parameter like <T: Trait>, except that the type is anonymous and doesn't appear in the GenericParams list.

So basically your example is desugared to something like:

fn curry<F: FnOnce(u8, u8) -> u8>(f: F) -> impl FnOnce(u8) -> impl FnOnce(u8) 

which makes your example similar to this one:

1 Like