Возвращает данные, которые содержат данные, принадлежащие функции

#rust

#Ржавчина

Вопрос:

Я хочу иметь a DataAllocator , который может возвращать данные со временем жизни 'r , поэтому я могу передать их something и при этом иметь возможность возвращать значение, выделенное внутри something :

 use std::marker::PhantomData;

pub struct Data<'a, T>{
    a: amp;'a [T]
}

impl<'a, T> Data<'a, T> {
    pub fn new() -> Data<'a, T> {
        todo!()
    }
    
    fn iter(amp;'a self) -> Iter<'a, T> {
        todo!()
    }
}

pub struct Iter<'a, T> {
    _phantom: PhantomData<amp;'a T>
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = amp;'a T;
    fn next(amp;mut self) -> Option<Self::Item> {
        todo!()
    }
}

pub trait DataAllocator<'s, 'r, T> {
    fn allocate(amp;'s self) -> Box<dyn AsRef<[T]>   'r>;
}

impl<'s, 'r, T> DataAllocator<'s, 'r, T> for Data<'r, T> {
    fn allocate(amp;'s self) -> Box<dyn AsRef<[T]>   'r> {
        todo!()
    }
}

fn do_something<'a, 'b, T>(data_allocator: amp;'a dyn DataAllocator<'a, 'b, T>) -> Data<'b, T> {
    let buffer = data_allocator.allocate();
    let data = Data{a: (*buffer).as_ref()};
    for e in data.iter(){}
    data
}
 

https://play.rust-lang.org/?version=stableamp;mode=debugamp;edition=2021amp;gist=2a3e0d0cdea86238413af25dddd04e19

 error[E0515]: cannot return value referencing local data `*buffer`
  --> src/lib.rs:42:5
   |
40 |     let data = Data{a: (*buffer).as_ref()};
   |                        ------------------ `*buffer` is borrowed here
41 |     for e in data.iter(){}
42 |     data
   |     ^^^^ returns a value referencing data owned by the current function
 

Проблема в том, что если я пытаюсь выполнить итерацию data , то он жалуется, что я пытаюсь вернуть что-то, что заимствовано .iter() функцией. Я думаю, это может быть связано с тем, что я говорю, что .iter() это заимствует Data на время жизни 'b , то есть на весь срок службы выделенных данных. Что я могу сделать в этом случае?

Комментарии:

1. Если вы удалите итерацию, вы все равно получите точно такую же ошибку.

2. Если вам интересно возвращать только фрагменты или Vec s, возможно, стоит использовать Cow<'r, [T]> вместо Box<AsRef> ?

Ответ №1:

Я думаю, что путаница возникает .as_ref() при dyn AsRef<[T]> 'r возврате ссылки, привязанной к самой себе, а не к времени 'r жизни. Таким образом, ссылка, которую вы получаете (*buffer).as_ref() , является производной от buffer , что, конечно, выходит за рамки.

Трудно сказать, что вам следует с этим делать, поскольку todo!() неясно, как вы планировали это сделать. Но, основываясь на том, что я вижу, я бы, вероятно, ожидал allocate() , что они вернут a amp;'r [T] . Игровая площадка.

Комментарии:

1. теперь я понял. Проблема с вашим решением заключается в том, что оно позволяет мне возвращать только ссылки. Что, если я действительно хочу выделить что-то, что живет само по себе? Например, я мог бы использовать TypedArena для выделения истинного фрагмента, но я также мог бы захотеть использовать неэффективный распределитель, который просто выделил a Vec , который живет сам по себе. Вот почему я хотел Box , чтобы они содержали все, что реализует AsRef<[T]> , а не просто возвращали фрагмент. Как вы думаете, это возможно?

2. вкратце: я хочу вернуть поле чего-то, что реализует AsRef , но это что-то может быть срезом (короткое время жизни) или vec (статическое время жизни). Второй случай — когда мне нужно передавать данные в другие потоки и т. Д

3.Ну, вы можете реализовать свою собственную черту, похожую на AsRef like so. Но я чувствую, что это не поможет вашим намерениям, потому что даже если вы вернете принадлежащий Vec , он скрыт за этим объектом trait и все равно будет привязан к этому 'r времени жизни, как срез.

4. да, но время, когда мне нужно вернуть a Vec , — это время, когда материал компилируется 'r = 'static . Мне действительно не нужно, чтобы это было выбрано во время выполнения. Мне нравится внедрять свои собственные AsRef , но тогда они не будут работать автоматически там, где AsRef это необходимо, что довольно скучно: c

5. Я пытаюсь реализовать DataRef из вашего примера для Vec, но это выглядит невозможным без 'a in amp;self , но если я это сделаю, у меня будет много проблем с другими вещами