Skip to content

Unhelpful higher-ranked lifetime error in non-async context #111465

Open
@veprolet

Description

Here is somewhat minified code producing the unhelpful error message (playground)

fn map<F, M, I, X, O>(function: F, mapper: M) -> impl Fn(I) -> O
where
    F: Fn(I) -> X,
    M: Fn(X) -> O,
{
    move |input| {
        mapper(function(input))
    }
}

fn pack<F, O>(function: F) -> impl Fn(&u32) -> ((), O)
where
    F: Fn(&u32) -> O,
{
    move |input| {
        ((), function(input))
    }
}

fn unpack<F, O>(function: F) -> impl Fn(&u32)
where
    F: Fn(&u32) -> O,
{
    map(pack(function), |(unit, _)| unit)
}

fn main() {}

This code produces the following error message, which is in my opinon quite unhelpful:

error: higher-ranked lifetime error
  --> src/main.rs:24:5
   |
24 |     map(pack(function), |(unit, _)| unit)
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I assume the lifetimes in the code desugar into something like this:

fn map<F, M, I, X, O>(function: F, mapper: M) -> impl Fn(I) -> O
where
    F: Fn(I) -> X,
    M: Fn(X) -> O,
{
    move |input| {
        mapper(function(input))
    }
}

fn pack<F, O>(function: F) -> impl for<'a> Fn(&'a u32) -> ((), O)
where
    for<'b> F: Fn(&'b u32) -> O,
{
    move |input| {
        ((), function(input))
    }
}

fn unpack<F, O>(function: F) -> impl for<'a> Fn(&'a u32)
where
    for<'b> F: Fn(&'b u32) -> O,
{
    map(pack(function), |(unit, _)| unit)
}

fn main() {}

This code produces the same error and does seem vaguely incorrect, as I'd expect the two lifetimes to be at least somewhat related. Specifying the lifetimes in almost any other way resolves the error. For example:

fn map<F, M, I, X, O>(function: F, mapper: M) -> impl Fn(I) -> O
where
    F: Fn(I) -> X,
    M: Fn(X) -> O,
{
    move |input| {
        mapper(function(input))
    }
}

fn pack<'a, F, O>(function: F) -> impl Fn(&'a u32) -> ((), O)
where
    for<'b> F: Fn(&'b u32) -> O,
{
    move |input| {
        ((), function(input))
    }
}

fn unpack<'a, F, O>(function: F) -> impl Fn(&'a u32)
where
    for<'b> F: Fn(&'b u32) -> O,
{
    map(pack(function), |(unit, _)| unit)
}

fn main() {}

This issue seems closely related to other issues with this error, such as: #102211, #102870, #99492. This issue is probably a duplicate of those, but I'm submitting a new issue, because all the aforementioned issues deal with complex async types and contexts, and apart from #102870 seem to include at least some helpful info in the error message. Also I don't completely understand the error, so I'm not sure whether it should even occur, which seems to be the main focus of those other issues, but I'm fairly confident the error message could provide more information.

Meta

rustc --version --verbose:

rustc 1.69.0 (84c898d65 2023-04-16)
binary: rustc
commit-hash: 84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc
commit-date: 2023-04-16
host: x86_64-unknown-linux-gnu
release: 1.69.0
LLVM version: 15.0.7

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerA-diagnosticsArea: Messages for errors, warnings, and lintsA-higher-rankedArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)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