rust-lang / rust-lang/rust

Closure breaks function with higher-ranked trait bound

Open
#131,677 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-closures A-higher-ranked C-bug T-compiler T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code:

pub fn f<T>()
where
    for<'a> &'a T:,
{
    || {};
}

I expected this to compile, perhaps with warnings. Instead, I get this error:

error: `T` does not live long enough
 --> src\lib.rs:5:5
  |
5 |     || {};
  |     ^^^^^

Rust version: rustc 1.84.0-nightly (27861c429 2024-10-13)

As best as I can tell, this happens when a generic is involved in a higher-ranked trait bound, and a closure is defined inside the function. It seems like since the closure is somewhat generic over T, the closure needs to satisfy something about the bound. Things that also exhibit the issue:

  • Adding more bounds
  • Using the HRTB with a GAT, e.g. T: for<'a> Trait<Item<'a> = &'a ()>
  • Adding arguments or a return to the closure
  • Using or calling the closure (calling the closure adds another error on the call expression)
  • Replacing the closure with an async block

Things that don't exhibit the issue:

  • A HRTB with a trait generic over a lifetime: T: for<'a> Trait<'a> or for<'a> T: Trait<'a>
  • A HRTB on a concrete type: for<'a> &'a ():
  • Defining the closure inside a function inside f

This is probably the same as #102540 but that issue misidentified the problem and is old. I did some quick checking of old versions and this compiles in 1.20.0 and 1.30.1, throws ICE in 1.40.0, and gives an error in 1.50.0 and 1.60.0. The 1.60.0 error has a little more info.

error: higher-ranked lifetime error
 --> src\lib.rs:5:5
  |
5 |     || {};
  |     ^^^^^
  |
  = note: could not prove for<'a, 'r> &'a T: 'r

The ICE from 1.40.0 looks similar to #59311 (weirdly, predates 1.30) and #71546 and looks like this:

error: internal compiler error: broken MIR in DefId(0:12 ~ rusttest[7b76]::f[0]) (NoSolution): could not prove Binder(OutlivesPredicate(&'a T, ReEmpty))
 --> src\lib.rs:5:5
  |
5 |     || {};
  |     ^^^^^

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the example in src/lib.rs with the reported rustc version, then compare behavior across the versions listed in the report. Read issues #102540, #59311, and #71546 for related HRTB and compiler-error history. The issue does not specify an implementation path or completion criteria beyond resolving the reported behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.