Как аннотировать реализацию черты, которая возвращает Self, имеет указанное время жизни? - PullRequest
0 голосов
/ 24 апреля 2020

заголовок, похоже, похож на Параметр Lifetime для `Self` в сигнатуре признака , но я создаю этот новый пост, потому что я считаю, что root причина отличается.

У меня есть признак например, следуйте

trait T<'a> {
    fn new(y: &'a Y) -> Self where Self: Sized;
    fn do_something(&self);
}

и хотите написать обобщенную функцию c, которая принимает тип X (которая реализует черту T <'a>) и ссылку на Y, затем создайте dyn Trait T <' a>.

fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> 

моя наивная реализация похожа на это

fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> {
    return Box::new(I::new(y)) as Box<dyn T<'a>>;
}

, тогда я получил эту ошибку.

error[E0310]: the parameter type `I` may not live long enough

но тип параметра I имеет ограничение T<'a> , Я не понимаю, почему это не говорит о том, что rustc to I::new(y) жив после шага выполнения go из этой функции.

Я подозреваю, что это происходит с помощью I:new() возвращает Self, который не имеет аннотации к жизни. но также я не могу найти способ дать аннотацию жизни для Self.

это полный пример, чтобы вызвать ошибку.

struct Y {
    z: i32
}

struct X<'a> {
    y: &'a Y
}

trait T<'a> {
    fn new(y: &'a Y) -> Self where Self: Sized;
    fn do_something(&self);
}

impl<'a> T<'a> for X<'a> {
    fn new(y: &'a Y) -> X<'a> {
        return X::<'a> {
            y: y
        }
    }
    fn do_something(&self) {
        println!("{}", self.y.z)
    }
}

fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> {
    // error: the parameter type `I` may not live long enough
    return Box::new(I::new(y)) as Box<dyn T<'a>>;
}

fn main() {
    let y = Y { z: 123 };
    {
        let t = create_t_from_i::<X>(&y);
        t.do_something()
    }
}

, если я удалю определение T :: new и давая X :: new для create_t_from_i в качестве указателя на функцию, код работает (нужно использовать T + 'a вместо T <' a>). но какое существенное отличие от 1-го примера?

struct Y {
    z: i32
}

struct X<'a> {
    y: &'a Y
}

trait T {
    fn do_something(&self);
}

impl<'a> X<'a> {
    fn new(y: &'a Y) -> X<'a> {
        return X::<'a> {
            y: y
        }
    }
}
impl<'a> T for X<'a> {
    fn do_something(&self) {
        println!("{}", self.y.z)
    }
}

fn create_t_from_i<'a, I: T + 'a>(ctor: fn (y: &'a Y) -> I, y: &'a Y) -> Box<dyn T + 'a> {
    // if passing constructor function directly and using annotation I: T + 'a, rustc does not complain. 
    let i = ctor(y);
    return Box::new(i) as Box<dyn T + 'a>;
}

fn main() {
    let y = Y { z: 123 };
    {
        let t = create_t_from_i::<X>(X::new, &y);
        t.do_something()
    }
}

У кого-нибудь есть идея, почему это происходит и как сделать "ржавчину c" счастливой?

С уважением.

Ответы [ 2 ]

2 голосов
/ 24 апреля 2020
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> 

неявно совпадает с

fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn 'static + T<'a>> 

, что, в свою очередь, означает, что I также должен иметь срок жизни c, чтобы иметь возможность сохранить его в возвращенном поле (т. Е. Вы необходимо ограничить I: 'static).

Чтобы решить эту проблему, вы можете добавить еще один параметр времени жизни для времени жизни I и использовать его в возвращаемой штучной упаковке. Это будет работать независимо от того, какое на самом деле время жизни I:

fn create_t_from_i<'a, 'b, I: 'b + T<'a>>(y: &'a Y) -> Box<dyn 'b + T<'a>> 
//                     ^^^^^^^^^                               ^^^^

Пример игровой площадки

0 голосов
/ 24 апреля 2020

Любой объект черты имеет аннотации времени жизни, которые неявно будут 'static. Ваша функция такова:

fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn 'static + T<'a>> 

Решение состоит в том, чтобы явно аннотировать время жизни вашего объекта черты:

fn create_t_from_i<'a, I: 'a + T<'a>>(y: &'a Y) -> Box<dyn 'a + T<'a>> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...