Confusing behavior and mismatched error reports for `impl_trait_in_fn_trait_return` && `type_alias_impl_trait`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.2k
- PR merge metrics
- PR metrics pending
Description
I tried this code in my lib for curring function with generics:
#![feature(impl_trait_in_fn_trait_return)]
#![feature(type_alias_impl_trait)]
#![allow(clippy::let_and_return)]
use std::fmt::Display;
// Failed to compile
fn concat_1<T: Display>(a: T) -> impl FnOnce(T) -> impl FnOnce(T) -> String {
move |b: T| move |c: T| format!("{a} {b} {c}")
}
// Successful
fn concat_2<T: Display>(a: T) -> impl FnOnce(T) -> impl FnOnce(T) -> String {
let f = move |b: T| move |c: T| format!("{a} {b} {c}");
f
}
// Failed to compile
type A3<T: Display> = impl FnOnce(T) -> B3<T>;
type B3<T: Display> = impl FnOnce(T) -> String;
fn concat_3<T: Display>(a: T) -> A3<T> {
move |b: T| move |c: T| format!("{a} {b} {c}")
}
// Successful
type A4<T: Display> = impl FnOnce(T) -> B4<T>;
type B4<T: Display> = impl FnOnce(T) -> String;
fn concat_4<T: Display>(a: T) -> A4<T> {
let f = move |b: T| move |c: T| format!("{a} {b} {c}");
f
}
fn main() {}
Meta
rustc --version --verbose:
rustc 1.78.0-nightly (2d24fe591 2024-03-09)
binary: rustc
commit-hash: 2d24fe591f30386d6d5fc2bb941c78d7266bf10f
commit-date: 2024-03-09
host: x86_64-unknown-linux-gnu
release: 1.78.0-nightly
LLVM version: 18.1.0
Error output
- for
concat_1:
error: concrete type differs from previous defining opaque type use
--> src/main.rs:9:17
|
9 | move |b: T| move |c: T| format!("{a} {b} {c}")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `impl FnOnce(T) -> String`, got `{closure@src/main.rs:9:17: 9:28}`
|
note: previous use here
--> src/main.rs:9:5
|
9 | move |b: T| move |c: T| format!("{a} {b} {c}")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0720]: cannot resolve opaque type
--> src/main.rs:8:52
|
8 | fn concat_1<T: Display>(a: T) -> impl FnOnce(T) -> impl FnOnce(T) -> String {
| ^^^^^^^^^^^^^^^^^^^^^^^^ cannot resolve opaque type
For more information about this error, try `rustc --explain E0720`.
- for
concat_3:
error: concrete type differs from previous defining opaque type use
--> src/main.rs:22:17
|
22 | move |b: T| move |c: T| format!("{a} {b} {c}")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `B3<T>`, got `{closure@src/main.rs:22:17: 22:28}`
|
note: previous use here
--> src/main.rs:22:5
|
22 | move |b: T| move |c: T| format!("{a} {b} {c}")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Why there is E0720 error in a piece of code where recursion does not occur?
(An impl Trait type must be expandable to a concrete type that contains no impl Trait types.)
Temporary solution:
fn concat<T: Display + 'static>(a: T) -> Box<dyn FnOnce(T) -> Box<dyn FnOnce(T) -> String>> {
Box::new(move |b: T| Box::new(move |c: T| format!("{a} {b} {c}")))
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the four examples in src/main.rs with the nightly compiler version reported in the issue, and compare the diagnostics for concat_1 through concat_4. Use the E0720 output and the linked playground to trace the mismatch between nested opaque types and closures; done means the behavior is explained or the compiler reports the cases consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100