rust-lang / rust-lang/rust

Confusing behavior and mismatched error reports for `impl_trait_in_fn_trait_return` && `type_alias_impl_trait`

Open
#122,279 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug F-impl_trait_in_fn_trait_return F-type_alias_impl_trait T-compiler
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}")))
}

playground

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.