rust 为什么借入检查器不能在Arc::get_mut None的情况下删除引用

dzhpxtsq  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(201)

试着做一些

  1. use std::sync::Arc;
  2. struct Foo(Arc<Bar>);
  3. # [derive(Clone)]
  4. struct Bar;
  5. impl Foo {
  6. fn bar_mut(&mut self) -> &mut Bar {
  7. match Arc::get_mut(&mut self.0) {
  8. Some(bar) => bar,
  9. None => {
  10. let new_bar = Bar::clone(&self.0);
  11. self.0 = Arc::new(new_bar);
  12. Arc::get_mut(&mut self.0).unwrap()
  13. }
  14. }
  15. }
  16. }
  17. fn main() {
  18. Foo(Arc::new(Bar)).bar_mut();
  19. }

但我得到以下错误:

  1. * Executing task: cargo check
  2. Checking testproj v0.1.0 (/home/dspyz/testproj)
  3. error[E0502]: cannot borrow `self.0` as immutable because it is also borrowed as mutable
  4. --> src/main.rs:13:42
  5. |
  6. 9 | fn bar_mut(&mut self) -> &mut Bar {
  7. | - let's call the lifetime of this reference `'1`
  8. 10 | match Arc::get_mut(&mut self.0) {
  9. | - ----------- mutable borrow occurs here
  10. | _________|
  11. | |
  12. 11 | | Some(bar) => bar,
  13. 12 | | None => {
  14. 13 | | let new_bar = Bar::clone(&self.0);
  15. | | ^^^^^^^ immutable borrow occurs here
  16. ... |
  17. 16 | | }
  18. 17 | | }
  19. | |_________- returning this value requires that `self.0` is borrowed for `'1`
  20. error[E0506]: cannot assign to `self.0` because it is borrowed
  21. --> src/main.rs:14:17
  22. |
  23. 9 | fn bar_mut(&mut self) -> &mut Bar {
  24. | - let's call the lifetime of this reference `'1`
  25. 10 | match Arc::get_mut(&mut self.0) {
  26. | - ----------- borrow of `self.0` occurs here
  27. | _________|
  28. | |
  29. 11 | | Some(bar) => bar,
  30. 12 | | None => {
  31. 13 | | let new_bar = Bar::clone(&self.0);
  32. 14 | | self.0 = Arc::new(new_bar);
  33. | | ^^^^^^ assignment to borrowed `self.0` occurs here
  34. 15 | | Arc::get_mut(&mut self.0).unwrap()
  35. 16 | | }
  36. 17 | | }
  37. | |_________- returning this value requires that `self.0` is borrowed for `'1`
  38. error[E0499]: cannot borrow `self.0` as mutable more than once at a time
  39. --> src/main.rs:15:30
  40. |
  41. 9 | fn bar_mut(&mut self) -> &mut Bar {
  42. | - let's call the lifetime of this reference `'1`
  43. 10 | match Arc::get_mut(&mut self.0) {
  44. | - ----------- first mutable borrow occurs here
  45. | _________|
  46. | |
  47. 11 | | Some(bar) => bar,
  48. 12 | | None => {
  49. 13 | | let new_bar = Bar::clone(&self.0);
  50. 14 | | self.0 = Arc::new(new_bar);
  51. 15 | | Arc::get_mut(&mut self.0).unwrap()
  52. | | ^^^^^^^^^^^ second mutable borrow occurs here
  53. 16 | | }
  54. 17 | | }
  55. | |_________- returning this value requires that `self.0` is borrowed for `'1`
  56. Some errors have detailed explanations: E0499, E0502, E0506.
  57. For more information about an error, try `rustc --explain E0499`.
  58. error: could not compile `testproj` due to 3 previous errors
  • 终端进程“货'检'"启动失败(退出代码:101页)。
  • 终端将被任务重复使用,按任意键关闭它。
zpf6vheq

zpf6vheq1#

借位检查器并不完美,仍然有一些情况下,它很难确定所涉及的生存期。每个版本都有改进,但目前,它很难弄清楚如何在代码中分配生存期。
它看到函数应该返回一个值&'0 mut Bar,并将该生存期'0赋给Arc::get_mut的输出。但是,这将意味着,当您随后试图在函数中重用这些值时,所使用的可变借位也将需要在导致错误的函数的持续时间内存在。希望这将在Rust编译器的后续版本中得到修复。
这很烦人,但是我们可以通过先检查None的情况来避免这个问题。如果运气好的话,编译器应该能够优化它,得到相同的输出。

  1. fn bar_mut(&mut self) -> &mut Bar {
  2. if Arc::get_mut(&mut self.0).is_none() {
  3. self.0 = Arc::new(Bar::clone(&*self.0));
  4. }
  5. Arc::get_mut(&mut self.0).unwrap()
  6. }

相关问题