Can't figure out how to return an "impl LendingIterator" from a method

Hey! I'm having trouble writing a return type signature for an impl LendingIterator.

Unfortunately I can't extract my problem into the Rust Playground since it uses the gat-lending-iterator crate, so I'll give some background on the project I've been working on it. It's a branch for doukutsu-rs, the Rust rewrite of Cave Story.

The way the NPC list is currently written is unsound as it creates multiple mutable references. I decided to create a branch to address this. I've been tweaking and refining this branch over the past few weeks.

The goals of this branch are:

  • To overhaul the NPC list to prevent doukutsu-rs from creating multiple mutable references. It now keeps each NPC in a RefCell instead of an UnsafeCell.
  • To have minimal runtime overhead
  • To have minimal impact on the rest of the game's code
  • To prevent "already borrowed" panics by ensuring all borrows are returned before certain operations such as iterating over the list. Borrow panics aren't impossible but they should be hard to trigger accidentally.

The rules are enforced through an access token. In order to borrow an NPC, you need to give away your access token. During the NPC tick function, the NPC can be unborrowed to recover the access token. It's basically a RefMut that can be temporarily unborrowed to get the RefCell back.

I'll confess that I only had a beginner-level understanding of Rust lifetimes before diving into the deep end. The lifetime issues here are seriously gnarly. Nevertheless, the branch currently compiles and works safely with no borrow panics.

The problem is in src/game/npc/list.rs, line 218:

    pub fn iter_mut<'a, P: NPCAccessTokenProvider>(
        &'a self,
        token_provider: &'a mut P
        // FIXME: I would love to put "-> impl LendingIterator<Item = ...>" in the return type, but nothing seems to work...
    ) -> NPCBorrowMutIterator<'a, 'a, P> {
        NPCBorrowMutIterator::new(&self, token_provider)
    }

The code works fine when I return an NPCBorrowMutIterator, but the usage is limited as I can't use .filter, .map, etc. I would like to return an "impl LendingIterator<Item = NPCRefMut>" Unfortunately, no such type signature seems to work. There is always either a "'_ must outlive 'static" error or there is an error when attempting to iterate through it.

Is it possible to return an "impl LendingIterator" from this function? If so, what is the correct type signature?

Is this what you're seeing?

If so, it's because GATs and HRTBs don't play nice together. It might be possible to hack up a workaround with your own sub-trait(s).

Yep, that's the error. Thanks for the link, I'll study the article.