Skip to content

Return impl for<'a> Fn(&'a) incorrectly rejected for closures #105528

Open
@verglasz

Description

@verglasz

I ran into a compile error while writing some iterator adapters involving building (types containing) closures in a function returning (types containing) impl for<'a> Fn(&'a), which I narrowed down to the following example:

fn const_if_unit(input: bool) -> impl for<'a> FnOnce(&'a ()) {
    if input {
        |_| ()
    } else {
        |_| ()
    }
}

This function fails to typecheck, seemingly because the return type is inferred to only implement Fn(&()) rather than for <'a> Fn(&'a ()).
Note that replacing the body with an unconditional |_| () instead works as expected, and using functions rather than closures also compiles without errors, see playground for more examples.
I'm on Rust 1.65.0 but the playground shows the same happening in beta and nightly too.

Seems related to #99991 and maybe #98437 (that I could find), but they are about trait bounds in input types rather than return impl, and here it actually does work as long as the closure is returned unconditionally, though feel free to close as duplicate if it's ultimately the same root issue.

`cargo check` output

error[E0308]: mismatched types
 --> repro/src/main.rs:2:19
  |
2 |       if input {
  |  ___________________^
3 | |         |_| ()
4 | |     } else {
  | |_____^ one type is more general than the other
  |
  = note: expected trait `for<'b> FnOnce<(&'b u8,)>`
             found trait `FnOnce<(&u8,)>`

error: implementation of `FnOnce` is not general enough
 --> repro/src/main.rs:2:19
  |
2 |       if input {
  |  ___________________^
3 | |         |_| ()
4 | |     } else {
  | |_____^ implementation of `FnOnce` is not general enough
  |
  = note: `fn(&'2 u8)` must implement `FnOnce<(&'1 u8,)>`, for any lifetime `'1`...
  = note: ...but it actually implements `FnOnce<(&'2 u8,)>`, for some specific lifetime `'2`

error: higher-ranked lifetime error
 --> repro/src/main.rs:4:12
  |
4 |       } else {
  |  ____________^
5 | |         |_| ()
6 | |     }
  | |_____^

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-coercionsArea: implicit and explicit `expr as Type` coercionsC-bugCategory: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions