Hiho there,
I have a very confusing lifetime error problem in my current project that is probably a result of some wrong specifications of lifetimes in my methods.
fn foo<'a>(&'a self) -> ArrayView1<'a, f32> {
let l: &'a ContainerLayer = self.get_layers();
let o: BiasedSignalView<'a> = l.output_signal();
let a: ArrayView1<'a, f32> = o.data(); // ERROR: 'o' does not live long enough!
a
}
First let me explain foo
:
This is just an example implementation of the real code.
I splitted it up in let-statements to give you more insight in what I actually want to achive and with types it even may be easier to follow the code and its intentions.
Basically I just want to propagate the 'a
lifetime through different methods into the resulting ArrayView1<f32>
.
This somehow fails and I think this is because the method signatures communicate the propagation of the wrong lifetimes.
Answers to some FAQ:
What is ArrayView1
? Link
What is BiasedSignalView
? Link
BiasedSignalView
is just a thin wrapper around ArrayView1<f32>
and ArrayView1<f32>
can be understood as a thin wrapper around &[f32]
.
Both are basically more or less fancy &[f32]
slices.
What I want to solve:
With methods like data
(Link) I want to transform the borrowed/viewed area of the underlying data and return it with the lifetime associated to the borrowed data, not the lifetime of the pre-transformed object: And as far as I can imagine this is currently my problem.
What I think may be the problem:
So methods like output_signal
(Link) or unbias
do transform their view into their borrowed data but lifetimes of the returned structures are not explicitly bound to the borrowed data, just the pre-transformed object itself. So when doing ...
foo.output_signal().data()
The Rust compiler correctly reports a bug that the thing returned by output_signal
does not live long enough for data
to return something with a lifetime associated to the lifetime of foo
.
So finally, my question:
How can I change the signature of my functions so that they properly propagate their lifetimes?
Edit
Some of the function signatures used:
The data
method:
impl<D, B> BufferBase<D, B>
where D: ndarray::Data<Elem = f32>,
B: marker::Marker
{
fn data(&self) -> ArrayView1<f32> {
self.data.view()
}
}
The output_signal
trait and method:
trait HasOutputSignal
{
fn output_signal(&self) -> BiasedSignalView;
}
impl HasOutputSignal for ContainerLayer {
fn output_signal(&self) -> BiasedSignalView {
self.output_layer().output_signal() // Just forwards to other trait implementors
}
I hope this helps ... :S