Skip to content

GAT type Assoc<T: ?Sized> implicitly requires Self to be 'static #131008

Open
@Veetaha

Description

@Veetaha

I tried this code:

trait Layout {}
trait Desc {
    type Children<A: ?Sized>;
    fn stage(_children: &Self::Children<dyn Layout>);
}

fn stage<D: Desc>(children: D::Children<dyn Layout>) {
    D::stage(&children);
}

This doesn't compile with two errors, and I can't explain why:

error[E0310]: the parameter type `D` may not live long enough
  --> crates/sandbox/src/main.rs:68:5
   |
68 |     D::stage(&children);
   |     ^^^^^^^^^^^^^^^^^^^
   |     |
   |     the parameter type `D` must be valid for the static lifetime...
   |     ...so that the type `D` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
67 | fn stage<D: Desc + 'static>(children: D::Children<dyn Layout>) {
   |                  +++++++++

error[E0597]: `children` does not live long enough
  --> crates/sandbox/src/main.rs:68:14
   |
67 | fn stage<D: Desc>(children: D::Children<dyn Layout>) {
   |                   -------- binding `children` declared here
68 |     D::stage(&children);
   |     ---------^^^^^^^^^-
   |     |        |
   |     |        borrowed value does not live long enough
   |     argument requires that `children` is borrowed for `'static`
69 | }
   | - `children` dropped here while still borrowed

Why is the D required to be 'static here?
Why does the &children need to have a 'static lifetime here as well?


Here are variations that do compile, but I also can't explain why they compile:

Adding `dyn Layout + 'static` in the trait definition

trait Layout {}
trait Desc {
    type Children<A: ?Sized>;
    fn stage(_children: &Self::Children<dyn Layout + 'static>);
}

fn stage<D: Desc>(children: D::Children<dyn Layout>) {
    D::stage(&children);
}

Adding `dyn Layout + '_` in the trait definition

trait Layout {}
trait Desc {
    type Children<A: ?Sized>;
    fn stage(_children: &Self::Children<dyn Layout + '_>);
}

fn stage<D: Desc>(children: D::Children<dyn Layout>) {
    D::stage(&children);
}

This variation doesn't compile, but it removes the `D` must be valid for the static lifetime error and I also don't understand why that is:

trait Layout {}
trait Desc {
    type Children<A: ?Sized>: 'static;
    fn stage(_children: &Self::Children<dyn Layout>);
}

fn stage<D: Desc>(children: D::Children<dyn Layout>) {
    D::stage(&children);
}

There is definitely something implicit going on here which I don't know. Some helpful people suggested this may be related to #87479, but I don't see how.

@nikomatsakis do you have an idea if this is related? Is this some compiler bug or smth not documented?

Meta

rustc --version --verbose:

rustc 1.81.0 (eeb90cda1 2024-09-04)
binary: rustc
commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c
commit-date: 2024-09-04
host: x86_64-unknown-linux-gnu
release: 1.81.0
LLVM version: 18.1.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerA-diagnosticsArea: Messages for errors, warnings, and lintsA-dyn-traitArea: trait objects, vtable layoutA-lifetimesArea: Lifetimes / regionsD-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