我最近偶然发现了一个我无法解决的终身强制问题。我认为源于同一问题的最小可重现示例如下:
const MACGUFFIN: i32 = 0;
trait GiveReference<'a> {
type Target;
fn give_reference(&'a self) -> &'a Self::Target;
}
struct Foo<'a>(&'a i32);
impl<'a> GiveReference<'a> for Foo<'a> {
type Target = i32;
fn give_reference(&'a self) -> &'a i32 {
&self.0
}
}
struct Bar<T, Target>(T, Target);
impl<'a, T: 'a> Bar<T, T::Target>
where
T: GiveReference<'a> + 'a,
T::Target: Copy,
{
pub fn new(foo: T) -> Self {
let val: <T as GiveReference>::Target = *foo.give_reference();
Self(foo, val)
}
}
fn main() {
let foo = Foo(&MACGUFFIN);
Bar::new(foo);
}
从根本上来说,我想要实现的是创建一个容器类型(类似于readguard)
Foo
,它存储可能超过其自身生命周期的数据,并且可以在不超过其生命周期的任何生命周期内返回对该数据的引用。我假设特征GiveReference
及其在Foo
上的实现满足这些条件(请告诉我这个假设是否错误)。
接下来,我尝试创建一个辅助容器类型,它以
Bar
的形式存储容器/读防护的初始值。在其 impl
where 子句中,我尝试向编译器明确表示,它应该仅针对不会比其数据寿命更长的 GiveReference
类型实现。然而这条线:
let val: <T as GiveReference>::Target = *foo.give_reference();
抱怨
foo
需要借用'a
。据我所知,我希望 foo.give_reference
能够借用 foo
直到复制函数结束,而不是将生命周期 'a
强加到借用上。有人可以向我解释一下我的思维模式在哪里崩溃了吗?如果有的话,可以做出哪些改变来解决这个问题。
我已经尝试阅读更多有关 Rust 中的生命周期强制的内容,但即使如此,我仍然认为我尝试使用的一般模式没有任何问题。
&'a self
不正确。这将迫使 self
具有相同生命周期作为其 <'a>
生命周期参数。
删除它可以修复错误:
const MACGUFFIN: i32 = 0;
trait GiveReference<'a> {
type Target;
fn give_reference(&self) -> &'a Self::Target;
}
struct Foo<'a>(&'a i32);
impl<'a> GiveReference<'a> for Foo<'a> {
type Target = i32;
fn give_reference(&self) -> &'a i32 {
&self.0
}
}
struct Bar<T, Target>(T, Target);
impl<'a, T: 'a> Bar<T, T::Target>
where
T: GiveReference<'a> + 'a,
T::Target: Copy,
{
pub fn new(foo: T) -> Self {
let val: <T as GiveReference>::Target = *foo.give_reference();
Self(foo, val)
}
}
fn main() {
let foo = Foo(&MACGUFFIN);
Bar::new(foo);
}