For the context: I am implementing a solution for Tom's Data Onion.
In my main
function I was trying to iterate over my solutions for various layers of the task using fold
to finally get the final answer in the end. Following is the code.
use std::string::FromUtf8Error;
use toms_data_onion::a85::decode;
use toms_data_onion::{find_payload, layer0, layer1, layer2, layer3, layer4, layer5, layer6};
fn main() {
let layer0 = include_str!("start.txt").to_string();
let core = unveilers()
.into_iter()
.copied()
.enumerate()
.fold(layer0, |layer, (idx, unveil)| {
let payload = find_payload(&layer)
.expect(&format!("payload not found in layer {idx}"))
.as_bytes()
.into_iter()
.copied();
let decoded = decode(payload);
unveil(decoded).expect(&format!("invalid UTF-8 in layer {idx}"))
});
println!("{core}");
}
fn unveilers<T: Iterator<Item = u8>>() -> &'static [fn(T) -> Result<String, FromUtf8Error>] {
&[
layer0::unveil,
layer1::unveil,
layer2::unveil,
layer3::unveil,
layer4::unveil,
layer5::unveil,
layer6::unveil,
]
}
However, borrow checker is not happy with this code:
error[E0597]: `layer` does not live long enough
--> src/main.rs:12:40
|
11 | .fold(layer0, |layer, (idx, unveil)| {
| ----- ------------- lifetime `'1` appears in the type (usize, fn(impl Iterator<Item = u8>) -> Result<String, FromUtf8Error>)
| |
| binding `layer` declared here
12 | let payload = find_payload(&layer)
| ^^^^^^ borrowed value does not live long enough
...
17 | let decoded = decode(payload);
| --------------- argument requires that `layer` is borrowed for `'1`
18 | unveil(decoded).expect(&format!("invalid UTF-8 in layer {idx}"))
19 | });
| - `layer` dropped here while still borrowed
find_payload
is
pub fn find_payload(s: &str) -> Option<&str> {
Some(&s[s.find("<~")? + 2..s.find("~>")?])
}
And decode
is a function declared as pub fn decode<I: IntoIterator<Item = u8>>(it: I) -> impl Iterator<Item = u8>
Could you please help me understand this error?
layer
is passed into the closure has a String
type. find_payload
borrows it, and this returned payload
is bound to its lifetime. I am not sure why here the borrow checker concludes that borrowed value does not live long enough
. But also later, I understand that since further I mainly operate with iterators, those too capture the lifetime of the object they iterate over. So decoded
should also have an implicit lifetime bound to its type. However, unveil
has a type fn(impl Iterator<Item = u8>) -> Result<String, FromUtf8Error>
, and there is no need for its returned value to have any lifetime limitation. But the compiler seems to be unhappy by the layer
being dropped at the end of the closure. But conceptually, there is no need for it to live any longer.
I might be missing something obvious, but please help me express my intention to the compiler in a way that makes sense to it.
Thank you!