Это не полный ответ, потому что я не до конца понимаю источник ошибки, но, по сути, теперь я считаю, что компилятор загадочно говорил вам, что у него недостаточно информации для разрешения времени жизни.
Я считаю, что часто бывает полезно удалить все жизни и добавить их по частям только по мере необходимости, чтобы лучше понять, что происходит, поэтому давайте сделаем это.
Начало:
trait Foo {
fn foo(&self) -> RefHolder;
}
struct SomeType;
impl Foo for SomeType {
fn foo(&self) -> RefHolder {
RefHolder(self)
}
}
struct RefHolder(&(dyn Foo));
// ...etc
Очевидно, что RefHolder
нужен пожизненный параметр из-за содержания заимствования, поэтому добавление их в:
trait Foo {
fn foo(&self) -> RefHolder<'a>;
}
struct SomeType;
impl Foo for SomeType {
fn foo(&self) -> RefHolder<'a> {
RefHolder(self)
}
}
struct RefHolder<'a>(&'a (dyn Foo));
// ...etc
Теперь foo()
нуждается в нем. Обратите внимание, не Foo
, просто функция.
trait Foo {
fn foo<'a>(&self) -> RefHolder<'a>;
}
struct SomeType;
impl Foo for SomeType {
fn foo<'a>(&self) -> RefHolder<'a> {
RefHolder(self)
}
}
struct RefHolder<'a>(&'a (dyn Foo));
// ...etc
Теперь компилятор скажет нам гораздо более прямо, что он не может определить время жизни возвращаемого значения foo
в импл. Он скажет, что ему нужно прожить до 'a
(из-за подписи), а также до анонимного времени жизни &self
(потому что он возвращает self
). Но ничего не сказано о том, как эти жизни связаны друг с другом. Итак, мы говорим:
trait Foo {
fn foo<'a, 's: 'a>(&'s self) -> RefHolder<'a>;
}
struct SomeType;
impl Foo for SomeType {
fn foo<'a, 's: 'a>(&'s self) -> RefHolder<'a> {
RefHolder(self)
}
}
struct RefHolder<'a>(&'a (dyn Foo));
// ...etc
Теперь все счастливы. То, что мы сделали, сказали, что 's
должно быть не меньше, чем 'a
(в противном случае self
может быть уничтожено до того, как RefHolder
ссылается на него). Когда мы его называем, проверка чека заимствований имеет место, и с миром все в порядке.
Раньше вы начали добавлять время жизни к черте Foo
, что является проигрышной битвой, потому что вы в итоге окажетесь с бесконечным регрессом, так как RefHolder
внезапно нужно сказать, как долго его dyn Foo
захочет быть заимствованным, а это не то, что вы знаете заранее.
Все еще не совсем уверен, почему это добавляет вплоть до той ошибки, которую вы впервые увидели, но я рад, что хотя бы частично распутал это.