rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

Proposal: Ability for borrow checker to identify unused closure which takes ownership

Open aaron-jack-manning opened this issue 3 years ago • 0 comments

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.

aaron-jack-manning avatar Jun 03 '22 09:06 aaron-jack-manning