I’ve been looking for an excuse to dive deeper into Rust now that it has reached a stable version (v1.0). With some recent consolidation of some old hard drives, I have need of a fast duplicate file detector. I thought that was the perfect excuse to play with Rust and see how it performed.
The first step in finding a duplicate file is to read the file system, so I set out to convince Rust to read a directory and print the results. My early investigation was promising – the std::fs module was (mostly) stable and had a method to read a directory – read_dir().
Things were looking good – a quick dive through the documentation lead me to the DirEntry struct, which had a code snippet that read the current directory and printed it. Problem solved:
use std::fs;
for entry in try!(fs::read_dir(".")) {
let dir = try!(entry);
println!("{:?}", dir.path());
}
A little manipulation to turn that snippet into an executable program and I was ready to go. Unfortunately, the snippet fails to compile with two identical errors:
:5:8: 6:42 error: mismatched types: expected `()`, found `core::result::Result<_, _>` (expected (), found enum `core::result::Result`) [E0308] :5 return $ crate:: result:: Result:: Err ( :6 $ crate:: convert:: From:: from ( err ) ) } } ) :1:1: 6:48 note: in expansion of try! :3:18: 3:41 note: expansion site :5:8: 6:42 error: mismatched types: expected `()`, found `core::result::Result<_, _>` (expected (), found enum `core::result::Result`) [E0308] :5 return $ crate:: result:: Result:: Err ( :6 $ crate:: convert:: From:: from ( err ) ) } } ) :1:1: 6:48 note: in expansion of try! :4:19: 4:30 note: expansion site error: aborting due to 2 previous errors
While most of that message is rather obtuse, it does offer a clue in the note:
section – apparently the 2 try!
macros were to blame.
Once I realized that, I could focus on why I was getting the error. My Google-fu turned up no suggestions, and the documentation samples all used try!
, so I turned to the source. The read_dir
source offered no clues – it returned the Result
struct that try!
was expecting. My next step was to look up the source for try!
, and the very first result was a bug report “try! not usable in main()â€.
Oops.
Turns out this issue is “by designâ€. Since main returns “()â€
, and try!
can return an error, you get a type mismatch, and the (now much clearer) error E0308 referenced above. Fortunately, now that I understood the problem, the solution was simple – just unwrap()
the result and let the program panic if it failed.
use std::fs; fn main() { for entry in fs::read_dir(".").unwrap() { let dir = entry.unwrap(); println!("{:?}", dir.path()); } }