The ?
operator at line 9 works OK, but if I use the same logic on the same type in line 19, it blows up.
use std::error::Error;
use walkdir::WalkDir;
fn main() -> Result<(), Box<dyn Error>> {
let valid_entries = WalkDir::new("/tmp")
.into_iter()
.flat_map(|e| e)
.flat_map(|e| {
let name = e.file_name().to_str()?; // <-- this works
if name.contains(".txt") {
Some(e)
} else {
None
}
});
for entry in valid_entries {
println!("This file matches: {:?}", entry);
let name_to_str = entry.file_name().to_str()?; // <-- this blows up
// ...
}
Ok(())
}
The errors are a little cryptic for me to interpret:
error[E0277]: the trait bound `std::option::NoneError: std::error::Error` is not satisfied
--> src/main.rs:19:53
|
26 | let name_to_str = entry.file_name().to_str()?;
| ^ the trait `std::error::Error` is not implemented for `std::option::NoneError`
|
= note: required because of the requirements on the impl of `std::convert::From<std::option::NoneError>` for `std::boxed::Box<dyn std::error::Error>`
= note: required by `std::convert::From::from`
Why is the ?
operator blowing up while iterating valid_entries
?
The ?
can be used to check-and-return any type that implements the Try
trait (still unstable). The only implementations in std
of those are Option<T>
and Result<T, E>
(plus some Future
-related impls that are not relevant to this discussion). This means that you can use the ?
operator in any function that returns Result<T, E>
or Option<T>
.
But you cannot mix-n-match those. That is, if your function returns a Result<T, E>
you cannot use the ?
in a value of type Option<T>
. Or vice versa.
The reason your first ?
works is because you are inside a flat_map()
that returns Option<String>
and all goes well. The second one, however, is in a function that returns a Result<(), Box<dyn Error>>
so you can't use ?
with an Option<String>
.
The solution is simply to deal with the None
in your Option<String>
in another way:
match
/ if let Some(x)
to handle the error separately.Result<String, Error>
and use ?
, for example with .ok_or(std::io::ErrorKind::InvalidData)?;
.impl From<&str> for Box<dyn Error>
and do .ok_or("invalid file name")
.Option::unwrap_or()
or similar.unwrap()
and panicking if None
.Ok, but what does this error mean? The idea is that actually you are able to use ?
with an Option<T>
that returns a Result<T, E>
, as long as your E
implements From<std::option::NoneError>
. Unfortunately, NoneError
is still unstable, too, so you can't implement From<NoneError>
in your code using the stable compiler. Nevertheless, the E
in your code is Box<dyn Error>
, and the compiler would be happy to do the boxing as long as NoneError
implements Error
, but...
error[E0277]: the trait bound `std::option::NoneError: std::error::Error` is not satisfied
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With