BorrowChecker complains in impl DerefMut only


#1

Hey, I have a

struct ProjectList{ pub projects: Option<Vec<Project>> }

and want implement Deref and DerefMut to access the <Vec<Project> (and initialize it if it’s None).

Deref worked fine, however in DerefMut the borrowchecker seems to not like my promises:
full example on github

Any Ideas?

Thanks in advance

struct Project{ name: String }
struct ProjectList{ pub projects: Option<Vec<Project>> }

impl Deref for ProjectList{
    type Target=Vec<Project>;
    fn deref(&self) -> &Vec<Project>{
        &self.projects
            .as_ref()
            .expect("projects need to be opened before they can referenced")
    }
}

impl DerefMut for ProjectList{
    fn deref_mut(&mut self) -> &mut Vec<Project>{
        &mut self.projects
            .as_mut()
            .expect("projects need to be opened before they can referenced")
    }
}
   Compiling deref_borrow v0.1.0 (file:///home/hendrik/code/rust/deref_borrow)
src/lib.rs:23:14: 25:77 error: borrowed value does not live long enough
src/lib.rssrc/lib.rs:23:14: 25:77 error: borrowed value does not live long enough
src/lib.rs:23         &mut self.projects
src/lib.rs:24             .as_mut()
src/lib.rs:25             .expect("projects need to be opened before they can referenced")
src/lib.rs:22:49: 26:6 note: reference must be valid for the anonymous lifetime #1 defined on the block at 22:48...
src/lib.rs:22     fn deref_mut(&mut self) -> &mut Vec<Project>{
src/lib.rs:23         &mut self.projects
src/lib.rs:24             .as_mut()
src/lib.rs:25             .expect("projects need to be opened before they can referenced")
src/lib.rs:26     }
src/lib.rs:22:49: 26:6 note: ...but borrowed value is only valid for the block at 22:48
src/lib.rs:22     fn deref_mut(&mut self) -> &mut Vec<Project>{
src/lib.rs:23         &mut self.projects
src/lib.rs:24             .as_mut()
src/lib.rs:25             .expect("projects need to be opened before they can referenced")
src/lib.rs:26     }

#2

You’re over-referencing this. You’re already getting &mut from .as_mut().expect(...), but then you’ve added an additional &mut in front, giving &mut &mut Vec<Project>. This can be automatically dereferenced, but then that’s bound to the lifetime of the temporary outer reference.

I believe the only reason it works for immutable & & Vec<Project> is that the inner reference implements Copy, unlike &mut.


#3

Thank you very much, that did it.
I had extended the .as_ref() and .as_mut() calls after wrapping the vec into the Option, so I didn’t think to actually remove &s. Here is the working version:

use std::ops::{Deref, DerefMut};

struct Project{ name: String }
struct ProjectList{ pub projects: Option<Vec<Project>> }

impl Deref for ProjectList{
    type Target=Vec<Project>;
    fn deref(&self) -> &Vec<Project>{
        self.projects
            .as_ref()
            .expect("projects need to be opened before they can referenced")
    }
}

impl DerefMut for ProjectList{
    fn deref_mut(&mut self) -> &mut Vec<Project>{
        self.projects
            .as_mut()
            .expect("projects need to be opened before they can referenced")
    }
}