Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lending iterator through GAT / HRTB implies unexpected lifetime despite being 'static #96669

Closed
udoprog opened this issue May 3, 2022 · 8 comments
Labels
A-GATs Area: Generic associated types (GATs) C-bug Category: This is a bug. F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@udoprog
Copy link
Contributor

udoprog commented May 3, 2022

I tried this code:

#![feature(generic_associated_types)]

trait Iterator {
    type Item<'this>: 'static where Self: 'this;
    fn next(&mut self) -> Self::Item<'_>;
}

fn not_ok<T>(mut it: T) where T: Iterator {
    let mut _out;

    loop {
        _out = it.next(); // `it` was mutably borrowed here in the previous iteration of the loop
    }
}

Since next returns an associated type with a 'static constraint, it seems like the associated type could be assumed to not have a lifetime associated with the Iterator that produces it and allow the program to compile.

Instead some lifetime constraint I can't wrap my head around is present, resulting in the above error.

Meta

rustc --version --verbose:

rustc 1.62.0-nightly (e7575f967 2022-04-14)
binary: rustc
commit-hash: e7575f9670f3c837def3d186ae09366c75c7632e
commit-date: 2022-04-14
host: x86_64-unknown-linux-gnu
release: 1.62.0-nightly
LLVM version: 14.0.0

@udoprog udoprog added the C-bug Category: This is a bug. label May 3, 2022
@jackh726 jackh726 added the F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs label May 4, 2022
@udoprog
Copy link
Contributor Author

udoprog commented May 4, 2022

This is a slightly less contrived example, which is what motivated me to open this issue originally.

Whatever constraint is being applied is projected across another trait as well:

#![feature(generic_associated_types)]

trait Iterator {
    type Item<'this>: Get
    where
        Self: 'this;

    fn next(&mut self) -> Self::Item<'_>;
}

trait Get {
    type Value: 'static;

    fn get(self) -> Self::Value;
}

fn not_ok<T>(mut it: T)
where
    T: Iterator,
{
    let mut _out;

    loop {
        let item = it.next(); // `it` was mutably borrowed here in the previous iteration of the loop
        _out = item.get();
    }
}

@udoprog
Copy link
Contributor Author

udoprog commented May 4, 2022

Repro without GATs:

trait IteratorItem<'a> {
    type Item: 'static;
}

trait Iterator: for<'a> IteratorItem<'a> {
    fn next(&mut self) -> <Self as IteratorItem<'_>>::Item;
}

fn not_ok<T>(mut it: T) where T: Iterator {
    let mut _a = it.next();
    let mut _b = it.next();
}

@udoprog udoprog changed the title Lending iterator through GAT implies unexpected lifetime despite being 'static Lending iterator through GAT / HRTB implies unexpected lifetime despite being 'static May 4, 2022
@Enselic Enselic added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 16, 2024
@archshift
Copy link
Contributor

Any news on this? It makes lending iterators very difficult to use when loops are involved...

@traviscross
Copy link
Contributor

We fixed this somewhere along the way. These all work fine now.

Playground link

Playground link

Playground link

Thanks to @udoprog for providing straightforward reproductions.

cc @oli-obk @compiler-errors

@udoprog
Copy link
Contributor Author

udoprog commented Jun 4, 2024

Thanks for the follow up!

@archshift
Copy link
Contributor

I guess I'm not 100% sure this is the same error, but it seems to manifest in very similar ways. Is this related?

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c1d12691844588acfd9940aacaa6d918

@udoprog
Copy link
Contributor Author

udoprog commented Jun 5, 2024

@archshift Since you're dealing with non-'static lifetimes, it's probably a different issue. I think your code could technically be legal if the borrow checker was smarter in how the local lifetime was dealt with in the loop. But I would emphasize that such a borrowing iterator is still very limited. It wouldn't be possible to hold onto several items at the same time since all of them would have to borrow exclusively from &mut self.

@archshift
Copy link
Contributor

Oh, did some more digging and it turns out #92985 is exactly my issue.

@fmease fmease added the A-GATs Area: Generic associated types (GATs) label Nov 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-GATs Area: Generic associated types (GATs) C-bug Category: This is a bug. F-generic_associated_types `#![feature(generic_associated_types)]` a.k.a. GATs T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants