Proposal: Ability for borrow checker to identify unused closure which takes ownership
Here is a simple example of a problem I have come across:
use std::path;
use std::fs;
use std::io::Write;
#[derive(Debug)]
enum FileError {
Creation(path::PathBuf),
Writing(path::PathBuf)
}
fn main() -> Result<(), FileError> {
let file_path = path::PathBuf::from("/home/something.txt");
let mut file =
fs::File::create(&file_path)
.map_err(|_e| FileError::Creation(file_path))?;
file.write_all(&[b'a'])
.map_err(|_e| FileError::Writing(file_path))?;
Ok(())
}
The above code does not compile due to the move of file_path into the closure given to the first call to .map_err which is then used again in the second call to that function.
This is despite the fact that the early return means that in the event of File::create failing, the value is moved and then cannot be reused because of the early return. If File::create succeeds then this closure is never called.
Replacing this first call of .map_err with a pattern match and return statement does compile due to the fact that the value is never moved into a closure in the meantime.
use std::path;
use std::fs;
use std::io::Write;
#[derive(Debug)]
enum FileError {
Creation(path::PathBuf),
Writing(path::PathBuf)
}
fn main() -> Result<(), FileError> {
let file_path = path::PathBuf::from("/home/something.txt");
let mut file = match fs::File::create(&file_path) {
Ok(file) => file,
Err(_) => return Err(FileError::Creation(file_path)),
};
file.write_all(&[b'a'])
.map_err(|_e| FileError::Writing(file_path))?;
Ok(())
}
I'm not sure to what extent removing the error in the first case would require a special case written in, but it seems to me like inlining the closure would resolve this issue.