昨天在搜索一个问题时发现一个例子:
fn main() {
let mut p = Processor::new();
let s = String::from("123");
{
p.set_callback(|| println!("{}", s.len()));
}
p.invoke();
println!("last {}", s);
}
struct Processor<'a> {
callback: Box<dyn Fn() + 'a>,
}
impl<'a> Processor<'a> {
fn new() -> Processor<'a> {
Processor { callback: Box::new(|| ()) }
}
fn set_callback<CB: 'a + Fn()>(&mut self, c: CB) {
self.callback = Box::new(c);
}
fn invoke(&self) {
(self.callback)();
}
}
这段代码是无法通过的,提示如下:
|
37 | p.set_callback(|| println!("{}", s.len()));
| -- ^ borrowed value does not live long enough
| |
| value captured here
...
43 | }
| -
| |
| `s` dropped here while still borrowed
| borrow might be used here, when `p` is dropped and runs the destructor for type `Processor<'_>`
|
= note: values in a scope are dropped in the opposite order they are defined
我按照原文的提示将s
的定义移到了p
之前即可通过。答案地址
休息时候我想了下觉得有点问题,因为在之前看生命周期时没发现变量定义的先后会造成这种问题,于是猜想是不是结构体或是闭包导致的问题,于是重新写了一段代码想验证一下,发现依然是无法通过编译:
let mut g :Box<dyn Fn()>;
let s = String::from("123");
{
g = Box::new(|| { println!("{}", &s) });
}
println!("{}", s);
// println!("{}", s);
g();
23 | g = Box::new(|| { println!("{}", &s) });
| -- ^ borrowed value does not live long enough
| |
| value captured here
...
31 | }
| -
| |
| `s` dropped here while still borrowed
| borrow might be used here, when `g` is dropped and runs the destructor for type `Box<dyn Fn()>`
|
= note: values in a scope are dropped in the opposite order they are defined
到这里我排除了结构体的问题,觉得是闭包的问题,于是写了下面这段代码发现可以通过编译:
struct Foo<'a> {
x: Box<Option<&'a String>>,
}
let mut x = Foo { x: Box::new(None) };
let y = String::from("asd");
{
x.x = Box::new(Some(&y));
}
println!("{:?}", x.x);
到这里我又去翻了下闭包和生命周期相关的章节,发现并没有相关描述,到github搜了下也没有类似issue,麻烦问下这是一种错误的编译器提示还是闭包的引用导致的问题?
1
共 6 条评论, 1 页
评论区
写评论感谢老哥。看了下应该是这段话。二者结合导致出现了在区块边缘提示
s dropped here while still borrowed
,而修改s变量相对位置则可解决问题。--
👇
johnmave126: 这是一个典型的drop顺序的问题
参考这个回答
--
👇
w: 我再搜一搜,看看issue里有没有
--
👇
uno: 感觉是drop顺序的问题,,你后面的那段代码也是交换一下位置就行了。 ....
这是一个典型的drop顺序的问题
参考这个回答
--
👇
w: 我再搜一搜,看看issue里有没有
--
👇
uno: 感觉是drop顺序的问题,,你后面的那段代码也是交换一下位置就行了。 ....
我再搜一搜,看看issue里有没有
--
👇
uno: 感觉是drop顺序的问题,,你后面的那段代码也是交换一下位置就行了。 ....
我加了这样的生命周期,得到了和我这个事例一样的错误信息:
| 21 | ||{self.foo()} | -- ^^^^ borrowed value does not live long enough | | | value captured here 22 | } | - | | |
self
dropped here while still borrowed | borrow later used here--
👇
Bai-Jinlin: 我也碰到过和你差不多的问题,我想实现的是类的一个方法返回一个闭包,这里闭包里调用了这个类的方法,并且不move self,但是生命周期不管如何标注都会有问题,不用unsafe根本解决不了。
这里的r就会出出问题,生命周期标注就算用'a:'b这种也不行,只能改成
感觉是drop顺序的问题,,你后面的那段代码也是交换一下位置就行了。
或者直接去掉g的类型定义,也可以。
我也碰到过和你差不多的问题,我想实现的是类的一个方法返回一个闭包,这里闭包里调用了这个类的方法,并且不move self,但是生命周期不管如何标注都会有问题,不用unsafe根本解决不了。
这里的r就会出出问题,生命周期标注就算用'a:'b这种也不行,只能改成