如何在Rust Wasm中修改数据?遇到借用检查错误。

huangapple go评论94阅读模式
英文:

How do you mutate data in Rust Wasm? Getting borrow checker errors

问题

I've translated the provided text for you:

我已经尝试了从 Rc<RefCell> 到 Arc 和 Mutex,async_std 甚至不能编译,尽管它显然包括 wasm 支持。
我已经与这个错误斗争了几天,但我无法理解问题,因为非 wasm 似乎工作正常,而 Promise 没有任何区别。我也尝试了不使用 self,使用没有结构的代码,但问题依然存在。

  1. use std::cell::RefCell;
  2. use std::rc::Rc;
  3. use wasm_bindgen_futures::spawn_local;
  4. use wasm_bindgen::prelude::*;
  5. pub struct MyClass {
  6. value: u32,
  7. }
  8. impl MyClass {
  9. pub fn new() -&gt; Self {
  10. return Self { value: 0 };
  11. }
  12. pub async fn boot_async(this: Rc&lt;RefCell&lt;&amp;mut Self&gt;&gt;) {
  13. this.borrow_mut().value += 1;
  14. }
  15. pub fn boot(&amp;mut self) {
  16. let this = Rc::new(RefCell::new(self));
  17. let async_function = MyClass::boot_async(this.clone());
  18. spawn_local(async_function);
  19. }
  20. }
  21. #[wasm_bindgen(start)]
  22. fn start() {
  23. let mut test = MyClass::new();
  24. test.boot();
  25. }

然后我得到了以下错误:

  1. error[E0521]: borrowed data escapes outside of method
  2. --&gt; src/main.rs:29:30
  3. |
  4. 27 | pub fn boot(&amp;mut self) {
  5. | ---------
  6. | |
  7. | `self` is a reference that is only valid in the method body
  8. | let&#39;s call the lifetime of this reference `&#39;1`
  9. 28 | let this = Rc::new(RefCell::new(self));
  10. 29 | let async_function = MyClass::boot_async(this.clone());
  11. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  12. | |
  13. | `self` escapes the method body here
  14. | argument requires that `&#39;1` must outlive `&#39;static`
  15. |
  16. = note: requirement occurs because of the type `RefCell&lt;&amp;mut MyClass&gt;`, which makes the generic argument `&amp;mut MyClass` invariant
  17. = note: the struct `RefCell&lt;T&gt;` is invariant over the parameter `T`
  18. = help: see &lt;https://doc.rust-lang.org/nomicon/subtyping.html&gt; for more information about variance
英文:

I've tried everything from Rc<RefCell> to Arc and Mutex async_std which wouldn't even compile despite it apparently including wasm support.
I've been fighting with this error for a few days now and I can't fathom the problem when non-wasm seems to work fine and Promise no different. Tried it on not-self as well, using struct-less code, same problem.

  1. use std::cell::RefCell;
  2. use std::rc::Rc;
  3. use wasm_bindgen_futures::spawn_local;
  4. use wasm_bindgen::prelude::*;
  5. pub struct MyClass {
  6. value: u32,
  7. }
  8. impl MyClass {
  9. pub fn new() -&gt; Self {
  10. return Self { value: 0 };
  11. }
  12. pub async fn boot_async(this: Rc&lt;RefCell&lt;&amp;mut Self&gt;&gt;) {
  13. this.borrow_mut().value += 1;
  14. }
  15. pub fn boot(&amp;mut self) {
  16. let this = Rc::new(RefCell::new(self));
  17. let async_function = MyClass::boot_async(this.clone());
  18. spawn_local(async_function);
  19. }
  20. }
  21. #[wasm_bindgen(start)]
  22. fn start() {
  23. let mut test = MyClass::new();
  24. test.boot();
  25. }

And I get:

  1. error[E0521]: borrowed data escapes outside of method
  2. --&gt; src/main.rs:29:30
  3. |
  4. 27 | pub fn boot(&amp;mut self) {
  5. | ---------
  6. | |
  7. | `self` is a reference that is only valid in the method body
  8. | let&#39;s call the lifetime of this reference `&#39;1`
  9. 28 | let this = Rc::new(RefCell::new(self));
  10. 29 | let async_function = MyClass::boot_async(this.clone());
  11. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  12. | |
  13. | `self` escapes the method body here
  14. | argument requires that `&#39;1` must outlive `&#39;static`
  15. |
  16. = note: requirement occurs because of the type `RefCell&lt;&amp;mut MyClass&gt;`, which makes the generic argument `&amp;mut MyClass` invariant
  17. = note: the struct `RefCell&lt;T&gt;` is invariant over the parameter `T`
  18. = help: see &lt;https://doc.rust-lang.org/nomicon/subtyping.html&gt; for more information about variance

答案1

得分: 2

The problem is that Rc doesn't help since you still have a reference. You need to get rid of it:

  1. impl MyClass {
  2. pub fn new() -&gt; Self {
  3. return Self { value: 0 };
  4. }
  5. pub async fn boot_async(this: Rc&lt;RefCell&lt;Self&gt;&gt;) {
  6. this.borrow_mut().value += 1;
  7. }
  8. pub fn boot(self) {
  9. let this = Rc::new(RefCell::new(self));
  10. let async_function = MyClass::boot_async(this.clone());
  11. spawn_local(async_function);
  12. }
  13. }
英文:

Your were close. The problem is that Rc doesn't help since you still have a reference. You need to get rid of it:

  1. impl MyClass {
  2. pub fn new() -&gt; Self {
  3. return Self { value: 0 };
  4. }
  5. pub async fn boot_async(this: Rc&lt;RefCell&lt;Self&gt;&gt;) {
  6. this.borrow_mut().value += 1;
  7. }
  8. pub fn boot(self) {
  9. let this = Rc::new(RefCell::new(self));
  10. let async_function = MyClass::boot_async(this.clone());
  11. spawn_local(async_function);
  12. }
  13. }

huangapple
  • 本文由 发表于 2023年5月21日 02:01:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76296664.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定