#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
}
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
для выделения истинного фрагмента, но я также мог бы захотеть использовать неэффективный распределитель, который просто выделил aVec
, который живет сам по себе. Вот почему я хотелBox
, чтобы они содержали все, что реализуетAsRef<[T]>
, а не просто возвращали фрагмент. Как вы думаете, это возможно?2. вкратце: я хочу вернуть поле чего-то, что реализует
AsRef
, но это что-то может быть срезом (короткое время жизни) или vec (статическое время жизни). Второй случай — когда мне нужно передавать данные в другие потоки и т. Д3.Ну, вы можете реализовать свою собственную черту, похожую на
AsRef
like so. Но я чувствую, что это не поможет вашим намерениям, потому что даже если вы вернете принадлежащийVec
, он скрыт за этим объектом trait и все равно будет привязан к этому'r
времени жизни, как срез.4. да, но время, когда мне нужно вернуть a
Vec
, — это время, когда материал компилируется'r = 'static
. Мне действительно не нужно, чтобы это было выбрано во время выполнения. Мне нравится внедрять свои собственныеAsRef
, но тогда они не будут работать автоматически там, гдеAsRef
это необходимо, что довольно скучно: c5. Я пытаюсь реализовать
DataRef
из вашего примера для Vec, но это выглядит невозможным без'a
inamp;self
, но если я это сделаю, у меня будет много проблем с другими вещами