在这里,难以理解`self`逃离了方法体。

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

Trouble understanding `self` escapes the method body here

问题

I'm very new to Rust. I've been through the various books etc but I'm consistently having issues with code like the following.

This is a simple repro that follows the function prototype of a package I'm using

#[derive(Default)]
struct DoSomething {
    x: i32,
}

fn some_func(loader: impl FnOnce() + 'static) {}

impl DoSomething {
    async fn do_something(&mut self) {
        some_func(|| {
            self.x = 100;
        });
    }
}

I get a compiler error in the call to some_func

error[E0521]: borrowed data escapes outside of method
  --> src\main.rs:44:9
   |
43 |       async fn do_something(&mut self) {
   |                             ---------
   |                             |
   |                             `self` is a reference that is only valid in the method body
   |                             let's call the lifetime of this reference `'1`
44 | /         some_func(|| {
45 | |             self.x = 100;
46 | |         });
   | |          ^
   | |          |
   | |__________`self` escapes the method body here
   |            argument requires that `'1` must outlive `'static`

Now I get that because the closure captures the reference of self and combined with 'static on some_func, the borrow checker can't be sure that self will be valid when the closure is eventually executed. Is that correct?

Now the million dollar question. What's the right way to do something like this?

For completeness, the package I'm using is called callback-future which allows me to turn a callback into a future. The full code I want to get working is:

async fn some_async(&mut self) -> Result<String, i32> {
    CallbackFuture::new(|complete| {
        self.cb = Some(complete);
    })
    .await
}

The idea is to store the complete Fn passed into the closure so I can execute when some later async workflows have completed.

英文:

I'm very new to Rust. I've been through the various books etc but I'm consistently having issues with code like the following.

This is a simple repro that follows the function prototype of a package I'm using

#[derive(Default)]
struct DoSomething {
    x: i32,
}

fn some_func(loader: impl FnOnce() + &#39;static) {}

impl DoSomething {
    async fn do_something(&amp;mut self) {
        some_func(|| {
            self.x = 100;
        });
    }
}

I get a compiler error in the call to some_func

error[E0521]: borrowed data escapes outside of method
  --&gt; src\main.rs:44:9
   |
43 |       async fn do_something(&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`
44 | /         some_func(|| {
45 | |             self.x = 100;
46 | |         });
   | |          ^
   | |          |
   | |__________`self` escapes the method body here
   |            argument requires that `&#39;1` must outlive `&#39;static`

Now I get that because the closure captures the reference of self and combined with 'static on some_func, the borrow checker can't be sure that self will be valid when the closure is eventually executed. Is that correct?

Now the million dollar question. Whats the right way to do something like this?

For completeness, the package I'm using is called callback-future which allows me to turn a callback into a future. The full code I want to get working is:

    async fn some_async(&amp;mut self) -&gt; Result&lt;String, i32&gt; {
        CallbackFuture::new(|complete| {
            self.cb = Some(complete);
        })
        .await
    }

The idea is to store the complete Fn passed into the closure so I can execute when some later async workflows have completed.

答案1

得分: 0

因为库要求一个由'static绑定的FnOnce,所以您必须确保传递到闭包中的所有引用也至少是'static。这是最简单的解决方案:

impl DoSomething {
    async fn do_something(&'static mut self) {
        some_func(|| self.x = 100);
    }
}

我建议您查看不同的crate,通常您必须泄漏内存以获得静态引用。

英文:

Because the library requires a FnOnce bound by &#39;static, you must ensure that all references passed into the closure are also at least &#39;static. This is the easiest solution:

impl DoSomething {
    async do_something(&amp;&#39;static mut self) {
        some_func(|| self.x = 100);
    }
}

I recommend looking into a different crate, usually you have to leak memory to obtain a static reference.

huangapple
  • 本文由 发表于 2023年5月17日 18:35:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76271168.html
匿名

发表评论

匿名网友

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

确定