[英]Const array of closures taking a mutable reference to a struct with lifetime parameter in Rust
I have the following scenario in a Rust project: 我在Rust项目中有以下情形:
struct Foo<'a> {
stuff: &'a i32,
}
thus I'm telling the compiler that my Foo
struct holds a reference to something and I have to give it a lifetime to make that work, fine. 因此,我告诉编译器,我的
Foo
结构拥有对某些内容的引用,因此我必须给它一个终身以使其正常工作。
Now, I declare this: 现在,我声明一下:
type FooFunc<'a> = &'a dyn Fn(&'a mut Foo<'a>) -> bool;
const funcs: [FooFunc; 4] = [
&|f| { *f.stuff = 0; false },
&|f| { *f.stuff = 1; true },
&|f| { *f.stuff = 2; true },
&|f| { *f.stuff = 3; true },
];
and try to call a closure from that const array inside a "method" of Foo
: 并尝试从
Foo
的“方法”内的该const数组调用一个闭包:
impl<'a> Foo<'a> {
fn bar(&mut self, i: usize) -> bool {
funcs[i](self)
}
}
Reasoning about lifetimes, this should be fine since the self
reference to the Foo
struct has a lifetime 'a
(which sure thing doesn't outlive 'static
, that is the lifetime of the closures) so the closures should be able to receive self
as a parameter without any issue. 关于生命周期的推理,这应该没问题,因为对
Foo
结构的self
引用具有生命周期'a
(确保事物不会超过'static
,即闭包的生存期),因此闭包应该能够将self
接收为没有任何问题的参数。
And the borrow checker sort of agrees with this, but still reports an error I don't understand: 借阅检查器对此表示同意,但仍然报告一个我不理解的错误:
error[E0308]: mismatched types
--> src/main.rs:7:18
|
7 | funcs[i](self)
| ^^^^ lifetime mismatch
|
= note: expected type `&'static mut Foo<'static>`
found type `&'static mut Foo<'a>`
note: the lifetime 'a as defined on the impl at 5:6...
--> src/main.rs:5:6
|
5 | impl<'a> Foo<'a> {
| ^^
= note: ...does not necessarily outlive the static lifetime
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/main.rs:7:18
|
7 | funcs[i](self)
| ^^^^
|
= note: ...the reference is valid for the static lifetime...
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 6:5
--> src/main.rs:6:5
|
6 | / fn bar(&mut self, i: usize) -> bool {
7 | | funcs[i](self)
8 | | }
| |_____^
It's telling me (in the note
tags) that the lifetime 'a as defined on the impl at 5:6 does not necessarily outlive the static lifetime
and that the reference is valid for the static lifetime but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 6:5
. 告诉我(在
note
标记中), the lifetime 'a as defined on the impl at 5:6 does not necessarily outlive the static lifetime
, the reference is valid for the static lifetime but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 6:5
。 While a compiler giving these kind of error messages is amazing, I still don't get what the problem is. 尽管提供此类错误消息的编译器令人惊叹,但我仍然不明白问题出在哪里。
Talking about the second note
(which is the one that sort of (tries to) explain the issue), I can't understand if the borrowed content is meant to be the const array or the self reference, but in either case: 谈到第二个
note
(这是一种(尝试)解释该问题的note
),我无法理解借来的内容是用于const数组还是用于自我引用,但无论哪种情况:
if the "borrowed content" is the const array, why would that be a problem even if an anonymous lifetime that matches the function body has been assigned to it? 如果“借用的内容”是const数组,那么即使分配了与函数体匹配的匿名生存期,也为什么会有问题? The closure just has to operate on the reference that gets passed as a parameter and return by transferring ownership of the return value, and not by returning a reference with some weird lifetime that could cause problems.
闭包只需要对作为参数传递的引用进行操作,并通过转移返回值的所有权来返回,而不是通过返回具有可能导致问题的奇怪寿命的引用来返回。
if the "borrowed content" is the self reference, again, why would that be the problem? 如果“借来的内容”是自我参考,那又为什么呢? Okay, the self reference is no more
'a
, but it's another one (let's call it 'b
) which is "included" in 'a
, thus shouldn't outlive 'static
, right? 好的,自我引用不再是
'a
,而是另一个引用(称为'b
),它包含在'a
,因此不应该超过'static
,对不对?
Sure thing I'm missing something here, any help would be appreciated. 当然,我在这里缺少什么,任何帮助将不胜感激。
Note : all the code in this post is just a stripped down version of the "architecture" I'm trying to implement - of course the logic you see in the example code could be easily implemented in a way simple manner, but that's not what I need. 注意 :这篇文章中的所有代码只是我正在尝试实现的“体系结构”的简化版本-当然,您可以以简单的方式轻松实现示例代码中看到的逻辑,但这不是事实我需要。 I would like to have a table of operations to do on my struct (thus the idea to make the elements closures that accept a
&mut
reference) and run these operations from a "method" of my struct. 我想在我的结构上有一个要执行的操作表(这样的想法是使元素闭包接受
&mut
引用)并从我的结构的“方法”中运行这些操作。 The actual type in the actual project is instead [Option<[FooFunc<'a>; 6]>; 256]
实际项目中的实际类型是
[Option<[FooFunc<'a>; 6]>; 256]
[Option<[FooFunc<'a>; 6]>; 256]
[Option<[FooFunc<'a>; 6]>; 256]
, so we're talking a pretty big bi-dimensional "table", which I imagine would become quite unpleasant to implement with match
statements, especially considering I reuse FooFunc
s very often. [Option<[FooFunc<'a>; 6]>; 256]
,因此我们要说的是一个很大的二维“表”,我想用match
语句实现该表将变得非常不愉快,尤其是考虑到我经常重用FooFunc
。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=17034fe41c74d65d7a296ae812f19945 https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=17034fe41c74d65d7a296ae812f19945
The line type FooFunc<'a> = &'a dyn Fn(&'a mut Foo<'a>) -> bool;
线型
type FooFunc<'a> = &'a dyn Fn(&'a mut Foo<'a>) -> bool;
does not say "A FooFunc
is a reference of any lifetime to a closure which takes a reference of any lifetime (to a Foo
of the same lifetime)". 不说“A
FooFunc
是任何寿命到闭合这需要任何寿命的基准(对基准Foo
相同的寿命的)”。 Instead it says "A FooFunc<'a>
is a reference with a specific lifetime 'a
to a closure which takes a reference of that specific lifetime 'a
(to a Foo
of the same specific lifetime 'a
), which is the same every time that closure is called ." 相反,它说:“
FooFunc<'a>
是对具有特定生存期'a
的引用,该闭包引用了该特定生存期'a
的引用(对具有相同特定生存期'a
的Foo
的引用), 每个所谓的关闭时间 。”
Moreover, when you omit the lifetime in the item declaration ( [FooFunc; 4]
) it's inferred to be 'static
. 此外,当您在项目声明中省略生命周期(
[FooFunc; 4]
)时,可以推断为'static
。 (This is because types themselves can't outlive their type parameters, but the item must be 'static
, so the only valid lifetime parameter is also 'static
.) So funcs
is an array of references to closures which only accept &'static mut Foo<'static>
. (这是因为类型本身不能超过其类型参数,但是该项目必须为
'static
,因此唯一有效的生命周期参数也为'static
。)因此funcs
是对闭包的引用数组,这些闭包仅接受&'static mut Foo<'static>
。
What you probably want is type FooFunc<'r> = &'r for<'a, 'b> dyn Fn(&'a mut Foo<'b>) -> bool;
您可能想要的是
type FooFunc<'r> = &'r for<'a, 'b> dyn Fn(&'a mut Foo<'b>) -> bool;
, although this still fails due to mutability issues elsewhere. ,尽管由于其他地方的可变性问题,此操作仍然失败。 What that says is "A
FooFunc<'r>
is a reference of lifetime 'r
to a closure which accepts references of any lifetime to Foo
s with any lifetime (the latter lifetime implicitly outlives the first lifetime)." 什么,说是“A
FooFunc<'r>
是寿命的参考'r
到它接受任何寿命的引用的封闭Foo
与任何寿命(后者寿命隐式会超越第一寿命)秒。” 'r
will still be inferred as 'static
but that's okay because that's what you have. 'r
仍将被推断为'static
但这没关系,因为这就是您所拥有的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.