I have a match block that is repeated in more or less identical form in a few places. I'd like to refactor that into a function, but ran into type mismatch issues. The match block uses a future creation function that returns an impl Trait and I think this is making the types harder to get right.
The future creation function signature is:
fn get_cmd_future(
name: &str,
cmd: &mut CmdSpec,
) -> Result<impl Future<Output = Result<CompletedCmd, std::io::Error>>, std::io::Error> {
}
The match block that I'd like to refactor is:
match get_cmd_future(cmd_to_start, &mut cmd) {
Ok(spawned_child) => {
println!("starting {}", cmd_to_start);
all_futures.push(Either::Right(spawned_child));
cmds.insert(cmd_to_start.to_string(), cmd);
}
Err(e) => println!("spawn failed: {:?}", e),
}
Background: all_futures is a FutureUnordered<_> and cmds is a HashMap<String, CmdSpec>. CmdSpec is a run-of-the-mill struct with a few fields.
The closest I could get to a successful compilation was the following:
fn start_process<T: Future<Output = Result<CompletedCmd, std::io::Error>>>(
cmd_to_start: &str,
cmd: CmdSpec,
cmds: &mut Cmds,
all_futures: &mut FuturesUnordered<Either<T, T>>,
) {
match get_cmd_future(cmd_to_start, &mut cmd) {
Ok(spawned_child) => {
println!("starting {}", cmd_to_start);
all_futures.push(Either::Right(spawned_child));
cmds.insert(cmd_to_start.to_string(), cmd);
}
Err(e) => println!("spawn failed: {:?}", e),
}
}
This produces the following error:
error[E0308]: mismatched types
--> src/boss.rs:121:44
|
67 | ) -> Result<impl Future<Output = Result<CompletedCmd, std::io::Error>>, std::io::Error> {
| ---------------------------------------------------------- the found opaque type
...
112 | fn start_process<T: Future<Output = Result<CompletedCmd, std::io::Error>>>(
| - this type parameter
...
121 | all_futures.push(Either::Right(spawned_child));
| ^^^^^^^^^^^^^ expected type parameter `T`, found opaque type
|
= note: expected type parameter `T`
found opaque type `impl core::future::future::Future`
= help: type parameters must be constrained to match other types
If I look at the type for spawned_child, it's not quite what I expect: impl core::future::future::Future. I would have expected it to be more specific, as the return signature of `get_cmd_future() would indicate.
But, I don't really understand the error message and I am still not clear what on opaque types actually are. I think the error says "spawned_child needs to be a more specific type", but I couldn't find a way to "coerce" it or otherwise make it match. Is there a way to fiddle with the type specifications here to get this to work or is a different approach needed?
Thanks,
Chuck