Skip to content

Confusing lifetime outlives error when mixing generics and Fn traits #144026

@camelid

Description

@camelid

Code

fn wrap(s: &str) -> Option<&str> {
    Some(s)
}

fn apply<T, U>(f: impl Fn(&T) -> U) -> T
where
    T: Default,
{
    let x = T::default();
    f(&x);
    x
}

fn foo() {
    let _ = apply::<String, _>(|s| wrap(s));
}

Current output

error: lifetime may not live long enough
  --> src/lib.rs:15:36
   |
15 |     let _ = apply::<String, _>(|s| wrap(s));
   |                                 -- ^^^^^^^ returning this value requires that `'1` must outlive `'2`
   |                                 ||
   |                                 |return type of closure is Option<&'2 str>
   |                                 has type `&'1 String`

Desired output

Rationale and extra context

No response

Other cases

Removing the reliance on deref:

fn wrap(s: &String) -> Option<&String> {
    Some(s)
}

fn apply<T, U>(f: impl Fn(&T) -> U) -> T
where
    T: Default,
{
    let x = T::default();
    f(&x);
    x
}

fn foo() {
    let _ = apply::<String, _>(wrap);
}
error: implementation of `Fn` is not general enough
  --> src/lib.rs:15:13
   |
15 |     let _ = apply::<String, _>(wrap);
   |             ^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
   |
   = note: `for<'a> fn(&'a String) -> Option<&'a String> {wrap}` must implement `Fn<(&String,)>`
   = note: ...but it actually implements `Fn<(&'0 String,)>`, for some specific lifetime `'0`

Using fn pointer:

fn wrap(s: &String) -> Option<&String> {
    Some(s)
}

fn apply<T, U>(f: fn(&T) -> U) -> T
where
    T: Default,
{
    let x = T::default();
    f(&x);
    x
}

fn foo() {
    let _ = apply::<String, _>(wrap);
}
error[E0308]: mismatched types
  --> src/lib.rs:15:32
   |
15 |     let _ = apply::<String, _>(wrap);
   |             ------------------ ^^^^ one type is more general than the other
   |             |
   |             arguments to this function are incorrect
   |
   = note: expected fn pointer `for<'a> fn(&'a String) -> _`
                 found fn item `for<'a> fn(&'a String) -> Option<&'a String> {wrap}`
note: function defined here
  --> src/lib.rs:5:4
   |
5  | fn apply<T, U>(f: fn(&T) -> U) -> T
   |    ^^^^^       --------------

For more information about this error, try `rustc --explain E0308`.

Rust Version

stable 1.88.0

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-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