Good day!
I am struggling to understand the difference between an argument of the concrete type implementing a trait vs. an argument of type bound by the same trait which implications on lifetime and borrowing.
The original code:
#![allow(dead_code,unused_imports,unused_variables)]
trait Trait<'a> {
fn m(&self, options: &'a mut i32) -> usize { 0 }
}
struct Impl;
impl<'a> Trait<'a> for Impl {}
struct S { f: i32 }
impl S {
fn m<'a, F: Trait<'a>>(&mut self, f: Impl, f2: F) -> &mut i32 {
f2.m(&mut self.f);
&mut self.f
}
}
This fails to compile:
src/lib.rs:15:14: 15:25 error: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
src/lib.rs:15 f2.m(&mut self.f);
^~~~~~~~~~~
src/lib.rs:14:5: 17:6 help: consider using an explicit lifetime parameter as shown: fn m<'a, F: Trait<'a>>(&'a mut self, f: Impl, f2: F) -> &mut i32
src/lib.rs:14 fn m<'a, F: Trait<'a>>(&mut self, f: Impl, f2: F) -> &mut i32 {
src/lib.rs:15 f2.m(&mut self.f);
src/lib.rs:16 &mut self.f
src/lib.rs:17 }
However if I change f2.m
to f.m
, everything works fine.
Now let's follow the advice of the compiler and add lifetime marker:
#![allow(dead_code,unused_imports,unused_variables)]
trait Trait<'a> {
fn m(&self, options: &'a mut i32) -> usize { 0 }
}
struct Impl;
impl<'a> Trait<'a> for Impl {}
struct S { f: i32 }
impl S {
fn m<'a, F: Trait<'a>>(&'a mut self, f: Impl, f2: F) -> &mut i32 {
f2.m(&mut self.f);
&mut self.f
}
}
Now again f2
variant fails to compile:
src/lib.rs:16:14: 16:20 error: cannot borrow `self.f` as mutable more than once at a time
src/lib.rs:16 &mut self.f
^~~~~~
src/lib.rs:15:19: 15:25 note: previous borrow of `self.f` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `self.f` until the borrow ends
src/lib.rs:15 f2.m(&mut self.f);
^~~~~~
src/lib.rs:17:6: 17:6 note: previous borrow ends here
src/lib.rs:14 fn m<'a, F: Trait<'a>>(&'a mut self, f: Impl, f2: F) -> &mut i32 {
src/lib.rs:15 f2.m(&mut self.f);
src/lib.rs:16 &mut self.f
src/lib.rs:17 }
And f
variant again compiles just fine.
May some one, please, explain, what goes on here?
cheers and tia,
anton.