Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning data which contains data owned by function

Tags:

I want to have a DataAllocator that can return data with lifetime 'r, so I can pass it to something and still be able to return the value allocated inside something:

use std::marker::PhantomData;

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

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

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

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

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

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

fn do_something<'a, 'b, T>(data_allocator: &'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=stable&mode=debug&edition=2021&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

The problem is that if I try to iterate over data, then it complains that I'm trying to return something that is borrowed by the .iter() function. I think it might have to do with me saying that .iter() borrows the Data for the lifetime 'b, which is the entire lifetime of the allocated data. What can I do in this case?

like image 746
Rafaelo Avatar asked Dec 09 '21 15:12

Rafaelo


1 Answers

I think the confusion is getting .as_ref() on a dyn AsRef<[T]> + 'r returns a reference tied to itself, not to the 'r lifetime. So the reference you get from (*buffer).as_ref() is derived from buffer, which of course goes out of scope.

Its hard to say what you should do about it though, since the todo!()s obscure how you were planning to accomplish this. But based on what I see, I would probably expect the allocate() to return a &'r [T]. Playground.

like image 129
kmdreko Avatar answered Sep 30 '22 16:09

kmdreko