Cannot borrow `*self` as mutable more than once at a time when returning a Result containing a reference

前端 未结 1 887
眼角桃花
眼角桃花 2020-12-22 10:41

Why is the following invalid and what should I do instead to make it work?

struct Foo;

impl Foo {
    fn mutable1(&         


        
相关标签:
1条回答
  • 2020-12-22 11:40

    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
    
    
    0 讨论(0)
提交回复
热议问题