Skip to content

E0716 without "let's call this" and spurious "requirement introduced here" #153545

@jendrikw

Description

@jendrikw

Edit (2026-03-07T23:28:55+01:00): massively simplified code

Code

use std::cell::RefCell;
use std::sync::Arc;
use std::collections::HashMap;
use std::collections::hash_map::Entry;

fn apply<'a>(
    f: Arc<dyn Fn(Entry<'a, String, String>) + 'a>,
) -> impl Fn(RefCell<HashMap<String, String>>)
{
    move |map| {
        let value = map.borrow_mut().entry("foo".to_string());
        let wrapped_value = value;
        f(wrapped_value);
    }
}

Current output

error[E0597]: `map` does not live long enough
  --> src/lib.rs:11:21
   |
 7 |     f: Arc<dyn Fn(Entry<'a, String, String>) + 'a>,
   |     - lifetime `'1` appears in the type of `f`
...
10 |     move |map| {
   |           --- binding `map` declared here
11 |         let value = map.borrow_mut().entry("foo".to_string());
   |                     ^^^ borrowed value does not live long enough
12 |         let wrapped_value = value;
13 |         f(wrapped_value);
   |         ---------------- argument requires that `map` is borrowed for `'1`
14 |     }
   |     - `map` dropped here while still borrowed
   |
note: requirement that the value outlives `'1` introduced here
  --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:76:34
   |
76 | pub const trait Fn<Args: Tuple>: [const] FnMut<Args> {
   |                                  ^^^^^^^^^^^^^^^^^^^

error[E0716]: temporary value dropped while borrowed
  --> src/lib.rs:11:21
   |
 7 |     f: Arc<dyn Fn(Entry<'a, String, String>) + 'a>,
   |     - lifetime `'1` appears in the type of `f`
...
11 |         let value = map.borrow_mut().entry("foo".to_string());
   |                     ^^^^^^^^^^^^^^^^                         - temporary value is freed at the end of this statement
   |                     |
   |                     creates a temporary value which is freed while still in use
12 |         let wrapped_value = value;
13 |         f(wrapped_value);
   |         ---------------- argument requires that borrow lasts for `'1`
   |
note: requirement that the value outlives `'1` introduced here
  --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:76:34
   |
76 | pub const trait Fn<Args: Tuple>: [const] FnMut<Args> {
   |                                  ^^^^^^^^^^^^^^^^^^^

Rationale and extra context

  1. The compiler says "lifetime '1 appears in the type of f", but I can't figure out where and how it can appear. The trait object has an explicit lifetime 'a, and there are no elided lifetimes in Entry.

  2. I'm used to a line saying "let's call this lifetime '1". It's missing in this case, so I don't know where '1 even comes from.

  3. I don't understand how the highlighted [const] FnMut<Args> can introduce a lifetime. Is it related to the impl Fn for &Fn?

  4. It is not clear how "temporary value is freed at the end of this statement" relates to the lifetime '1. It looks like a separate error, but all the messages from the first error are duplicated.

Other cases

When replacing Arc with Box, the note "requirement ..." goes away.

Rust Version

rustc 1.93.1 (01f6ddf75 2026-02-11)
binary: rustc
commit-hash: 01f6ddf7588f42ae2d7eb0a2f21d44e8e96674cf
commit-date: 2026-02-11
host: x86_64-unknown-linux-gnu
release: 1.93.1
LLVM version: 21.1.8

Anything else?

No response

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsD-confusingDiagnostics: Confusing error or lint that should be reworked.D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.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