This RFC proposes to add filename information to std::io:Error. By doing so, std::io error messages will include which file the user is trying to access and making it easier for the user to notice where their code is failing.
Motivation
Consider a simple program which reads a file which doesn't exist:
use File;
This program emits the following error message:
Error: Os { code: 2, kind: NotFound, message: "No such file or directory" }
This error message doesn't tell the user which file doesn't exist and doesn't give the user a full breakdown of the error and what went wrong. As I've experienced and many others have, this error doesn't help a beginner Rust programmer to understand what went wrong and how to fix it. If the compiler emitted a full error and more information such as the name of the file which doesn't exist, this would be much more helpful.
Guide-level explanation
Suppose a user creates the same program as before:
use File;
With this change, a much more descriptive and helpful error message will be emitted:
Error: Os { code: 2, kind: NotFound, message: "No such file or directory", file: "/Users/henryboisdequin/hello.txt" }
This error explains where the error is emitted and the cause of it. As you can see, this error is much more helpful. It points to where the problem is and the cause of it. Let's look at another case:
use File;
This program returns the following error:
Error: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }
This program is not helpful at all, not displaying file information or how to fix this error. With this change, here is the projected error message:
Error: Os { code: 13, kind: PermissionDenied, message: "Permission denied", file: "/etc/protocols" }
In this case, this change would add the file to the Os error message. Many crates and Rust applications write their own error messages to improve the experience while working with std::io. This is why we should incorporate filename information to std::io:Error to reduce the amount of boilerplate crates and Rust applications need to write to ensure a better std::io development process.
Reference-level explanation
1.
- Add field
file: Option<PathBuf>to structstd::io::Error- Whenever a file doesn't exist or another error occurs when writing/reading/accessing a file, add the filename to the
filefield
- Whenever a file doesn't exist or another error occurs when writing/reading/accessing a file, add the filename to the
2.
- Test impact of performance by adding benchmarks and looking at
std's andstd::io's general difference in performance before and after this implementation
Drawbacks
Option<PathBuf>would makestd::io:Errorheavier than before (originally pointed out by @withoutboats)- In some cases, this would also make
std::io:Errorinefficient as operations which expect a large number of failures would have to allocate to the error itself and thePathBufin thefilefield (originally pointed out by @alexcrichton)
- In some cases, this would also make
Rationale and alternatives
- Of course, an alternative to this RFC would to leave OS errors as they are. We should implement this change because it makes is much more helpful to the user with a more useful diagnostic. For example, if a certain crate that a user is using is trying to access an arbitrary file which doesn't exist, currently an error message such as this would be emptied:
Error: Os { code: 2, kind: NotFound, message: "No such file or directory" }
This doesn't help the user whatsoever. If they were also trying to access files from their own code, they wouldn't know where the error is coming from as their is no filename or information on how to resolve this problem.
- (@nagisa's idea): To have callers to attach the filename and the operation done to the error by adding context to it (similarly to how the community handles
std::ioerrors with error handling crates such asanyhow).
Prior art
-
Python's
OSErrorexception contains filename information (filenameandfilename2) which is later used when emitting anOSError -
This change was previously implemented in 2014, but was removed during the
std::ioreform due to various different reasons -
Node's
EACCESError also contains filename information which include the path of the file -
fs-err is a replacement for
std::fswhich keeps adds the filename to the diagnostic