How to make OwningRef work with iterators?

166 Views Asked by At

I have a RwLock protected global WORLD, and I want to write a function that read locks it and returns an iterator (of type Neighbors) that iterates over edges in a petgraph::stable_graph::StableGraph that is stored inside the global. I'm using OwningRef to deal with keeping the read lock guard alive after the function exits, which has worked for me in the past when just returning a field of World directly. I've included a compilable example and the error I'm getting below -- it seems there is some sort of type problem but I haven't been able to figure it out. I think it might have to do with OwningRef wanting to deal with a reference rather than an object containing a reference (Neighbors) but I'm not sure how to work around that.

Cargo.toml:

[package]
name = "problem_demo"
version = "0.1.0"
authors = ["Joseph Garvin <[email protected]>"]
edition = "2018"

[dependencies]
owning_ref="0.4.1"
once_cell="1.4.0"
petgraph={version="0.5.1", features=["serde-1"]}

main.rs:

use std::{sync::RwLock};
use once_cell::sync::OnceCell;
use owning_ref::RwLockReadGuardRef;
use petgraph::stable_graph::{StableGraph, Neighbors};

struct Bar {
    data: i32
}

struct World {
    graph: StableGraph<(), Bar, petgraph::Directed, u32>
}

pub static WORLD: OnceCell<RwLock<World>> = OnceCell::new();

fn neighbors(id: u32) -> Result<RwLockReadGuardRef<'static, World, Neighbors<'static, Bar, u32>>, Box<dyn std::error::Error>> {
    RwLockReadGuardRef::new(WORLD.get().unwrap().read().unwrap())
        .try_map(
            |world: &World| -> std::result::Result<Neighbors<'static, Bar, u32>, Box<dyn std::error::Error>>
            {
                let neighbors = world.graph.neighbors_directed(
                    petgraph::graph::NodeIndex::new(id as usize),
                    petgraph::Direction::Outgoing
                );

                Ok(neighbors)
            }
        )
}

Errors:

error[E0271]: type mismatch resolving `for<'r> <[closure@src/main.rs:21:13: 29:14 id:_] as std::ops::FnOnce<(&'r World,)>>::Output == std::result::Result<&'r _, _>`
  --> src/main.rs:20:10
   |
20 |         .try_map(
   |          ^^^^^^^ expected struct `petgraph::stable_graph::Neighbors`, found reference
   |
   = note: expected enum `std::result::Result<petgraph::stable_graph::Neighbors<'static, Bar>, std::boxed::Box<dyn std::error::Error>>`
              found enum `std::result::Result<&_, _>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0271`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.
0

There are 0 best solutions below