rust-lang / rust-lang/rust

Odd lifetime error with closures and HRTBs

Open
#147,618 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

This code:

#![feature(closure_lifetime_binder)]

struct Foo<'a, 'b: 'a, 'c: 'a>(*mut &'a (), *mut &'b (), *mut &'c ());

fn bar<'b, 'c>(callback: impl for<'a> Fn(Foo<'a, 'b, 'c>) + 'static) {
    let _ = for<'a> |foo: Foo<'a, 'b, 'c>| -> () {
        callback(foo);
    };
}

produces on latest nightly:

error: lifetime may not live long enough
 --> src/lib.rs:7:9
  |
5 | fn bar<'b, 'c>(callback: impl for<'a> Fn(Foo<'a, 'b, 'c>) + 'static) {
  |        --  -- lifetime `'c` defined here
  |        |
  |        lifetime `'b` defined here
6 |     let _ = for<'a> |foo: Foo<'a, 'b, 'c>| -> () {
7 |         callback(foo);
  |         ^^^^^^^^^^^^^ argument requires that `'b` must outlive `'c`
  |
  = help: consider adding the following bound: `'b: 'c`

error: lifetime may not live long enough
 --> src/lib.rs:7:9
  |
5 | fn bar<'b, 'c>(callback: impl for<'a> Fn(Foo<'a, 'b, 'c>) + 'static) {
  |        --  -- lifetime `'c` defined here
  |        |
  |        lifetime `'b` defined here
6 |     let _ = for<'a> |foo: Foo<'a, 'b, 'c>| -> () {
7 |         callback(foo);
  |         ^^^^^^^^^^^^^ argument requires that `'c` must outlive `'b`
  |
  = help: consider adding the following bound: `'c: 'b`

help: `'b` and `'c` must be the same: replace one with the other

I think this code should be valid. After all, the type signatures on the closure itself and on the function it's trying to call are identical. I would expect both the closure and the function to implicitly establish bounds 'b: 'a and 'c: 'a due to the use of Foo<'a, 'b, 'c> as an argument. But this shouldn't require 'b: 'c or 'c: 'b.

Disclaimer: I don't really understand how implied bounds work.

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

Start with the nightly reproduction in src/lib.rs, using the linked Rust Playground to confirm the reported diagnostics. Read the closure lifetime binder and implied-bounds handling relevant to higher-ranked trait bounds. Done means determining whether the identical closure and callback signatures should compile without requiring either 'b: 'c or 'c: 'b, and documenting or testing the resulting behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.