#[macro_use] extern crate rental; pub struct Foo { i: i32, } pub struct Bar<'a> { foo: &'a mut Foo, } pub struct Baz<'a: 'b, 'b> { bar: &'b mut Bar<'a> } pub struct Qux<'a: 'b, 'b: 'c, 'c> { baz: &'c mut Baz<'a, 'b> } pub struct Xyzzy<'a: 'b, 'b: 'c, 'c: 'd, 'd> { qux: &'d mut Qux<'a, 'b, 'c> } impl Foo { pub fn borrow_mut<'a>(&'a mut self) -> Bar<'a> { Bar { foo: self } } pub fn try_borrow_mut<'a>(&'a mut self) -> Result, ()> { Ok(Bar { foo: self }) } pub fn fail_borrow_mut<'a>(&'a mut self) -> Result, ()> { Err(()) } } impl<'a> Bar<'a> { pub fn borrow_mut<'b>(&'b mut self) -> Baz<'a, 'b> { Baz { bar: self } } pub fn try_borrow_mut<'b>(&'b mut self) -> Result, ()> { Ok(Baz { bar: self }) } pub fn fail_borrow_mut<'b>(&'b mut self) -> Result, ()> { Err(()) } } impl<'a: 'b, 'b> Baz<'a, 'b> { pub fn borrow_mut<'c>(&'c mut self) -> Qux<'a, 'b, 'c> { Qux { baz: self } } pub fn try_borrow_mut<'c>(&'c mut self) -> Result, ()> { Ok(Qux { baz: self }) } pub fn fail_borrow_mut<'c>(&'c mut self) -> Result, ()> { Err(()) } } impl<'a: 'b, 'b: 'c, 'c> Qux<'a, 'b, 'c> { pub fn borrow_mut<'d>(&'d mut self) -> Xyzzy<'a, 'b, 'c, 'd> { Xyzzy { qux: self } } pub fn try_borrow_mut<'d>(&'d mut self) -> Result, ()> { Ok(Xyzzy { qux: self }) } pub fn fail_borrow_mut<'d>(&'d mut self) -> Result, ()> { Err(()) } } rental! { mod rentals { use super::*; #[rental_mut] pub struct ComplexRent { foo: Box, bar: Box>, baz: Box>, qux: Box>, xyzzy: Xyzzy<'foo, 'bar, 'baz, 'qux>, } } } #[test] fn new() { let foo = Foo { i: 5 }; let _ = rentals::ComplexRent::new( Box::new(foo), |foo| Box::new(foo.borrow_mut()), |bar| Box::new(bar.borrow_mut()), |baz| Box::new(baz.borrow_mut()), |qux| qux.borrow_mut() ); let foo = Foo { i: 5 }; let cm = rentals::ComplexRent::try_new( Box::new(foo), |foo| foo.try_borrow_mut().map(|bar| Box::new(bar)), |bar| bar.try_borrow_mut().map(|baz| Box::new(baz)), |baz| baz.try_borrow_mut().map(|qux| Box::new(qux)), |qux| qux.try_borrow_mut() ); assert!(cm.is_ok()); let foo = Foo { i: 5 }; let cm = rentals::ComplexRent::try_new( Box::new(foo), |foo| foo.try_borrow_mut().map(|bar| Box::new(bar)), |bar| bar.try_borrow_mut().map(|baz| Box::new(baz)), |baz| baz.try_borrow_mut().map(|qux| Box::new(qux)), |qux| qux.fail_borrow_mut() ); assert!(cm.is_err()); } #[test] fn read() { let foo = Foo { i: 5 }; let cm = rentals::ComplexRent::new( Box::new(foo), |foo| Box::new(foo.borrow_mut()), |bar| Box::new(bar.borrow_mut()), |baz| Box::new(baz.borrow_mut()), |qux| qux.borrow_mut() ); let i = cm.rent(|xyzzy| xyzzy.qux.baz.bar.foo.i); assert_eq!(i, 5); let iref = cm.ref_rent(|xyzzy| &xyzzy.qux.baz.bar.foo.i); assert_eq!(*iref, 5); } #[test] fn write() { let foo = Foo { i: 5 }; let mut cm = rentals::ComplexRent::new( Box::new(foo), |foo| Box::new(foo.borrow_mut()), |bar| Box::new(bar.borrow_mut()), |baz| Box::new(baz.borrow_mut()), |qux| qux.borrow_mut() ); { let iref: &mut i32 = cm.ref_rent_mut(|xyzzy| &mut xyzzy.qux.baz.bar.foo.i); *iref = 12; } let i = cm.rent(|xyzzy| xyzzy.qux.baz.bar.foo.i); assert_eq!(i, 12); }