提问人:Xavier Detant 提问时间:7/7/2023 更新时间:7/7/2023 访问量:92
“在借来的时候掉在这里”,当做出终身明确时
"dropped here while still borrowed" when making lifetime explicits
问:
我试图通过显式隐式生存期来提高我对 rust borrow 检查器的理解。它实际上来自一个更大的工作问题,但我把它归结为这个(到目前为止)。
我们以这段代码为例:
struct StringWrapper<'a>(&'a str);
struct StringWrapperWrapper<'a>(&'a StringWrapper<'a>);
struct ContainingAValue {
value: String,
}
impl ContainingAValue {
fn do_something_with_wrapper<F>(&self, f: F)
where
F: FnOnce(StringWrapper) -> (),
{
let wrapper = StringWrapper(&self.value);
f(wrapper)
}
fn do_something_with_wrapper_wrapper<F>(&self, f: F)
where
F: FnOnce(StringWrapperWrapper) -> (),
{
let wrapper = StringWrapper(&self.value);
let tmp = StringWrapperWrapper(&wrapper);
f(tmp)
}
}
此代码编译正常。现在,我想在实现中明确生命周期。
impl ContainingAValue {
fn do_something_with_wrapper<'a, F>(&'a self, f: F)
where
F: FnOnce(StringWrapper<'a>) -> (),
{
let wrapper = StringWrapper(&self.value);
f(wrapper)
}
fn do_something_with_wrapper_wrapper<'a, F>(&'a self, f: F)
where
F: FnOnce(StringWrapperWrapper<'_>) -> (),
{
let wrapper = StringWrapper(&self.value);
let tmp = StringWrapperWrapper(&wrapper);
f(tmp)
}
}
在那之前,它也可以正常编译。
现在,最大的问题是:我应该把什么寿命而不是放在 的 ?'_
StringWrapperWrapper<'_>
do_something_with_wrapper_wrapper
我认为这会起作用(在错误中添加了行号以供参考):
17 │ fn do_something_with_wrapper_wrapper<'a, F>(&'a self, f: F)
18 │ where
19 ~ │ F: FnOnce(StringWrapperWrapper<'a>) -> (),
20 │ {
21 │ let wrapper = StringWrapper(&self.value);
22 │ let tmp = StringWrapperWrapper(&wrapper);
23 │ f(tmp)
24 │ }
但我得到:
|
17 | fn do_something_with_wrapper_wrapper<'a, F>(&'a self, f: F)
| -- lifetime `'a` defined here
...
21 | let wrapper = StringWrapper(&self.value);
| ------- binding `wrapper` declared here
22 | let tmp = StringWrapperWrapper(&wrapper);
| ^^^^^^^^
| |
| borrowed value does not live long enough
| this usage requires that `wrapper` is borrowed for `'a`
23 | f(tmp)
24 | }
| - `wrapper` dropped here while still borrowed
所以,我试图添加一个不同的生命周期:
17 ~ │ fn do_something_with_wrapper_wrapper<'a: 'b, 'b, F>(&'a self, f: F)
18 │ where
19 ~ │ F: FnOnce(StringWrapperWrapper<'b>) -> (),
20 │ {
21 │ let wrapper = StringWrapper(&self.value);
22 │ let tmp = StringWrapperWrapper(&wrapper);
23 │ f(tmp)
24 │ }
但得到完全相同的错误(被替换为 )。'a
'b
我使用 a 的事实对于我的用例和错误很重要,因为这会编译:FnOnce
fn do_something_with_wrapper_wrapper<'a, F>(&'a self, f: F)
where
F: FnOnce(StringWrapperWrapper<'a>) -> (),
{
let wrapper = StringWrapper(&self.value);
let tmp = StringWrapperWrapper(&wrapper);
// f(tmp)
}
答:
1赞
jthulhu
7/7/2023
#1
这是更高等级特征边界的完美用例。正确的代码应该是
impl ContainingAValue {
fn do_something_with_wrapper<'a, F>(&'a self, f: F)
where
F: for<'b> FnOnce(StringWrapper<'b>) -> (),
{
let wrapper = StringWrapper(&self.value);
f(wrapper)
}
fn do_something_with_wrapper_wrapper<'a, F>(&'a self, f: F)
where
F: for<'b> FnOnce(StringWrapperWrapper<'b>) -> (),
{
let wrapper = StringWrapper(&self.value);
let tmp = StringWrapperWrapper(&wrapper);
f(tmp)
}
}
这个想法是,无论参数的生存期如何,您都希望工作,这意味着它特别适用于受 作用域限制的生存期,该作用域不能在 之外命名。f
do_something_with_wrapper_wrapper
do_something_with_wrapper_wrapper
你在表达什么
fn do_something_with_wrapper_wrapper<'a, F>(&'a self, f: F)
where
F: FnOnce(StringWrapperWrapper<'a>) -> (),
{
let wrapper = StringWrapper(&self.value);
let tmp = StringWrapperWrapper(&wrapper);
f(tmp)
}
是调用方选择其参数所需的生存期,该生存期可能比 的范围长。do_something_with_wrapper_wrapper
f
do_something_with_wrapper_wrapper
评论
0赞
Xavier Detant
7/7/2023
你是救命恩人。这完全有道理。我不知道那个符号。多谢!
0赞
Xavier Detant
7/8/2023
这是一个关于如何概括(和使用)的后续问题:stackoverflow.com/questions/76638405/......
评论