I wrote the following code that filters a stream of data which worked fine until I changed from parsing simple numbers to also have types that are bound to lifetimes like &str and &[u8].
use wirefilter::{ExecutionContext, Filter, Scheme};
lazy_static::lazy_static! {
static ref SCHEME: Scheme = Scheme! {
port: Int,
name: Bytes,
};
}
#[derive(Debug)]
struct MyStruct {
port: i32,
name: String,
}
impl MyStruct {
fn scheme() -> &'static Scheme {
&SCHEME
}
fn filter_matches<'s>(&self, filter: &Filter<'s>) -> bool {
let mut ctx = ExecutionContext::new(Self::scheme());
ctx.set_field_value("port", self.port).unwrap();
ctx.set_field_value("name", self.name.as_str()).unwrap();
filter.execute(&ctx).unwrap()
}
}
fn main() -> Result<(), failure::Error> {
let data = expensive_data_iterator();
let scheme = MyStruct::scheme();
let filter = scheme
.parse("port in {2 5} && name matches \"http.*\"")?
.compile();
for my_struct in data
.filter(|my_struct| my_struct.filter_matches(&filter))
.take(2)
{
println!("{:?}", my_struct);
}
Ok(())
}
fn expensive_data_iterator() -> impl Iterator<Item = MyStruct> {
(0..).map(|port| MyStruct {
port,
name: format!("http {}", port % 2),
})
}
If I try to compile it the compiler will fail with this:
error[E0623]: lifetime mismatch
--> src/main.rs:26:16
|
21 | fn filter_matches<'s>(&self, filter: &Filter<'s>) -> bool {
| ----- ----------
| |
| these two types are declared with different lifetimes...
...
26 | filter.execute(&ctx).unwrap()
| ^^^^^^^ ...but data from `self` flows into `filter` here
error: aborting due to previous error
error: Could not compile `wirefilter_playground`.
To learn more, run the command again with --verbose.
Process finished with exit code 101
my first thought was that self and filter should have the same lifetime in fn filter_matches<'s>(&self, filter: &Filter<'s>) -> bool but if I change the signature to fn filter_matches<'s>(&'s self, filter: &Filter<'s>) -> bool I will start getting this error:
error: borrowed data cannot be stored outside of its closure
--> src/main.rs:38:29
|
33 | let filter = scheme
| ------ ...so that variable is valid at time of its declaration
...
38 | .filter(|my_struct| my_struct.filter_matches(&filter))
| ----------- ^^^^^^^^^ -------------- cannot infer an appropriate lifetime...
| | |
| | cannot be stored outside of its closure
| borrowed data cannot outlive this closure
error: aborting due to previous error
error: Could not compile `wirefilter_playground`.
To learn more, run the command again with --verbose.
Process finished with exit code 101
I am failing to understand the reason, Filter<'s> is bound to SCHEME which is lazily generated and is bound to 'static which makes sense not allowing filter.execute to take reference to &self.name.as_str() because it would be outlived but, isn't filter.execute(&ctx) which the signature is pub fn execute(&self, ctx: &ExecutionContext<'s>) -> Result<bool, SchemeMismatchError> supposed to drop the references as soon as it finishes as the result of it has not other lifetimes?
In order to try and compile the code above, you can use this Cargo.toml:
[package]
name = "wirefilter_playground"
version = "0.1.0"
edition = "2018"
[dependencies]
wirefilter-engine = "0.6.1"
failure = "0.1.5"
lazy_static = "1.3.0"
PS: That could be solved by compiling the as inside filter_matches method but that would be sort of bad because the user would only get the parse error when trying to filter and it could potentially be slower.
I see 2 ways to solve this problem:
1) extend lifetime of self.name. This can be achieved by collecting expensive_data_iterator into, say, Vec.
--- let data = expensive_data_iterator();
+++ let data: Vec<_> = expensive_data_iterator().collect();
2) reduce lifetime of filter.
--- let filter = scheme.parse("...")?.compile();
+++ let filter = scheme.parse("...")?;
--- .filter(|my_struct| my_struct.filter_matches(&filter))
+++ .filter(|my_struct| my_struct.filter_matches(&filter.clone().compile()))
I omitted some other minor changes. And yes, filter_matches<'s>(&'s self, ...) is mandatory in either case.
PS yes, 2nd option works because my_struct outlives filter. Well, if both approaches are somewhat bad, then you can combine them! Process data by chunks, collecting each one into vector.
const N: usize = 10; // or any other size
loop {
let cur_chunk: Vec<_> = data.by_ref().take(N).collect();
if cur_chunk.is_empty() {
break;
}
let cur_filter = filter.clone().compile();
// etc
}
it uses only O(N) memory and compiles filter N times less
Related
I would like to return binary data in chunks of specific size. Here is a minimal example.
I made a wrapper struct for hyper::Response to hold my data like status, status text, headers and the resource to return:
pub struct Response<'a> {
pub resource: Option<&'a Resource>
}
This struct has a build method that creates the hyper::Response:
impl<'a> Response<'a> {
pub fn build(&mut self) -> Result<hyper::Response<hyper::Body>, hyper::http::Error> {
let mut response = hyper::Response::builder();
match self.resource {
Some(r) => {
let chunks = r.data
.chunks(100)
.map(Result::<_, std::convert::Infallible>::Ok);
response.body(hyper::Body::wrap_stream(stream::iter(chunks)))
},
None => response.body(hyper::Body::from("")),
}
}
}
There is also another struct holding the database content:
pub struct Resource {
pub data: Vec<u8>
}
Everything works until I try to create a chunked response. The Rust compiler gives me the following error:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:14:15
|
14 | match self.resource {
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 11:6...
--> src/main.rs:11:6
|
11 | impl<'a> Response<'a> {
| ^^
note: ...so that the types are compatible
--> src/main.rs:14:15
|
14 | match self.resource {
| ^^^^^^^^^^^^^
= note: expected `Option<&Resource>`
found `Option<&'a Resource>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
--> src/main.rs:19:31
|
19 | response.body(hyper::Body::wrap_stream(stream::iter(chunks)))
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `From<&[u8]>`
found `From<&'static [u8]>`
I don't know how to fulfill these lifetime requirements. How can I do this correctly?
The problem is not in the 'a itself, but in the fact that the std::slice::chunks() function returns an iterator that borrows the original slice. You are trying to create a stream future from this Chunks<'_, u8> value, but the stream requires it to be 'static. Even if your Resource did not have the 'a lifetime, you would still have the r.data borrowed, and it would still fail.
Remember that here 'static does not mean that the value lives forever, but that it can be made to live as long as necessary. That is, the future must not hold any (non-'static) borrows.
You could clone all the data, but if it is very big, it can be costly. If so, you could try using Bytes, that is just like Vec<u8> but reference counted.
It looks like there is no Bytes::chunks() function that returns an iterator of Bytes. Fortunately it is easy to do it by hand.
Lastly, remember that iterators in Rust are lazy, so they keep the original data borrowed, even if it is a Bytes. So we need to collect them into a Vec to actually own the data (playground):
pub struct Resource {
pub data: Bytes,
}
impl<'a> Response<'a> {
pub fn build(&mut self) -> Result<hyper::Response<hyper::Body>, hyper::http::Error> {
let mut response = hyper::Response::builder();
match self.resource {
Some(r) => {
let len = r.data.len();
let chunks = (0..len)
.step_by(100)
.map(|x| {
let range = x..len.min(x + 100);
Ok(r.data.slice(range))
})
.collect::<Vec<Result<Bytes, std::convert::Infallible>>>();
response.body(hyper::Body::wrap_stream(stream::iter(chunks)))
}
None => response.body(hyper::Body::from("")),
}
}
}
UPDATE: We can avoid the call to collect() if we notice that stream::iter() takes ownership of an IntoIterator that can be evaluated lazily, as long as we make it 'static. It can be done if we do a (cheap) clone of r.data and move it into the lambda (playground):
let data = r.data.clone();
let len = data.len();
let chunks = (0..len).step_by(100)
.map(move |x| {
let range = x .. len.min(x + 100);
Result::<_, std::convert::Infallible>::Ok(data.slice(range))
});
response.body(hyper::Body::wrap_stream(stream::iter(chunks)))
I am trying to write a packet parser, where basically one builds up a packet by parsing each Layer in the packet. The packet then holds those 'layers' in a vector.
The ~pseudo code~ code with compilation errors is something like the following -
Also added comments below - for each step. I have experimented with RefCell , but could not get that working. Essentially the challenges are enumerated at the end of the code.
The basic pattern is as follows - Get the object of a Layer type (Every Layer type will return a default next object based upon some field in the current layer as a 'boxed trait object'.)
Edit: I am adding a code that's more than a pseudo code - Also added following compilation errors. May be a way to figure out how to fix these errors could solve the problems.!
#[derive(Debug, Default)]
pub struct Packet<'a> {
data: Option<&'a [u8]>,
meta: PacketMetadata,
layers: Vec<Box<dyn Layer<'a>>>,
}
pub trait Layer<'a>: Debug {
fn from_u8<'b>(&mut self, bytes: &'b [u8]) -> Result<(Option<Box<dyn Layer>>, usize), Error>;
}
#[derive(Debug, Default)]
pub struct PacketMetadata {
timestamp: Timestamp,
inface: i8,
len: u16,
caplen: u16,
}
impl<'a> Packet<'a> {
fn from_u8(bytes: &'a [u8], _encap: EncapType) -> Result<Self, Error> {
let mut p = Packet::default();
let eth = ethernet::Ethernet::default();
let mut layer: RefCell<Box<dyn Layer>> = RefCell::new(Box::new(eth));
let mut res: (Option<Box<dyn Layer>>, usize);
let mut start = 0;
loop {
let mut decode_layer = layer.borrow_mut();
// process it
res = decode_layer.from_u8(&bytes[start..])?;
if res.0.is_none() {
break;
}
// if the layer exists, get it in a layer.
let boxed = layer.replace(res.0.unwrap());
start = res.1;
// append the layer to layers.
p.layers.push(boxed);
}
Ok(p)
}
}
Compilation Errors
error[E0515]: cannot return value referencing local variable `decode_layer`
--> src/lib.rs:81:9
|
68 | res = decode_layer.from_u8(&bytes[start..])?;
| ------------ `decode_layer` is borrowed here
...
81 | Ok(p)
| ^^^^^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `layer`
--> src/lib.rs:81:9
|
65 | let mut decode_layer = layer.borrow_mut();
| ----- `layer` is borrowed here
...
81 | Ok(p)
| ^^^^^ returns a value referencing data owned by the current function
error: aborting due to 2 previous errors; 3 warnings emitted
It's not clear why the above errors come. I am using the values returned by the calls. (The 3: warnings shown above can be ignored, they are unused warnings.)
The challenges -
p.layers.last_mut and p.layers.push are simultaneous mutable borrows - not allowed. I could somehow put it behind a RefCell, but how that's not clear.
This code is similar in pattern to syn::token::Tokens, however one basic difference being, there an Enum is used(TokenTree). In the above example I cannot use Enum because the list of protocols to be supported is potentially unbounded.
I cannot use Layer trait without Trait Objects due to the loop construct.
The pattern can be thought of as - mutably iterating over a container of Trait objects while updating the container itself.
Perhaps I am missing something very basic.
The problem with the above code is due to lifetime annotation on the Layer trait. If that lifetime annotation is removed, the above code indeed compiles with a few modifications as posted below -
// Layer Trait definition
pub trait Layer: Debug {
fn from_u8(&mut self, bytes: &[u8]) -> Result<(Option<Box<dyn Layer>>, usize), Error>;
}
impl<'a> Packet<'a> {
fn from_u8(bytes: &'a [u8], _encap: EncapType) -> Result<Self, Error> {
let mut p = Packet::default();
let eth = ethernet::Ethernet::default();
let layer: RefCell<Box<dyn Layer>> = RefCell::new(Box::new(eth));
let mut res: (Option<Box<dyn Layer>>, usize);
let mut start = 0;
loop {
{
// Do a `borrow_mut` in it's own scope, that gets dropped at the end.
let mut decode_layer = layer.borrow_mut();
res = decode_layer.from_u8(&bytes[start..])?;
}
if res.0.is_none() {
// This is just required to push something to the RefCell, that will get dropped anyways.
let fake_boxed = Box::new(FakeLayer {});
let boxed = layer.replace(fake_boxed);
p.layers.push(boxed);
break;
}
// if the layer exists, get it in a layer.
let boxed = layer.replace(res.0.unwrap());
start = res.1;
// append the layer to layers.
p.layers.push(boxed);
}
Ok(p)
}
}
I'm stuck with ownership; I but can't make the Option<OutputPin> in my function usable. How should it be?
struct Chip {
wake_pin: Option<OutputPin>,
}
impl Chip {
pub fn new(wake_pin: Option<Pin>) -> Chip {
Chip {
wake_pin: wake_pin.map(|pin| pin.into_output()),
}
}
pub fn awake(&self) {
// Fails
if let Some(pin) = self.wake_pin {
pin.set_low();
}
}
}
fn main() {
let wake_pin = Gpio::new()
.expect("Can not init gpio")
.get(255)
.expect("Could not attach to wake pin");
let chip = Chip::new(Some(wake_pin));
}
I am using the rppal crate and the compiler fails in the if let Some area. I tried to borrow wake_pin, get the Option as a reference and some other things but I don't understand the ownership rules completely.
I believe I've duplicated your set up. If something isn't right, please edit your question with the relevant details.
src/main.rs:
use rppal::gpio::{Gpio, OutputPin, Pin};
struct Chip {
wake_pin: Option<OutputPin>,
}
impl Chip {
pub fn new(wake_pin: Option<Pin>) -> Chip {
Chip {
wake_pin: wake_pin.map(|pin| pin.into_output()),
}
}
pub fn awake(&self) {
// Fails
if let Some(pin) = self.wake_pin {
pin.set_low();
}
}
}
fn main() {
let wake_pin = Gpio::new()
.expect("Can not init gpio")
.get(255)
.expect("Could not attach to wake pin");
let chip = Chip::new(Some(wake_pin));
}
Cargo.toml:
[package]
name = "tmp"
version = "0.0.1"
edition = "2018"
[dependencies]
rppal = "0.11.3"
Attempting to compile this (with cargo check or similar), we get a warning and two errors.
warning: unused variable: `chip`
--> src/main.rs:28:9
|
28 | let chip = Chip::new(Some(wake_pin));
| ^^^^ help: consider prefixing with an underscore: `_chip`
|
= note: `#[warn(unused_variables)]` on by default
error[E0507]: cannot move out of `self.wake_pin.0` which is behind a shared reference
--> src/main.rs:16:28
|
16 | if let Some(pin) = self.wake_pin {
| --- ^^^^^^^^^^^^^ help: consider borrowing here: `&self.wake_pin`
| |
| data moved here
| move occurs because `pin` has type `rppal::gpio::pin::OutputPin`, which does not implement the `Copy` trait
error[E0596]: cannot borrow `pin` as mutable, as it is not declared as mutable
--> src/main.rs:17:13
|
16 | if let Some(pin) = self.wake_pin {
| --- help: consider changing this to be mutable: `mut pin`
17 | pin.set_low();
| ^^^ cannot borrow as mutable
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0507, E0596.
For more information about an error, try `rustc --explain E0507`.
error: Could not compile `tmp`.
To learn more, run the command again with --verbose.
Since you're presumably going to use chip later, we can silence the warning by temporarily renaming it to _chip.
let _chip = Chip::new(Some(wake_pin));
The first error tells us that we can't move the pin out of self since we're only borrowing self. It would be rather rude to invalidate the data behind self if we're only borrowing it. However, the compiler is telling us a solution. help: consider borrowing here: `&self.wake_pin`
It ends up not quite being right, but it's the right direction.
if let Some(pin) = &self.wake_pin {
pin.set_low();
}
Now instead of pin having type OutputPin (an owned value), it has type &OutputPin (a borrowed value).
We still get the second error though (with a slightly different phrasing). The point is that pin.set_low() requires pin to be a mutable reference. Right now, we're taking self as an immutable reference (pub fn awake(&self)). If we're going to mutate self or any of its fields, we need to take it mutably. This also means we need to make sure pin is borrowed mutably.
pub fn awake(&mut self) {
if let Some(pin) = &mut self.wake_pin {
pin.set_low();
}
}
I am testing some Rust code and want to log some of the intermediate data to a file to make sure it is correct before I write the next element in the pipeline that consumes the data. In any other language I'd just write the data to a file handle stored in a static variable, but rust complains (correctly) that this is not thread safe. Since the application in question uses gstreamer this is theoretically a threat. I'll just paste my naive version below:
use std::fs::File;
use std::io::Write;
fn main() {
log_mesh("bacon");
}
static mut meshes : Option<Result<File, std::io::Error>> = None;
fn log_mesh(message: &str)
{
if let None = meshes {
meshes = Some(File::open("/tmp/meshes.txt"));
}
if let Ok(mut f) = meshes.unwrap() {
f.write_all(message.as_bytes());
f.flush();
}
}
This results in two important kinds of compile errors:
error[E0507]: cannot move out of static item
--> src/main.rs:16:24
|
16 | if let Ok(mut f) = meshes.unwrap() {
| ^^^^^^ cannot move out of static item
error[E0133]: use of mutable static is unsafe and requires unsafe function or block
--> src/main.rs:12:19
|
12 | if let None = meshes {
| ^^^^^^ use of mutable static
|
= note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
I have flailed around with Mutex, lazy_static!, mut_static, but all of them lead me into the woods and I get lost. I assume there has to be some compact idiom to solve this problem that isn't coming up in Google search results.
The first attempt at lazy_static! usage would be
use lazy_static::lazy_static;
use std::sync::Mutex;
use std::fs::File;
use std::io::Write;
lazy_static! {
static ref meshes : Mutex<Result<File, std::io::Error>> = Mutex::new(File::open("/tmp/meshes.txt"));
}
pub fn log_mesh(message: &str)
{
let mut tmp = meshes.lock().unwrap();
if let Ok(ref mut f) = tmp {
f.write_all(message.as_bytes());
f.flush();
}
}
which triggers this compile error:
error[E0308]: mismatched types
--> src/module2.rs:16:12
|
16 | if let Ok(ref mut f) = tmp {
| ^^^^^^^^^^^^^ --- this match expression has type `std::sync::MutexGuard<'_, std::result::Result<std::fs::File, std::io::Error>>`
| |
| expected struct `std::sync::MutexGuard`, found enum `std::result::Result`
|
= note: expected type `std::sync::MutexGuard<'_, std::result::Result<std::fs::File, std::io::Error>, >`
found type `std::result::Result<_, _>`
which is somewhat discouraging and chock-full of behind-the-curtain magic, but can be solved by changing it to
if let Ok(ref mut f) = *tmp {
I hesitate to mark it as an answer because there could be race conditions a more experienced coder can spot or another idiom that is superior.
I am trying to write a method that returns a rusqlite::MappedRows:
pub fn dump<F>(&self) -> MappedRows<F>
where F: FnMut(&Row) -> DateTime<UTC>
{
let mut stmt =
self.conn.prepare("SELECT created_at FROM work ORDER BY created_at ASC").unwrap();
let c: F = |row: &Row| {
let created_at: DateTime<UTC> = row.get(0);
created_at
};
stmt.query_map(&[], c).unwrap()
}
I am getting stuck on a compiler error:
error[E0308]: mismatched types
--> src/main.rs:70:20
|
70 | let c: F = |row: &Row| {
| ____________________^ starting here...
71 | | let created_at: DateTime<UTC> = row.get(0);
72 | | created_at
73 | | };
| |_________^ ...ending here: expected type parameter, found closure
|
= note: expected type `F`
= note: found type `[closure#src/main.rs:70:20: 73:10]`
What am I doing wrong here?
I tried passing the closure directly to query_map but I get the same compiler error.
I'll divide the answer in two parts, the first about how to fix the return type without considering borrow-checker, the second about why it doesn't work even if you fixed the return type.
§1.
Every closure has a unique, anonymous type, so c cannot be of any type F the caller provides. That means this line will never compile:
let c: F = |row: &Row| { ... } // no, wrong, always.
Instead, the type should be propagated out from the dump function, i.e. something like:
// ↓ no generics
pub fn dump(&self) -> MappedRows<“type of that c”> {
..
}
Stable Rust does not provide a way to name that type. But we could do so in nightly with the "impl Trait" feature:
#![feature(conservative_impl_trait)]
// ↓~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pub fn dump(&self) -> MappedRows<impl FnMut(&Row) -> DateTime<UTC>> {
..
}
// note: wrong, see §2.
The impl F here means that, “we are going to return a MappedRows<T> type where T: F, but we are not going to specify what exactly is T; the caller should be ready to treat anything satisfying F as a candidate of T”.
As your closure does not capture any variables, you could in fact turn c into a function. We could name a function pointer type, without needing "impl Trait".
// ↓~~~~~~~~~~~~~~~~~~~~~~~~
pub fn dump(&self) -> MappedRows<fn(&Row) -> DateTime<UTC>> {
let mut stmt = self.conn.prepare("SELECT created_at FROM work ORDER BY created_at ASC").unwrap();
fn c(row: &Row) -> DateTime<UTC> {
row.get(0)
}
stmt.query_map(&[], c as fn(&Row) -> DateTime<UTC>).unwrap()
}
// note: wrong, see §2.
Anyway, if we do use "impl Trait", since MappedRows is used as an Iterator, it is more appropriate to just say so:
#![feature(conservative_impl_trait)]
pub fn dump<'c>(&'c self) -> impl Iterator<Item = Result<DateTime<UTC>>> + 'c {
..
}
// note: wrong, see §2.
(without the 'c bounds the compiler will complain E0564, seems lifetime elision doesn't work with impl Trait yet)
If you are stuck with Stable Rust, you cannot use the "impl Trait" feature. You could wrap the trait object in a Box, at the cost of heap allocation and dynamic dispatch:
pub fn dump(&self) -> Box<Iterator<Item = Result<DateTime<UTC>>>> {
...
Box::new(stmt.query_map(&[], c).unwrap())
}
// note: wrong, see §2.
§2.
The above fix works if you want to, say, just return an independent closure or iterator. But it does not work if you return rusqlite::MappedRows. The compiler will not allow the above to work due to lifetime issue:
error: `stmt` does not live long enough
--> 1.rs:23:9
|
23 | stmt.query_map(&[], c).unwrap()
| ^^^^ does not live long enough
24 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the body at 15:80...
--> 1.rs:15:81
|
15 | pub fn dump(conn: &Connection) -> MappedRows<impl FnMut(&Row) -> DateTime<UTC>> {
| ^
And this is correct. MappedRows<F> is actually MappedRows<'stmt, F>, this type is valid only when the original SQLite statement object (having 'stmt lifetime) outlives it — thus the compiler complains that stmt is dead when you return the function.
Indeed, if the statement is dropped before we iterate on those rows, we will get garbage results. Bad!
What we need to do is to make sure all rows are read before dropping the statement.
You could collect the rows into a vector, thus disassociating the result from the statement, at the cost of storing everything in memory:
// ↓~~~~~~~~~~~~~~~~~~~~~~~~~
pub fn dump(&self) -> Vec<Result<DateTime<UTC>>> {
..
let it = stmt.query_map(&[], c).unwrap();
it.collect()
}
Or invert the control, let dump accept a function, which dump will call while keeping stmt alive, at the cost of making the calling syntax weird:
// ↓~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pub fn dump<F>(&self, mut f: F) where F: FnMut(Result<DateTime<UTC>>) {
...
for res in stmt.query_map(&[], c).unwrap() {
f(res);
}
}
x.dump(|res| println!("{:?}", res));
Or split dump into two functions, and let the caller keep the statement alive, at the cost of exposing an intermediate construct to the user:
#![feature(conservative_impl_trait)]
pub fn create_dump_statement(&self) -> Statement {
self.conn.prepare("SELECT '2017-03-01 12:34:56'").unwrap()
}
pub fn dump<'s>(&self, stmt: &'s mut Statement) -> impl Iterator<Item = Result<DateTime<UTC>>> + 's {
stmt.query_map(&[], |row| row.get(0)).unwrap()
}
...
let mut stmt = x.create_dump_statement();
for res in x.dump(&mut stmt) {
println!("{:?}", res);
}
The issue here is that you are implicitly trying to return a closure, so to find explanations and examples you can search for that.
The use of the generic <F> means that the caller decides the concrete type of F and not the function dump.
What you would like to achieve instead requires the long awaited feature impl trait.