Reputation: 952
I'm struggling to understand where I'm returning a reference to a local value in this function (full code: https://gist.github.com/9f88f9ded8f2f6a1f3b839422a521073):
fn encode_initial_configs<'a, TSym, NTSym>(
alpha: impl IntoIterator<Item = TSym> + 'a,
grammar: &'a OPGrammar<TSym, NTSym>,
chunk_size: usize,
) -> impl Iterator<Item = GPUParseConfig> + 'a
where
TSym: Eq + std::hash::Hash + Clone,
NTSym: Eq + Clone,
{
assert_ne!(chunk_size, 0, "`chunk_size` must be non-zero.");
let mut alpha_chunks = grammar
.encode_iterator(alpha)
.chunks(chunk_size)
.into_iter()
.map(|chunk| chunk.collect_vec())
.fuse();
let curr_chunk = alpha_chunks.next();
InitialConfigs {
alpha_chunks,
last_sym: 0,
curr_chunk,
}
}
The compiler complains about the value returned in the bottom:
error[E0515]: cannot return value referencing temporary value
--> src/par_parse.rs:77:5
|
70 | let mut alpha_chunks = grammar
| ____________________________-
71 | | .encode_iterator(alpha)
72 | | .chunks(chunk_size)
| |___________________________- temporary value created here
...
77 | / InitialConfigs {
78 | | alpha_chunks,
79 | | last_sym: 0,
80 | | curr_chunk,
81 | | }
| |_____^ returns a value referencing data owned by the current function
|
= help: use `.collect()` to allocate the iterator
For more information about this error, try `rustc --explain E0515`.
But the alpha_chunks
iterator returned as part of the InitialConfigs
instance is obtained by moving every intermediate iterator into the next one. Where is this reference?
EDIT: encode_iterator
might be relevant:
pub fn encode_iterator<'a>(
&'a self,
s: impl IntoIterator<Item = TSym> + 'a,
) -> impl Iterator<Item = u32> + 'a {
s.into_iter().map(|sym| self.encode_term(sym))
}
Upvotes: 0
Views: 106
Reputation: 952
The culprit seems to be .into_iter()
, which instead of consuming the result of .chunks(chunk_size)
, borrows it. In fact, reading the itertools code, IntoIterator
is impl
'd for &'a IntoChunks<I>
, which is the type of the result of chunks
. Furthermore, the borrowed reference to IntoChunks
is stored in the returned Chunks
struct, which is then stored into the iterator returned by map
, and so on. A possible solution could be finding or implementing a chunk iterator that can be moved directly into map
and does not hold references to local values.
Upvotes: 1
Reputation: 715
Short answer: You are returning reference to alpha chunk
Let's look at this statement:
let mut alpha_chunks = grammar
.encode_iterator(alpha)
.chunks(chunk_size)
.into_iter()
.map(|chunk| chunk.collect_vec())
.fuse();
Here are the diffusion of statement:
grammer
refer to the variable passed into the function itselfendoe_iterator()
returns an iterator which which yields the item that is passed as argument. But note that iterator is local in itself, it just yields value that is not localchunks()
, into_iterator()
, map()
, fuse()
all this just manipulate the iterator and keep re-making new iterators typealpha_chunks
variable which is also localSo you realize that iterators are lazy i.e they don't compute anything unless called with come methods that actually make them to like collect()
method. But in you case you never "collected" anything from iterator and the function just return the iterator itself which is local
Upvotes: 0