What 's happen with borrow checker?

// Decorator
type Name<'a> = &'a str;
#[cfg_attr(test, derive(Clone))]
#[derive(PartialEq, PartialOrd,Debug)]
pub enum Role{
    Employee,
    Customer,
    Both,
    None
}

pub struct Person<'a>{
    name:Name<'a>,
    role:Role
}
impl <'a> Person <'a>{
    pub fn get_name(&self)->Name<'a>{
        self.name
    }
    pub fn set_name(&mut self,name:&'a str){
        self.name = name;
    }
    pub fn add_role(self:&mut Self){
        self.role = match (*self).role {
            Role::Employee| Role::None=> Role::Employee,
            Role::Customer| Role::Both=> Role::Both,
        };
    }

}

    
//
//Decoration1;
pub struct Employee<'a>{
    person:&'a Person<'a>
}
impl <'a>Employee<'a> {
    pub fn add_role (person:&'a mut Person<'a>)->Self{
        person.add_role();
        let person:&Person = &*person;
        Self{
            person
        }
    }

}

//Decoration2;
pub struct Customer<'a>{
    person:&'a Person<'a>
}
impl <'a>Customer<'a> {
    pub fn add_role (person:&'a mut Person<'a>)->Self{
        person.add_role();
        let person= &*person;
        Self{
            person
        }
    }
}

#[cfg(test)]
mod decorator_test {
    use super::*;
    #[test]
    fn test_decorator() {
        let mut p = Person{
            name:"Name",
            role:Role::None
        };
        //decorate to employee
        assert_eq!(Role::None,p.role);
        let e = Employee::add_role(&mut p);
        assert_eq!("Name",e.person.get_name());
        assert_eq!(Role::Employee,e.person.role);
   // error appear here     
        let c = Customer::add_role(&mut p);
        assert_eq!(Role::Both,c.person.role);
    }

    #[derive(PartialEq, Eq, PartialOrd, Ord,Debug)]
    enum State {
        On,
        Off
    }
    impl State {
    fn turn_on<'a>(c:&'a mut State) {
        *c =  State::On;
    }
    fn turn_off<'a>(c:&'a mut State) {
        *c =  State::Off;
    }
        
    }

    #[test]
    fn reference_test(){
        let mut p = "10";
        p = "20";
        assert_eq!(p,"20");
        let p =&mut "10";
        *p = "20";
        assert_eq!(*p,"20");
        let mut c = State::Off;
        State::turn_on(&mut c);
        assert_eq!(c,State::On);
        State::turn_off(&mut c);
        assert_eq!(c,State::Off);
    }
}

in the same case

impl State {
    fn turn_on<'a>(c:&'a mut State) {
        *c =  State::On;
    }
    fn turn_off<'a>(c:&'a mut State) {
        *c =  State::Off;
    }
        
    }

    #[test]
    fn reference_test(){
        let mut p = "10";
        p = "20";
        assert_eq!(p,"20");
        let p =&mut "10";
        *p = "20";
        assert_eq!(*p,"20");
        let mut c = State::Off;
        State::turn_on(&mut c);
        assert_eq!(c,State::On);
        State::turn_off(&mut c);
        assert_eq!(c,State::Off);
    }

it work well.
playground

It's a case about lifetime variance. I will just direct you to this nice explanation by @quinedot .

1 Like

can I downgrade &mut to & only ?
I have used let p = person as &'a Person<'a>; inside impl of
fn add_role<'a> (person:&mut Person<'a>)
and

//  impl Person<'a> {...
    pub fn add_role(&mut self){
        let role = match (*self).role {
            Role::Employee| Role::None=> Role::Employee,
            Role::Customer| Role::Both=> Role::Both,
        } as Role;
        self.role = role;
    }

but It doesn't work

You could reborrow it:

let p = &*person;
1 Like

It doesn't work too

80 |         let c = Customer::add_role(&mut p);
   |                                    ^^^^^^
   |                                    |
   |                                    second mutable borrow occurs here
   |                                    first borrow later used here

I seem like this my pattern is pitful. are there any suggestion

Sorry, I was on the mobile and had not seen your playgrund.

One way to fix this is to shorten the time you borrow a Person:

impl <'a, 'b:'a> Employee<'a> {
    pub fn add_role (person:&'a mut Person<'b>)->Self{
        person.add_role();
        let person:&Person = &*person;
        Self{
            person
        }
    }

}

impl <'a, 'b:'a> Customer<'a> {
    pub fn add_role (person:&'a mut Person<'b>)->Self{
        person.add_role();
        let person= &*person;
        Self{
            person
        }
    }
}
1 Like

Thank for this . It work.
P/S:
I read in explanation by @quinedot . &'medium mut &'long mut T -> &'long mut T .
It's explanable why &mut p life so long.
but why do your techniqe work?
Does It something like changing &'medium mut &'long mut T -> &'medium mut T . ?
This ideal is so brightain,
Thank you !!!

        assert_eq!(&Role::Both,&c.person.role);
        assert_eq!(&Role::Employee,&p.role);
        // assert_eq!(&Role::Both,&c.person.role);

It fix the problem but
I can make it to be working like arc or rc :(.
it doesn't work if I try to access value from Employee or Custom or Person at same time but even only Customer or Employee

// Decorator
//
#![deny(elided_lifetimes_in_paths)]
type Name<'a> = &'a str;
#[cfg_attr(test, derive(Clone))]
#[derive(PartialEq, PartialOrd,Debug)]
pub enum Role{
    Employee,
    Customer,
    Both,
    None
}

pub struct Person<'a>{
    name:Name<'a>,
    role:Role
}
impl <'a> Person <'a>{
    pub fn get_name(&self)->Name<'a>{
        self.name
    }
    pub fn set_name(&mut self,name:&'a str){
        self.name = name;
    }
    pub fn add_role(&'_ mut self,role:Role){
        self.role = match &self.role {
            r if *r==role||*r==Role::None =>role,
            _=>Role::Both,
        };
    }

}

    
//
//Decoration1;
pub struct Employee<'a>{
    person:&'a Person<'a>
}
impl <'a,'b:'a>Employee<'a> {

    pub fn add_role (person:&'a mut Person<'b>)->Self{
        person.add_role(Role::Employee);
        let p = &*person ;
        Self{
            person:p
        }
    }

}

//Decoration2;
pub struct Customer<'a>{
    person:&'a Person<'a>
}
impl <'a,'b:'a>Customer<'a> {

    pub fn add_role (person:&'a mut Person<'b>)->Self{
        person.add_role(Role::Customer);
        let p = &*person ;
        Self{
            person:p
        }
    }
}

#[cfg(test)]
mod decorator_test {
    use super::*;
    #[test]
    fn test_decorator() {
        let mut p = Person{
            name:"Name",
            role:Role::None
        };
        //decorate to employee
        assert_eq!(Role::None,p.role);
        let e = Employee::add_role(&mut p);
        assert_eq!("Name",e.person.get_name());
        assert_eq!(&Role::Employee,&e.person.role);
        let c = Customer::add_role(&mut p);
        assert_eq!(&Role::Both,&c.person.role);
        assert_eq!(&Role::Both,&p.role.e); //
        // assert_eq!(&Role::Both,&c.person.role);<— this error happen here 
    }


}

My actual advice is don't use lifetime based references for things like Person -- presumably values which will be kept around as more than just temporary values.

Part of the fix is just avoiding borrowing something forever.

Part of how it works is variance. Once you reborrow the &'a mut Person<'b> so that you have a &'x Person<'y>, both lifetimes are covariant in the new value -- they can be coerced to be shorter. One way to think of it is as if this is how the transformation happened:

    // It is a given that `'b: 'a`
    pub fn add_role (person:&'a mut Person<'b>)->Self{
        person.add_role();
        // Say this is a `&'a Person<'b>`
        let person = &*person;

        // Then here it coerces to `&'a Person<'a>`, possible due to variance,
        // and because `'b: 'a` (and because `'a: 'a`)
        Self { person }
    }

(This is a simplification of what the borrow checker does, but the net result is the same, so it suffices for this example.)

Customer::add_role and Employee::add_role modify p.role. If it didn't, you wouldn't have gotten Both in your second-to-last assert.

2 Likes

this error actually happens in the line that I have commented.
I’m trying to access Person though Employee and Customer
P/s: Thank for this docs.

If this is a question, I'm afraid I don't understand what the question is.

1 Like

you can try to comment/uncomment the last line.
I don’t have any clues for this error yet :frowning:

You can't exclusively borrow a variable twice at the same time. So in this snippet which compiles:

/*  0 */   // Exclusively borrow `p` to create `e`.
/*  1 */   // So long as `e` is in use, `p` will remain exclusively borrowed.
/*  2 */   let e = Employee::add_role(&mut p);
/*  3 */
/*  4 */   // Exclusively borrow `p` to create `c`.
/*  5 */   // So long as `c` is in use, `p` will remain exclusively borrowed.
/*  6 */   let c = Customer::add_role(&mut p);
/*  7 */
/*  8 */   assert_eq!(&Role::Both, &c.person.role);
/*  9 */   // assert_eq!(&Role::Both, &e.person.role);
/* 10 */   assert_eq!(&Role::Both, &c.person.role);

We can conclude that the borrow created on line 2 expires before line 6.

If we uncomment line 9 we get an error:

error[E0499]: cannot borrow `p` as mutable more than once at a time
  --> src/lib.rs:75:39
   |
71 | /*  2 */   let e = Employee::add_role(&mut p);
   |                                       ------ first mutable borrow occurs here
...
75 | /*  6 */   let c = Customer::add_role(&mut p);
   |                                       ^^^^^^ second mutable borrow occurs here
...
78 | /*  9 */   assert_eq!(&Role::Both, &e.person.role);
   |                                    -------------- first borrow later used here

The use of e on line 9 now keeps the exclusive borrow of p on line 2 active for lines 3 through 9 -- including line 6. Now trying to create a second exclusive borrow of p conflicts will already being borrowed.

This is a fundamental property of how exclusive references (&mut _) works. You have to stop using e before you can create c with the API / function signatures how they are.

There is no API for "pass in a &mut _ and pass back a reborrow of it, and then immediately downgrade the input borrow to shared." Even if there was, it wouldn't help you here, since you need the exclusive &mut _ in both Employee::add_role and Customer::add_role. And based on the test, you are indeed expecting the creation of c to change what is pointed to by e. There's no sound way to make that happen without some sort of shared ("interior") mutability.

Maybe you want Cell<Role> or such instead, so you can change it with shared borrows.[1]

(But I really we're just patching around a larger design issue, be it overusing lifetimes or expectations around everything being mutable. Perhaps you're expecting everything to invisibly work like it was wrapped in an Arc<Mutex<_>>, ala some higher-level languages.)


    pub fn add_role(&'_ mut self,role:Role){
        self.role = match &self.role {
            r if *r==role||*r==Role::None =>role,
            _=>Role::Both,
        };
    }

Incidentally, if role is Role::None and self.role is (e.g.) Role::Employee, you return Role::Both here. Perhaps you want something more like

        let role = match (self.role.get(), role) {
            (Role::None, r) | (r, Role::None) => r,
            (r1, r2) if r1 == r2 => r1,
            _ => Role::Both,
        };

  1. In the playground, Cell is providing shared mutability. ↩︎

2 Likes