rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.92k stars 12.68k forks source link

lifetime bound not satisfied for a lending iterator (using generic associated types) with `for_each` method #91693

Open Imberflur opened 2 years ago

Imberflur commented 2 years ago

I'm trying to write a streaming/lending iterator trait using the nightly generic_associated_types feature (i.e. in the vein outlined here), in particular with a for_each method:

#![feature(generic_associated_types)]

pub trait LendingIterator {
    type Item<'a> where Self: 'a;
    fn next(&mut self) -> Option<Self::Item<'_>>;

    fn for_each<F>(mut self, mut f: F)
    where
        Self: Sized,
        F: FnMut(Self::Item<'_>),
    {
        while let Some(item) = self.next() {
            f(item)
        }
    }
}

However, the lifetime bounds don't appear to be satisfied for calling the for_each method when Self contains non 'static lifetimes:

pub struct Mutator<T>(T);

impl<T> LendingIterator for Mutator<T> {
    type Item<'a> where Self: 'a = &'a mut T;
    fn next(&mut self) -> Option<Self::Item<'_>> {
        Some(&mut self.0)
    }
}

pub fn bar<T>(m: Mutator<T>) {
    m.for_each(|_: &mut T| {});
}

pub fn foo<'m>(m: Mutator<&'m i32>) {
    m.for_each(|_: &mut &'m i32| {});
}
   Compiling playground v0.0.1 (/playground)
error[E0311]: the parameter type `T` may not live long enough
  --> src/lib.rs:28:7
   |
27 | pub fn bar<T>(m: Mutator<T>) {
   |            - help: consider adding an explicit lifetime bound...: `T: 'a`
28 |     m.for_each(|_: &mut T| {});
   |       ^^^^^^^^ ...so that the type `Mutator<T>` will meet its required lifetime bounds

error[E0477]: the type `Mutator<&i32>` does not fulfill the required lifetime
  --> src/lib.rs:32:7
   |
32 |     m.for_each(|_: &mut &'m i32| {});
   |       ^^^^^^^^

For more information about this error, try `rustc --explain E0477`.
error: could not compile `playground` due to 2 previous errors

playground

I think I would expect 'a be constrained to not outlive Self rather than requiring Self outlive any particular 'a. I could be missing something though.

It appears to be triggered by the inclusion of the closure parameter with its impilcit HRTB So potentially this issue is related to https://github.com/rust-lang/rust/issues/88460

forum discussion

Meta

Version tested with on the playground:

Nightly channel
Build using the Nightly version: 1.59.0-nightly
(2021-12-07 0b6f079e4987ded15c13)
QuineDot commented 2 years ago

@rustbot label requires-nightly, F-generic_associated_types, T-compiler

jackh726 commented 2 years ago

I think this is a known issue (iterator adapters don't play well with GATs atm), likely related to the leak check and universes work. Any fix here is probably going to be very involved.

jackh726 commented 2 years ago

GATs issue triage: not blocking. This needs some work with Polonius, I think. But not backwards-incompatible.