I meant "get the traits of functions together", in other words the compiler always pointed at some trait missing.
I tried another time the approach. It seems to work, just as the solutions by @semicoleon and @jbe. But as soon as I try to pass None
instead of a callback, the compiler never gets happy.
Here's the source code that works:
// inside the struct
pub fn map_all<F1, F2, F3>(&mut self, mut node_cb: Option<F1>, mut way_cb: Option<F2>, mut rel_cb: Option<F3>) -> OkOrBox
where
F1: FnMut(Node) -> OkOrBox,
F2: FnMut(Way) -> OkOrBox,
F3: FnMut(Relation) -> OkOrBox
{
self.skip_nodes = node_cb.is_none();
self.skip_ways = way_cb.is_none();
self.skip_relations = rel_cb.is_none();
for item in self.into_iter() {
match item? {
OsmObj::Node(n) => if let Some(ref mut ncb) = node_cb { ncb(n)?; },
OsmObj::Way(w) => if let Some(ref mut wcb) = way_cb { wcb(w)?; },
OsmObj::Relation(r) => if let Some(ref mut rcb) = rel_cb { rcb(r)?; },
}
}
Ok(())
}
...
// usage:
let mut nodes_count:i32 = 0;
let mut ways_count:i32 = 0;
let mut rels_count:i32 = 0;
let ncb = |_n: Node| -> OkOrBox { nodes_count +=1; Ok(()) };
let wcb = |_w: Way| -> OkOrBox{ ways_count +=1; Ok(()) };
let rcb = |_r: Relation| -> OkOrBox { rels_count +=1; Ok(()) };
let mut my_rdr = OsmXmlReader::from_path(&osm_xml_path)?;
my_rdr.map_all(Some(ncb), Some(wcb), Some(rcb))?;
This works fine. But if you try passing a None
, the compiler starts giving more and more requirements: first, "I need type annotations", then when I make them:
my_rdr.map_all(Some(ncb), Some(wcb), None as Option<dyn FnMut(Relation) -> OkOrBox>)?;
it tells the size can't be known. Then I make the parameters Option<Box<dyn FnMut...>>
and it wants the generics to be 'static
. I put static, it wants ?Sized
, but then doesn't allow ?Sized
in the return type.
The version with applied changes that still doesn't work is in this commit.
Of course, I can make a stub function that does nothing, and this whole issue goes away (and tell via skip_X
flags that I want to skip those variants of OsmObj
).
I tried to run Option<FnMut...>
in a background thread (replace into_iter
with in_background
), and it gave the same kind of errors. As I see, passing generic callbacks with loose types in threads is too hard (or impossible because of mutability and data safety).