Hi!
I have a problem where I want to consume a value after an action, but the code only compiles when I take a reference. In my use case, it does not make sense to use a value more than once. I want to avoid users accidentally using the same value twice by taking ownership instead of borrowing. Alas, I don't know how to correctly declare the lifetime such that the ownership can be taken.
Here is a rather involved example, which is a simplification of the real code.
Here is a human description:
- Some data exists that should be analysed
- A temporary analyser is created to store temporary data while performing the analysis (it must borrow from the data to analyse it)
- The temporary borrowing analyser produces an independent
'static
value - The temporary analyser cannot be dropped, even though the returned value is
'static
? Why? How can I declare the correct lifetime?
// a piece of data which can be analysed
trait CreateBorrowingAnalyser<'s> {
type Analyser: Analyser;
fn create_borrowing_analyser(&'s self) -> Self::Analyser;
}
// stores temporary data used to analyse some data
trait Analyser {
type Analysis: 'static; // independent value without any references
fn analyse(self) -> Self::Analysis; // should consume the analyser and destroy any references to the data
}
fn analyse
<'b, B: 'b + CreateBorrowingAnalyser<'b>>
(analysable: /* &'b */ B) // FIXME my use case requires to consume this value by taking ownership instead of borrowing here
-> <<B as CreateBorrowingAnalyser<'b>>::Analyser as Analyser>::Analysis
{
let temporary_borrowing_analyser = analysable.create_borrowing_analyser();
let independent_result = temporary_borrowing_analyser.analyse();
independent_result
}
fn main(){
struct AnalyseAverage<'s> {
slice: &'s [usize]
}
impl<'s> CreateBorrowingAnalyser<'s> for Vec<usize> {
type Analyser = AnalyseAverage<'s>;
fn create_borrowing_analyser(&'s self) -> Self::Analyser {
AnalyseAverage { slice: self.as_slice() }
}
}
impl<'s> Analyser for AnalyseAverage<'s> {
type Analysis = usize; // independent value without any references
fn analyse(self) -> Self::Analysis {
self.slice.iter().sum::<usize>() / self.slice.len()
}
}
let data: Vec<usize> = vec![0, 1, 2, 3, 4];
let average = analyse(/* & */data);
assert_eq!(average, 2);
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0597]: `analysable` does not live long enough
--> src/main.rs:20:40
|
16 | <'b, B: 'b + CreateBorrowingAnalyser<'b>>
| -- lifetime `'b` defined here
...
20 | let temporary_borrowing_analyser = analysable.create_borrowing_analyser();
| ^^^^^^^^^^----------------------------
| |
| borrowed value does not live long enough
| argument requires that `analysable` is borrowed for `'b`
...
23 | }
| - `analysable` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
Have you got some advice or hints that I could try?