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

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

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,使用没有结构的代码,但问题依然存在。

use std::cell::RefCell;
use std::rc::Rc;

use wasm_bindgen_futures::spawn_local;

use wasm_bindgen::prelude::*;

pub struct MyClass {
    value: u32,
}

impl MyClass {
    pub fn new() -&gt; Self {
        return Self { value: 0 };
    }

    pub async fn boot_async(this: Rc&lt;RefCell&lt;&amp;mut Self&gt;&gt;) {
        this.borrow_mut().value += 1;
    }

    pub fn boot(&amp;mut self) {
        let this = Rc::new(RefCell::new(self));
        let async_function = MyClass::boot_async(this.clone());
        spawn_local(async_function);
    }
}

#[wasm_bindgen(start)]
fn start() {
    let mut test = MyClass::new();
    test.boot();
}

然后我得到了以下错误:

error[E0521]: borrowed data escapes outside of method
  --&gt; src/main.rs:29:30
   |
27 |     pub fn boot(&amp;mut self) {
   |                 ---------
   |                 |
   |                 `self` is a reference that is only valid in the method body
   |                 let&#39;s call the lifetime of this reference `&#39;1`
28 |         let this = Rc::new(RefCell::new(self));
29 |         let async_function = MyClass::boot_async(this.clone());
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                              |
   |                              `self` escapes the method body here
   |                              argument requires that `&#39;1` must outlive `&#39;static`
   |
   = note: requirement occurs because of the type `RefCell&lt;&amp;mut MyClass&gt;`, which makes the generic argument `&amp;mut MyClass` invariant
   = note: the struct `RefCell&lt;T&gt;` is invariant over the parameter `T`
   = 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.

use std::cell::RefCell;
use std::rc::Rc;

use wasm_bindgen_futures::spawn_local;

use wasm_bindgen::prelude::*;

pub struct MyClass {
    value: u32,
}

impl MyClass {
    pub fn new() -&gt; Self {
        return Self { value: 0 };
    }

    pub async fn boot_async(this: Rc&lt;RefCell&lt;&amp;mut Self&gt;&gt;) {
        this.borrow_mut().value += 1;
    }

    pub fn boot(&amp;mut self) {
        let this = Rc::new(RefCell::new(self));
        let async_function = MyClass::boot_async(this.clone());
        spawn_local(async_function);
    }
}

#[wasm_bindgen(start)]
fn start() {
    let mut test = MyClass::new();
    test.boot();
}

And I get:

error[E0521]: borrowed data escapes outside of method
  --&gt; src/main.rs:29:30
   |
27 |     pub fn boot(&amp;mut self) {
   |                 ---------
   |                 |
   |                 `self` is a reference that is only valid in the method body
   |                 let&#39;s call the lifetime of this reference `&#39;1`
28 |         let this = Rc::new(RefCell::new(self));
29 |         let async_function = MyClass::boot_async(this.clone());
   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                              |
   |                              `self` escapes the method body here
   |                              argument requires that `&#39;1` must outlive `&#39;static`
   |
   = note: requirement occurs because of the type `RefCell&lt;&amp;mut MyClass&gt;`, which makes the generic argument `&amp;mut MyClass` invariant
   = note: the struct `RefCell&lt;T&gt;` is invariant over the parameter `T`
   = 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:

impl MyClass {
    pub fn new() -&gt; Self {
        return Self { value: 0 };
    }

    pub async fn boot_async(this: Rc&lt;RefCell&lt;Self&gt;&gt;) {
        this.borrow_mut().value += 1;
    }

    pub fn boot(self) {
        let this = Rc::new(RefCell::new(self));
        let async_function = MyClass::boot_async(this.clone());
        spawn_local(async_function);
    }
}
英文:

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

impl MyClass {
    pub fn new() -&gt; Self {
        return Self { value: 0 };
    }

    pub async fn boot_async(this: Rc&lt;RefCell&lt;Self&gt;&gt;) {
        this.borrow_mut().value += 1;
    }

    pub fn boot(self) {
        let this = Rc::new(RefCell::new(self));
        let async_function = MyClass::boot_async(this.clone());
        spawn_local(async_function);
    }
}

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:

确定