我从根Fmt
开始,然后递归下降(沿着Vec<String>
)到Fmt
调用产生的get_subfmt
s中。当向量为空时,我调用一个方法(为简便起见,此处未显示)。与递归函数的作用域相比,前一个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>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
似乎编译器无法证明'a
定义中的get_subfmt
与'b
中的impl
相同,这很可能是因为我没有没告诉过它。如何与希望self
引用精确地'b
的编译器通信?我无法在<'a: 'b>
的{{1}}上打get_subfmt
,因为这与方法签名不匹配。我尝试将impl
约束为T
,但这无济于事,错误仍然存在。
我可以将T: Borrow<dyn Fmt + 'b> + 'b
从方法移到'a
本身,但这似乎并不正确,因此,如果可以的话,我想避免这样做。
答案 0 :(得分:1)
这是我能想到的最好的方法
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
,因为借用的引用不能超过其引用的寿命。