Reputation: 5345
I've written a pretty straight-forward script based on the Rust docs:
use std::fs::{self, DirEntry};
use std::path::Path;
fn main() {
let path = Path::new(".");
for entry in fs::read_dir(path)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
println!("directory found!");
}
}
}
but I get the following compile errors about ?
:
error[E0277]: the trait bound `(): std::ops::Carrier` is not satisfied
--> test.rs:6:18
|
6 | for entry in fs::read_dir(path)? {
| -------------------
| |
| the trait `std::ops::Carrier` is not implemented for `()`
| in this macro invocation
|
= note: required by `std::ops::Carrier::from_error`
error[E0277]: the trait bound `(): std::ops::Carrier` is not satisfied
--> test.rs:7:21
|
7 | let entry = entry?;
| ------
| |
| the trait `std::ops::Carrier` is not implemented for `()`
| in this macro invocation
|
= note: required by `std::ops::Carrier::from_error`
I only partially understand ?
but I know the gist is that it allows you to act on a Result
only if it's an Ok
. The error here is that it's being used on a ()
rather than a Result
, which is weird. I tried implementing the loop without ?
:
use std::fs::{self, DirEntry};
use std::path::Path;
fn main() {
let path = Path::new(".");
for entry in fs::read_dir(path) {
println!("{}", entry.path());
}
}
But I get the error:
error: no method named `path` found for type `std::fs::ReadDir` in the current scope
--> test.rs:7:30
|
7 | println!("{}", entry.path());
| ^^^^
Which implies that instead of fs::read_dir
returning ReadDir
which is an iterator over DirEntry
items, fs::read_dir
is returning ()
which is somehow an iterator over ReadDir
items?
I'm so confused.
It's probably worth mentioning that i'm running: rustc 1.16.0 (30cf806ef 2017-03-10)
Upvotes: 1
Views: 8435
Reputation: 29983
The ?
operator and the try!
macro will only work when your function returns a Result
(in which the raised errors can be properly converted, of course). The main function does not return a result.
You may wish to send all of your code to a separate function and handle the error in main()
, with something like this:
use std::io;
use std::fs::{self, DirEntry};
use std::path::Path;
fn main() {
run().unwrap_or_else(|e| {
println!("Something went wrong: {}", e.to_string());
});
}
fn run() -> io::Result<()> {
let path = Path::new(".");
for entry in fs::read_dir(path)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
println!("directory found!");
}
}
Ok(())
}
Upvotes: 5
Reputation: 430711
The first error is because you cannot use try!
or ?
in a function returning ()
.
The second error is because read_dir
returns a Result
:
pub fn read_dir<P: AsRef<Path>>(path: P) -> Result<ReadDir>
Result
implements IntoIterator
, so path
is actually the iterator you think you had.
Handling the errors and calling Path::display
gets you what you want:
use std::fs;
use std::path::Path;
fn main() {
let path = Path::new(".");
for entry in fs::read_dir(path).expect("Unable to list") {
let entry = entry.expect("unable to get entry");
println!("{}", entry.path().display());
}
}
Upvotes: 9