Consider the following code:
fn foo<E, F: FnMut() -> Result<bool, E>>(f: F) -> Result<bool, E> {
todo!();
}
fn qux() -> Result<(), &'static str> {
Err("qux")
}
fn bar() {
foo(|| {
qux()?;
Ok(true)
});
}
This fails to compile with:
error[E0282]: type annotations needed
--> src/lib.rs:10:5
|
10 | foo(|| {
| ^^^ cannot infer type for type parameter `E` declared on the function `foo`
The naive observer might think "but this is the same as":
fn bar() {
foo(|| {
match qux() {
Ok(()) => {},
Err(e) => return Err(e),
}
Ok(true)
});
}
which does compile, but the actual equivalent would be
fn bar() {
foo(|| {
match qux() {
Ok(()) => {},
Err(e) => return Err(e.into()),
}
Ok(true)
});
}
which does fail to compile.
So my question would be: could type inference disambiguate these cases by considering the simplest Into::into that might be used, i.e. the identity?
Although I guess type annotations are not all that bad...
fn bar() {
[1, 2].iter().try_find(|i| -> Result<_, &'static_str> {
qux()?;
Ok(true)
});
}
Funnily enough, this does not happen in this case:
fn bar() -> Result<(), &'static str> {
[1, 2].iter().try_find(|i| {
qux()?;
Ok(true)
})?;
Ok(())
}
But it does when changing the error type to e.g. String
on both bar
and qux
.