金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  423 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks
# &'a mut self is restrictive

From https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md#5-if-it-compiles-then-my-lifetime-annotations-are-correct

```
#[derive(Debug)]
struct NumRef<'a>(&'a i32);

impl<'a> NumRef<'a> {
    // my struct is generic over 'a so that means I need to annotate
    // my self parameters with 'a too, right? (answer: no, not right)
    fn some_method(&'a mut self) {}
}

fn main() {
    let mut num_ref = NumRef(&5);
    num_ref.some_method(); // mutably borrows num_ref for the rest of its lifetime
    num_ref.some_method(); // ❌
    println!("{:?}", num_ref); // ❌
}
```

If we have some struct generic over 'a we almost never want to write a method with a &'a mut self receiver. 
What we're communicating to Rust is "this method will mutably borrow the struct for the entirety of the struct's lifetime". 
In practice this means Rust's borrow checker will only allow at most one call to some_method 
before the struct becomes permanently mutably borrowed and thus unusable. 
The use-cases for this are extremely rare but the code above is very easy for confused beginners to write and it compiles. 
The fix is to not add unnecessary explicit lifetime annotations and let Rust's lifetime elision rules handle it:

```
#[derive(Debug)]
struct NumRef<'a>(&'a i32);

impl<'a> NumRef<'a> {
    // no more 'a on mut self
    fn some_method(&mut self) {}

    // above line desugars to
    fn some_method_desugared<'b>(&'b mut self){}
}

fn main() {
    let mut num_ref = NumRef(&5);
    num_ref.some_method();
    num_ref.some_method(); // ✅
    println!("{:?}", num_ref); // ✅
}
```
posted on 2021-08-25 13:32 金庆 阅读(194) 评论(0)  编辑 收藏 引用 所属分类: 8. Rust

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理