Potentially false positive of "lifetime may not live long enough" after introduction of `Sized` bound on associated type
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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