Я начинаю с корня Fmt
и рекурсивно спускаюсь (вдоль Vec<String>
) в Fmt
s, создаваемый вызовом get_subfmt
.Когда вектор пуст, я вызываю метод (для краткости здесь не показан).Каждый предшествующий 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>
на get_subfmt
в impl
, так как это не соответствует сигнатуре метода.Я пытался ограничить T
значением T: Borrow<dyn Fmt + 'b> + 'b
, но это не помогает, ошибки остаются.
Я мог бы переместить 'a
из метода к самому Fmt
, но это нене кажется правильным, поэтому я хотел бы избежать этого, если есть способ.