英文:
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() -> Self {
return Self { value: 0 };
}
pub async fn boot_async(this: Rc<RefCell<&mut Self>>) {
this.borrow_mut().value += 1;
}
pub fn boot(&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
--> src/main.rs:29:30
|
27 | pub fn boot(&mut self) {
| ---------
| |
| `self` is a reference that is only valid in the method body
| let's call the lifetime of this reference `'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 `'1` must outlive `'static`
|
= note: requirement occurs because of the type `RefCell<&mut MyClass>`, which makes the generic argument `&mut MyClass` invariant
= note: the struct `RefCell<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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() -> Self {
return Self { value: 0 };
}
pub async fn boot_async(this: Rc<RefCell<&mut Self>>) {
this.borrow_mut().value += 1;
}
pub fn boot(&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
--> src/main.rs:29:30
|
27 | pub fn boot(&mut self) {
| ---------
| |
| `self` is a reference that is only valid in the method body
| let's call the lifetime of this reference `'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 `'1` must outlive `'static`
|
= note: requirement occurs because of the type `RefCell<&mut MyClass>`, which makes the generic argument `&mut MyClass` invariant
= note: the struct `RefCell<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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() -> Self {
return Self { value: 0 };
}
pub async fn boot_async(this: Rc<RefCell<Self>>) {
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() -> Self {
return Self { value: 0 };
}
pub async fn boot_async(this: Rc<RefCell<Self>>) {
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);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论