rust-lang / rust-lang/rust

Potentially false positive of "lifetime may not live long enough" after introduction of `Sized` bound on associated type

Open
#137,184 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-lifetimes A-trait-system C-bug T-lang
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code:

use std::marker::PhantomData;

/// Some data. In real life, imagine that its content is arena-allocated with lifetime `'a`.
struct Data<'a> {
    _marker: PhantomData<&'a ()>,
}

struct DataAlloc;

/// Data with borrowed content that can be copied from one location to another.
trait CopyTo {
    /// This is always `Self`, be we need associated types to make Rust understand that `Self` is
    /// actually parametric over some lifetime.
    type Data<'a>;

    /// Copy data from the current allocator to `dest`.
    fn copy_to<'from, 'to>(data: Self::Data<'from>, dest: &'to DataAlloc) -> Self::Data<'to>;
}

impl CopyTo for Data<'_> {
    type Data<'a> = Data<'a>;

    fn copy_to<'from, 'to>(data: Data<'from>, _dest: &'to DataAlloc) -> Data<'to> {
        Data {
            _marker: PhantomData,
        }
    }
}

impl DataAlloc {
    pub fn copy<'from, 'to, T: CopyTo>(&'to self, data: T::Data<'from>) -> T::Data<'to>
    where
        T: CopyTo<Data<'to>: Sized>,
    {
        T::copy_to(data, self)
    }
}

I expected to see this happen: this code should compile. In fact, if I remove the where T: CopyTo<Data<'to>: Sized> clause, which isn't used at all, this code compiles.

Instead, this happened: I get a lifetime may not live long enough error, with the note "Proving this value is Sized requires to to must outlive 'from" as well as the dual message:

error: lifetime may not live long enough
  --> src/lib.rs:35:20
   |
31 |     pub fn copy<'from, 'to, T: CopyTo>(&'to self, data: T::Data<'from>) -> T::Data<'to>
   |                 -----  --- lifetime `'to` defined here
   |                 |
   |                 lifetime `'from` defined here
...
35 |         T::copy_to(data, self)
   |                    ^^^^ proving this value is `Sized` requires that `'to` must outlive `'from`
   |
   = help: consider adding the following bound: `'to: 'from`

error: lifetime may not live long enough
  --> src/lib.rs:35:20
   |
31 |     pub fn copy<'from, 'to, T: CopyTo>(&'to self, data: T::Data<'from>) -> T::Data<'to>
   |                 -----  --- lifetime `'to` defined here
   |                 |
   |                 lifetime `'from` defined here
...
35 |         T::copy_to(data, self)
   |                    ^^^^ proving this value is `Sized` requires that `'from` must outlive `'to`
   |
   = help: consider adding the following bound: `'from: 'to`

Context

This is a simplified version of a real use-case where I have arena-allocated data and I want a trait that implements moving them from one arena to another with a different lifetime. Since Rust doesn't support general higher-kinded types, I use GATs as a poor man's HKT, which requires more annotations but it works ok. However, when I try to implement a variant of copy where I need additional bounds on the associated type, I started to get strange lifetime errors. What's surprising here is that the trait bound is unrelated to the body of the function and never used. It's surprising that adding a Sized bound adds any lifetime constraints at all, unless I'm missing something obvious.

Potential duplicate of https://github.com/rust-lang/rust/issues/108345, but I wanted to make sure it's not a different error first.

Meta

rustc --version --verbose:

rustc 1.84.1 (e71f9a9a9 2025-01-27)
binary: rustc
commit-hash: e71f9a9a98b0faf423844bf0ba7438f29dc27d58
commit-date: 2025-01-27
host: x86_64-unknown-linux-gnu
release: 1.84.1
LLVM version: 19.1.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

Start with the minimal reproducer in the issue and run it with rustc 1.84.1, then compare the diagnostics after removing the where T: CopyTo<Data<'to>>: Sized clause. Investigate the related issue #108345 and verify that the bounded version should compile without requiring either lifetime outlive the other.

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
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.