Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error messages for io::fs #14629

Closed
wants to merge 1 commit into from

Conversation

Projects
None yet
4 participants
@wycats
Copy link
Contributor

wycats commented Jun 3, 2014

This commit improves the error descriptions and details for the functions and methods exposed in io::fs.

The basic idea is that the description should always map onto the high-level operation that the user was trying to perform, with the detail containing the original message. The IoErrorKind is always maintained. The detail also includes additional information (most notably the relevant path, but also other parameters or contextual information).

I added an UpdateIoError trait to make it easier to do these in-place modification, and I'm eager for feedback on the specific strategy.

@@ -134,6 +135,8 @@ impl File {
last_nread: -1
}
})
}).update_err("Couldn't open file", |e| {

This comment has been minimized.

@alexcrichton

alexcrichton Jun 3, 2014

Member

Our convention, at least for the compiler, is to start with lowercase letters as opposed to uppercase letters.

@@ -134,6 +135,8 @@ impl File {
last_nread: -1
}
})
}).update_err("Couldn't open file", |e| {
format!("{}; path={}; mode={}; access={}", e, path.display(), mode_string(mode), access_string(access))

This comment has been minimized.

@alexcrichton

alexcrichton Jun 3, 2014

Member

Could you wrap this line and the ones below to 80 characters?

}

//fn io_err_for_path(path: &Path) -> (|&mut IoError| -> String) {
//|err| format!("{}; path={}", err, path.display())
//}

This comment has been minimized.

@alexcrichton

alexcrichton Jun 3, 2014

Member

This may have stuck around by accident

super::ReadWrite => "readwrite"
}
}

#[cfg(test)]
#[allow(unused_imports)]
mod test {

This comment has been minimized.

@alexcrichton

alexcrichton Jun 3, 2014

Member

Could you add some tests to make sure there's some more contextual information in the errors returned?

fn update_desc(self, desc: &'static str) -> IoResult<T> {
self.map_err(|mut e| { e.desc = desc; e })
}
}

This comment has been minimized.

@alexcrichton

alexcrichton Jun 3, 2014

Member

This is an interesting pattern, I wonder if it could be generalized? Not a worry for now, though, it's just a private detail.

Some(ref s) => write!(fmt, " ({})", *s),
None => Ok(())
match *self {
IoError { kind: OtherIoError, desc: "unknown error", detail: Some(ref detail), .. } =>

This comment has been minimized.

@alexcrichton

alexcrichton Jun 6, 2014

Member

I'm actually a little surprised that the compiler lets you get away with , .. here, you matched all the fields!

This comment has been minimized.

@wycats

wycats Jun 6, 2014

Author Contributor

Heh, good call!

detail: if detail {
Some(os::error_string(errno))
detail: if detail && kind == OtherIoError {
Some(os::error_string(errno).as_slice().chars().map(|c| c.to_lowercase()).collect())

This comment has been minimized.

@alexcrichton

alexcrichton Jun 6, 2014

Member

Did you lowercase just to stick with our same conventions? I'd be wary about changing what the OS is giving us, and if it's against our conventions it's not really our fault.

This comment has been minimized.

@wycats

wycats Jun 6, 2014

Author Contributor

Yeah. I think we should try to have consistency between error messages that are produced in userland (like in libuv, for example) and ones that are produced by the OS.

@@ -303,6 +303,8 @@ impl IoError {
/// struct is filled with an allocated string describing the error
/// in more detail, retrieved from the operating system.
pub fn from_errno(errno: uint, detail: bool) -> IoError {
use str::Str;

This comment has been minimized.

@alexcrichton

alexcrichton Jun 6, 2014

Member

Could you put this at the top of the file instead?

This comment has been minimized.

@wycats

wycats Jun 6, 2014

Author Contributor

Sure.

macro_rules! error( ($e:expr, $s:expr) => (
match $e {
Ok(val) => fail!("Should have been an error, was {:?}", val),
Err(ref err) => assert!(err.to_str().as_slice().contains($s.as_slice()), format!("`{}` did not contain `{}`", err, $s))

This comment has been minimized.

@alexcrichton

alexcrichton Jun 6, 2014

Member

This line may be approaching the 100 character line limit.

This comment has been minimized.

@wycats

wycats Jun 6, 2014

Author Contributor

It looked like tests had a different limit?

|e| format!("{}; path={}", e, file.path.display()))
}

let result: IoResult<int> = update_err(self.fd.read(buf), self);

This comment has been minimized.

@alexcrichton

alexcrichton Jun 6, 2014

Member

Is this type ascription necessary? I would have thought that rustc could figure it out.

@@ -452,6 +481,8 @@ pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
/// directory at the provided path, or if the directory isn't empty.
pub fn rmdir(path: &Path) -> IoResult<()> {
LocalIo::maybe_raise(|io| io.fs_rmdir(&path.to_c_str()))
.update_err("couldn't remove directory",
|e| format!("{}; path={}", e, path.display()))

This comment has been minimized.

@alexcrichton

alexcrichton Jun 6, 2014

Member

Stylistically, we normally line up the | right after the open-paren so the arguments are all aligned, like:

.update_err("...",
            |e| ...);

This comment has been minimized.

@wycats

wycats Jun 6, 2014

Author Contributor

I feel like there is a conspiracy to make each method call at least 10 lines ;)

This comment has been minimized.

@adrientetar

adrientetar Jun 6, 2014

Contributor

+1

@wycats

This comment has been minimized.

Copy link
Contributor Author

wycats commented Jun 6, 2014

I believe I have responded to all of your comments. 😄

@alexcrichton

This comment has been minimized.

Copy link

alexcrichton commented on 5ae6e93 Jun 6, 2014

r+

@bors

This comment has been minimized.

Copy link
Contributor

bors commented on 5ae6e93 Jun 7, 2014

saw approval from alexcrichton
at wycats@5ae6e93

This comment has been minimized.

Copy link
Contributor

bors replied Jun 7, 2014

merging wycats/rust/improve-fs-errors = 5ae6e93 into auto

This comment has been minimized.

Copy link
Contributor

bors replied Jun 7, 2014

wycats/rust/improve-fs-errors = 5ae6e93 merged ok, testing candidate = 67b0569

bors added a commit that referenced this pull request Jun 7, 2014

auto merge of #14629 : wycats/rust/improve-fs-errors, r=alexcrichton
This commit improves the error descriptions and details for the functions and methods exposed in `io::fs`.

The basic idea is that the description should always map onto the high-level operation that the user was trying to perform, with the `detail` containing the original message. The `IoErrorKind` is always maintained. The `detail` also includes additional information (most notably the relevant path, but also other parameters or contextual information).

I added an `UpdateIoError` trait to make it easier to do these in-place modification, and I'm eager for feedback on the specific strategy.
@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Jun 11, 2014

I'll rebase and take over from here (talked with @wycats on IRC)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.