Precice capturing does not normalize aliases/projections (e.g. Self::Assoc)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I tried this code:
pub trait Trait<'a, T> {
type Item;
fn method(&self) -> Option<impl Iterator<Item = Self::Item>>;
}
impl<'a, 's, T, U> Trait<'a, T> for &'s U
where
U: std::ops::Deref<Target: Sized>,
{
type Item = U::Target;
#[allow(refining_impl_trait)]
fn method(&self) -> Option<impl Iterator<Item = Self::Item> + use<T, U>> {
None::<std::vec::IntoIter<U::Target>>
}
}
I expected to see this happen (in increasing order of preference):
- Underline
Selfspecifically as the origin of lifetime capturing (not the entire opaque) - Suggest the following fix
- fn method(&self) -> Option<impl Iterator<Item = Self::Item> + use<T, U>> { + fn method(&self) -> Option<impl Iterator<Item = U::Target> + use<T, U>> { - Compile successfully
Further explanation: It's natural to copy the bounds from the trait definition. Moreover one may, say, add precise captures during the course of development by editing an opaque that is already present (which may use aliases such as Self). It's easy to miss that any use of Self can pull in other parameters. In the example it pulls in not only the lifetime in the implementing type, but also the one in the trait:
impl Iterator<Item = <&'s U as Trait<'a, T>>::Item>
It would be a breaking change to make Self::Item capture the lifetimes, so normalizing shouldn't be a future compatibility concern for the example at least.
If normalization/successful compilation isn't possible for whatever reason, this can be considered purely a diagnostic issue.
Instead, this happened:
error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
--> src/lib.rs:13:32
|
6 | impl<'a, 's, T, U> Trait<'a, T> for &'s U
| -- this lifetime parameter is captured
...
13 | fn method(&self) -> Option<impl Iterator<Item = Self::Item> + use<T, U>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait`
error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
--> src/lib.rs:13:32
|
6 | impl<'a, 's, T, U> Trait<'a, T> for &'s U
| -- this lifetime parameter is captured
...
13 | fn method(&self) -> Option<impl Iterator<Item = Self::Item> + use<T, U>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait`
Meta
Playground beta and nightly
- Build using the Beta version: 1.87.0-beta.3 (2025-04-07 a22ecb51f85284abc5b1)
- Build using the Nightly version: 1.88.0-nightly (2025-04-07 e643f59f6da3a84f43e7)
- Playground link
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
Reproduce the example in src/lib.rs on the beta and nightly versions linked in the report, then trace how precise captures analyze Self::Item and projected associated types. Compare the current duplicate lifetime diagnostics with the requested normalization or more specific span. Done means the example compiles or produces the improved diagnostic behavior without regressing capture checking.
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
- 42/100