Kimundi / owning-ref-rs

A library for creating references that carry their owner with them.
MIT License
361 stars 50 forks source link

Example for Option inside RwLock? #66

Closed jgarvin closed 4 years ago

jgarvin commented 4 years ago

I've been trying to get this to work:

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

#![allow(dead_code)]

use std::sync::RwLock;

struct World {
    pub foo: Option<String>
}

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

pub fn outer_foo() -> Result<owning_ref::RwLockReadGuardRef<String>, ()> {
    owning_ref::RwLockReadGuardRef::new(WORLD.get().unwrap().read().unwrap()).try_map(
        |world|
        match &world.foo {
            Some(p) => Ok(&p),
            None => Err(())
        }
    )
}

But I keep getting these errors:

   = note: expected enum `std::result::Result<owning_ref::OwningRef<std::sync::RwLockReadGuard<'_, String>, String>, _>`
              found enum `std::result::Result<owning_ref::OwningRef<std::sync::RwLockReadGuard<'_, world::World>, &String>, _>`

Sorry if this isn't really a bug, wasn't sure where the best place to ask was and figure other users might benefit.

jgarvin commented 4 years ago

I solved this, for posterity, issue was &p vs p.

#![allow(dead_code)]

use std::sync::RwLock;
use owning_ref::*;

pub struct World {
    pub foo: Option<String>,
}

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

pub fn get_string(world: &World) -> Result<&String, ()>
{
    match &world.foo {
        Some(p) => Ok(&p),
        None => Err(()),
    }
}

// works
pub fn outer_foo() -> Result<RwLockReadGuardRef<'static, World, String>, ()> {
    owning_ref::RwLockReadGuardRef::new(WORLD.get().unwrap().read().unwrap()).try_map(get_string)
}

// works
pub fn outer_foo2() -> Result<RwLockReadGuardRef<'static, World, String>, ()> {
    owning_ref::RwLockReadGuardRef::new(WORLD.get().unwrap().read().unwrap()).try_map(|world: &World| -> Result<&String, ()>
                                                                                      {
                                                                                          match &world.foo {
                                                                                              Some(p) => Ok(p), // p not &p, already a ref b/c &world.foo
                                                                                              None => Err(()),
                                                                                          }
                                                                                      }
    )
}

fn main() {
    println!("Hello, world!");
}