This is the same problem discussed in Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?. Through lifetime elision, the lifetime of the &str
is tied to the lifetime of &self
. The compiler isn't aware that the borrow won't be used in the condition that an Ok
is returned. It's overly conservative and disallows this code. This is a limitation of the current borrow checker implementation.
If you did need the lifetime of the Err
variant to be tied to the lifetime of the Foo
instance, there's not much to be done in safe Rust (unsafe Rust is another story). In your case, however, it seems unlikely that your &str
is intended to be tied to the lifetime of self
, so you can use explicit lifetimes to avoid the problem. For example, a &'static str
is a common basic error type:
impl Foo {
fn mutable1(&mut self) -> Result<(), &'static str> {
Ok(())
}
fn mutable2(&mut self) -> Result<(), &'static str> {
self.mutable1()?;
self.mutable1()?;
Ok(())
}
}
as it's the presence of the implicit return provided by ?
Not really, as the same code with explicit returns has the same problem:
fn mutable2(&mut self) -> Result<(), &str> {
if let Err(e) = self.mutable1() {
return Err(e);
}
if let Err(e) = self.mutable1() {
return Err(e);
}
Ok(())
}
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/lib.rs:12:25
|
8 | fn mutable2(&mut self) -> Result<(), &str> {
| - let's call the lifetime of this reference `'1`
9 | if let Err(e) = self.mutable1() {
| ---- first mutable borrow occurs here
10 | return Err(e);
| ------ returning this value requires that `*self` is borrowed for `'1`
11 | }
12 | if let Err(e) = self.mutable1() {
| ^^^^ second mutable borrow occurs here
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…