如何指定 impl 的生命周期应该与 'self' 的生命周期相同?
How to specify that a lifetime from an impl should be the same as the lifetime of 'self'?
我从根 Fmt
开始递归(沿着 Vec<String>
)进入 get_subfmt
调用产生的 Fmt
。当向量为空时,我调用一个方法(为简洁起见,此处未显示)。每个前面的 Fmt
(和它的 BoxOrRef
)自然地比下面的一个具有更长的生命周期,由递归函数的范围强制执行。这看起来很安全,但我对生命周期业务还很陌生,所以我的推理可能有误。
考虑以下简化代码:
use std::borrow::Borrow;
pub trait Fmt {
fn get_subfmt<'a>(&'a self, name: &str) -> Option<BoxOrRef<'a, dyn Fmt>>;
}
pub enum BoxOrRef<'a, T: ?Sized + 'a> {
Boxed(Box<T>),
Ref(&'a T)
}
impl<'b, T: Borrow<dyn Fmt + 'b>> Fmt for T {
fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
self.borrow().get_subfmt(name)
}
}
失败并出现以下错误:
error[E0308]: method not compatible with trait
--> src/lib.rs:13:5
|
13 | fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `fn(&'a T, &str) -> std::option::Option<BoxOrRef<'a, Fmt + 'a>>`
found type `fn(&'b T, &str) -> std::option::Option<BoxOrRef<'b, Fmt + 'b>>`
note: the lifetime 'a as defined on the method body at 13:5...
--> src/lib.rs:13:5
|
13 | fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 12:1
--> src/lib.rs:12:1
|
12 | impl<'b, T: Borrow<dyn Fmt + 'b>> Fmt for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: method not compatible with trait
--> src/lib.rs:13:5
|
13 | fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `fn(&'a T, &str) -> std::option::Option<BoxOrRef<'a, Fmt + 'a>>`
found type `fn(&'b T, &str) -> std::option::Option<BoxOrRef<'b, Fmt + 'b>>`
note: the lifetime 'b as defined on the impl at 12:1...
--> src/lib.rs:12:1
|
12 | impl<'b, T: Borrow<dyn Fmt + 'b>> Fmt for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime 'a as defined on the method body at 13:5
--> src/lib.rs:13:5
|
13 | fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
编译器似乎无法证明 get_subfmt
定义中的 'a
与 impl
中的 'b
相同,很可能是因为我没有告诉它它是。如何与编译器沟通我希望 self
引用精确到最后 'b
?我不能在 impl
中的 get_subfmt
上添加 <'a: 'b>
,因为它与方法签名不匹配。我已经尝试将 T
限制为 T: Borrow<dyn Fmt + 'b> + 'b
,但这没有帮助,错误仍然存在。
我可以将 'a
从方法移动到 Fmt
本身,但它看起来并不正确,所以如果有办法的话我想避免它。
这是我能想到的最好的:
use std::borrow::Borrow;
pub trait Fmt<'b> {
fn get_subfmt<'a>(&'a self, name: &str) -> Option<BoxOrRef<'a, dyn Fmt + 'a>>
where
'b: 'a;
}
pub enum BoxOrRef<'a, T: ?Sized + 'a> {
Boxed(Box<T>),
Ref(&'a T)
}
impl<'b, T: Borrow<dyn Fmt<'b> + 'b>> Fmt<'b> for T {
fn get_subfmt<'a>(&'a self, name: &str) -> Option<BoxOrRef<'a, dyn Fmt + 'a>>
where
'b: 'a,
{
self.borrow().get_subfmt(name)
}
}
我们想要绑定 'b: 'a
('b
比 'a
长),而不是 'a: 'b
,因为借用的引用不能比它的引用长。
我从根 Fmt
开始递归(沿着 Vec<String>
)进入 get_subfmt
调用产生的 Fmt
。当向量为空时,我调用一个方法(为简洁起见,此处未显示)。每个前面的 Fmt
(和它的 BoxOrRef
)自然地比下面的一个具有更长的生命周期,由递归函数的范围强制执行。这看起来很安全,但我对生命周期业务还很陌生,所以我的推理可能有误。
考虑以下简化代码:
use std::borrow::Borrow;
pub trait Fmt {
fn get_subfmt<'a>(&'a self, name: &str) -> Option<BoxOrRef<'a, dyn Fmt>>;
}
pub enum BoxOrRef<'a, T: ?Sized + 'a> {
Boxed(Box<T>),
Ref(&'a T)
}
impl<'b, T: Borrow<dyn Fmt + 'b>> Fmt for T {
fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
self.borrow().get_subfmt(name)
}
}
失败并出现以下错误:
error[E0308]: method not compatible with trait
--> src/lib.rs:13:5
|
13 | fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `fn(&'a T, &str) -> std::option::Option<BoxOrRef<'a, Fmt + 'a>>`
found type `fn(&'b T, &str) -> std::option::Option<BoxOrRef<'b, Fmt + 'b>>`
note: the lifetime 'a as defined on the method body at 13:5...
--> src/lib.rs:13:5
|
13 | fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 12:1
--> src/lib.rs:12:1
|
12 | impl<'b, T: Borrow<dyn Fmt + 'b>> Fmt for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0308]: method not compatible with trait
--> src/lib.rs:13:5
|
13 | fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `fn(&'a T, &str) -> std::option::Option<BoxOrRef<'a, Fmt + 'a>>`
found type `fn(&'b T, &str) -> std::option::Option<BoxOrRef<'b, Fmt + 'b>>`
note: the lifetime 'b as defined on the impl at 12:1...
--> src/lib.rs:12:1
|
12 | impl<'b, T: Borrow<dyn Fmt + 'b>> Fmt for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime 'a as defined on the method body at 13:5
--> src/lib.rs:13:5
|
13 | fn get_subfmt(&'b self, name: &str) -> Option<BoxOrRef<'b, dyn Fmt>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
编译器似乎无法证明 get_subfmt
定义中的 'a
与 impl
中的 'b
相同,很可能是因为我没有告诉它它是。如何与编译器沟通我希望 self
引用精确到最后 'b
?我不能在 impl
中的 get_subfmt
上添加 <'a: 'b>
,因为它与方法签名不匹配。我已经尝试将 T
限制为 T: Borrow<dyn Fmt + 'b> + 'b
,但这没有帮助,错误仍然存在。
我可以将 'a
从方法移动到 Fmt
本身,但它看起来并不正确,所以如果有办法的话我想避免它。
这是我能想到的最好的:
use std::borrow::Borrow;
pub trait Fmt<'b> {
fn get_subfmt<'a>(&'a self, name: &str) -> Option<BoxOrRef<'a, dyn Fmt + 'a>>
where
'b: 'a;
}
pub enum BoxOrRef<'a, T: ?Sized + 'a> {
Boxed(Box<T>),
Ref(&'a T)
}
impl<'b, T: Borrow<dyn Fmt<'b> + 'b>> Fmt<'b> for T {
fn get_subfmt<'a>(&'a self, name: &str) -> Option<BoxOrRef<'a, dyn Fmt + 'a>>
where
'b: 'a,
{
self.borrow().get_subfmt(name)
}
}
我们想要绑定 'b: 'a
('b
比 'a
长),而不是 'a: 'b
,因为借用的引用不能比它的引用长。