Skip to content

Closure type mismatch on higher-ranked bounds #51004

Open
@cramertj

Description

@cramertj

In the following code, identical impls for a concrete type, a fn type, and a closure exist yet the only the closure fails to meet the higher-ranked bound:

trait FnLt<'a> {
    fn apply(self, input: &'a u8) -> &'a u8;
}

// Struct impl
struct Foo;
impl<'a> FnLt<'a> for Foo {
    fn apply(self, input: &'a u8) -> &'a u8 {
        input
    }
}

// Closure impl
impl<'a, T> FnLt<'a> for T
where
    T: FnOnce(&'a u8) -> &'a u8,
{
    fn apply(self, input: &'a u8) -> &'a u8 {
        (self)(input)
    }
}

fn take_fn_lt(_: impl for<'a> FnLt<'a>) {}

fn main() {
    take_fn_lt(Foo); // Works
    
    fn foo(x: &u8) -> &u8 { x }
    take_fn_lt(foo); // Works
    
    take_fn_lt(|x: &u8| -> &u8 { x }); // Doesn't work
}

The error is this:

error[E0271]: type mismatch resolving `for<'a> <[closure@src/main.rs:31:16: 31:37] as std::ops::FnOnce<(&'a u8,)>>::Output == &'a u8`
  --> src/main.rs:31:5
   |
31 |     take_fn_lt(|x: &u8| -> &u8 { x }); // Doesn't work
   |     ^^^^^^^^^^ expected bound lifetime parameter 'a, found concrete lifetime
   |
   = note: required because of the requirements on the impl of `for<'a> FnLt<'a>` for `[closure@src/main.rs:31:16: 31:37]`
note: required by `take_fn_lt`
  --> src/main.rs:23:1
   |
23 | fn take_fn_lt(_: impl for<'a> FnLt<'a>) {}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Edit: the closure can be made to work through coercion to a fn pointer (which is unsurprising, since it's then the same as foo). take_fn_lt({ |x: &u8| -> &u8 { x } } as fn(&u8) -> &u8); compiles.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-higher-rankedArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.T-compilerRelevant to the compiler 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