Why is the following invalid and what should I do instead to make it work?
struct Foo;
impl Foo {
fn mutable1(&
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. 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