Change:
On Windows an io::Error created via with the Windows system error code (1460) is not of the kind , but . This is counter-intuitive considering both (system error code and kind) have (almost) the same symbolic name. I've tested this with Rust 1.42 on x8664-pc-windows-gnu, but this behavior is obviously still present in . Unless I'm overlooking sth., this should be fairly easy to fix by defining the constant and adding the following after : If you'd like me to, I can prepare a merge request implementing the suggested fix. I tried this code: I expected to see this happen: Assertion passes because (should be): Instead, this happened: Assertion fails because: <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details
This issue is not limited to the system error code , as Windows appears to use various error codes for what would all be on POSIX. For example, I'm getting an () if a write operation on a COM port times out (on Windows 10 version 1809). Looking at the list of , I found the following that contain TIME and appear to be timeouts: () () () () () () Thanks to for pointing out that this error code indicates an invalid timeout and not that a timeout occurred. () () () () () () () () () ()
One concern with merging these all into is that the caller would no longer know which of the timeout occurred -- are there cases where that's important?
I don't think that's the case, but please correct me if I'm wrong. The following example will produce this on Windows: Currently, only will yield an of . All other timeout errors will be of , which is counter-intuitive, because matching an error's kind against will not catch all timeout errors. I would suggest to only change the kind of the errors listed above to . The original OS error code can still be accessed via if the programmer is interested in the OS-specific timeout reason. Therefore, this should not break backwards-compatibility, unless someone expects these errors to be , which should be discouraged.
Ah, okay, right. I would in that case not be personally opposed to making this change, I think a PR that does so would be the best way to do so (and that can be FCP'd to libs team).
All right. Thanks for the quick response. I'll prepare a pull request.
Note that does not indicate the operation timed out, but rather that the timeout you specified was invalid.
Thanks for checking that. I'll revise the list of errors before submitting the PR, but I'm afraid I have very close to zero experience with the Windows API. I just stumbled over this issue while porting POSIX software to Windows.

Discussion:
#[stable(feature = "rust1", since = "1.0.0")] Interrupted, /// Any I/O error not part of this list. <ins> /// /// Errors that are `Other` now may move to a different or a new /// [`ErrorKind`] variant in the future. It is not recommended to match /// an error against `Other` and to expect any additional characteristics, /// e.g., a specific [`Error::raw_os_error`] return value. </ins> #[stable(feature = "rust1", since = "1.0.0")] Other,

pub const PROGRESS_CONTINUE: DWORD = 0; <ins> // List of Windows system error codes with descriptions: // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes#system-error-codes </ins> pub const ERROR_FILE_NOT_FOUND: DWORD = 2; pub const ERROR_PATH_NOT_FOUND: DWORD = 3; pub const ERROR_ACCESS_DENIED: DWORD = 5;

pub const ERROR_INVALID_PARAMETER: DWORD = 87; pub const ERROR_BROKEN_PIPE: DWORD = 109; pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; <ins> pub const ERROR_SEM_TIMEOUT: DWORD = 121; </ins> pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; pub const ERROR_ALREADY_EXISTS: DWORD = 183; <del> pub const ERROR_NO_DATA: DWORD = 232; </del> pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203; <ins> pub const ERROR_NO_DATA: DWORD = 232; pub const ERROR_DRIVER_CANCEL_TIMEOUT: DWORD = 594; </ins> pub const ERROR_OPERATION_ABORTED: DWORD = 995; pub const ERROR_IO_PENDING: DWORD = 997; <del> pub const ERROR_TIMEOUT: DWORD = 0x5B4; </del> <ins> pub const ERROR_SERVICE_REQUEST_TIMEOUT: DWORD = 1053; pub const ERROR_COUNTER_TIMEOUT: DWORD = 1121; pub const ERROR_TIMEOUT: DWORD = 1460; pub const ERROR_RESOURCE_CALL_TIMED_OUT: DWORD = 5910; pub const ERROR_CTX_MODEM_RESPONSE_TIMEOUT: DWORD = 7012; pub const ERROR_CTX_CLIENT_QUERY_TIMEOUT: DWORD = 7040; pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: DWORD = 8014; pub const ERROR_DS_TIMELIMIT_EXCEEDED: DWORD = 8226; pub const DNS_ERROR_RECORD_TIMED_OUT: DWORD = 9705; pub const ERROR_IPSEC_IKE_TIMED_OUT: DWORD = 13805; pub const ERROR_RUNLEVEL_SWITCH_TIMEOUT: DWORD = 15402; pub const ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT: DWORD = 15403; </ins> pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT;

c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound, c::ERROR_NO_DATA => return ErrorKind::BrokenPipe, <del> c::ERROR_OPERATION_ABORTED => return ErrorKind::TimedOut, </del> <ins> c::ERROR_SEM_TIMEOUT | c::WAIT_TIMEOUT | c::ERROR_DRIVER_CANCEL_TIMEOUT | c::ERROR_OPERATION_ABORTED | c::ERROR_SERVICE_REQUEST_TIMEOUT | c::ERROR_COUNTER_TIMEOUT | c::ERROR_TIMEOUT | c::ERROR_RESOURCE_CALL_TIMED_OUT | c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT | c::ERROR_CTX_CLIENT_QUERY_TIMEOUT | c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT | c::ERROR_DS_TIMELIMIT_EXCEEDED | c::DNS_ERROR_RECORD_TIMED_OUT | c::ERROR_IPSEC_IKE_TIMED_OUT | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return ErrorKind::TimedOut, </ins> _ => {} }