简体   繁体   English

闭包的常量数组,在Rust中使用寿命参数对结构进行可变引用

[英]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 lifetimethe 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的引用(对具有相同特定生存期'aFoo的引用), 每个所谓的关闭时间 。”

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM