我很难解决终身问题:
pub struct A<'a> {
pub a: &'a str,
pub b: &'a u8,
}
pub enum Executable<'a> {
ExecutableA(A<'a>),
}
pub struct Config {
pub a: String,
pub b: u8, // some more config values to follow
}
impl Config {
pub fn new() -> Config {
// Implementation details omitted due to irrelevancy
unimplemented!();
}
}
pub struct Cli<'a> {
pub config: Config,
pub execution_list: Vec<Executable<'a>>,
}
impl<'a> Cli<'a> {
pub fn new() -> Cli<'a> {
Cli {
config: Config::new(),
execution_list: vec![],
}
}
pub fn prepare(&mut self) {
self.execution_list.push(
// Compilation error occurs for following line
Executable::ExecutableA(A {
a: &self.config.a,
b: &self.config.b,
}),
)
}
}
编译错误为:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/lib.rs:39:20
|
39 | a: &self.config.a,
| ^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 35:20...
--> src/lib.rs:35:20
|
35 | pub fn prepare(&mut self) {
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:39:20
|
39 | a: &self.config.a,
| ^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 27:6...
--> src/lib.rs:27:6
|
27 | impl<'a> Cli<'a> {
| ^^
note: ...so that the expression is assignable
--> src/lib.rs:38:13
|
38 | / Executable::ExecutableA(A {
39 | | a: &self.config.a,
40 | | b: &self.config.b,
41 | | }),
| |______________^
= note: expected `Executable<'a>`
found `Executable<'_>`
(游乐场)
在做了大量的阅读和查看其他问题之后,我仍然无法说服自己正确理解了错误,主要是因为我无法解释为什么编译器将"匿名"生存期附加到prepare
函数中的&mut self
引用。
我的总体设计思想是,我将让我的Cli
结构包含一个配置和一个可执行文件列表,以便我可以将所有相关的可执行文件添加到Cli
的prepare
函数中的该列表中(我希望这些可执行文件能够引用Config
拥有的值)。然后,我将遍历该执行列表以启动/停止可执行文件。
我认为这个问题的一个答案是不要让可执行文件维护对配置值的引用,而是复制这些值,但我觉得这不应该是必要的,并希望将这个问题用作学习机会。
我完全愿意接受"也许你应该重新考虑你的设计并做X"的建议。
匿名生存期由编译器推断,其中大多数会指向'static
,
如果添加此 (&'a mut self
):
pub fn prepare (&'a mut self) /* ... */
它的编译效果很好,因为impl
生存期要求与Executable
生存期要求并不冲突。
编辑:
正如所指出的,我错了(可能是因为 rust 风格确实进入了我的脑海,但 Lifetimes 没有),我虽然是关于通用生命周期的,但我查看了已经存在的生命周期'a
,发现它编译了,至少可变借用类为永恒是有意义的。
关于您的设计:
我发现它对你想做的事情有好处,而且我也不是设计专家,尤其是在rust 方面,所以我没有发现任何错误。
可行的解决方案:
如前所述,您可以添加通用生命周期:
pub fn prepare <'b> (&'b mut self) { ... }
现在,每当调用该函数时,可变借用都将持续所需的生命周期,当您想要不可变借用它时,它将起作用。