windows-result: unwrap FACILITY_WIN32 HRESULTs when converting to std::io::Error#4448
windows-result: unwrap FACILITY_WIN32 HRESULTs when converting to std::io::Error#4448Copilot wants to merge 3 commits into
Conversation
Agent-Logs-Url: https://github.com/microsoft/windows-rs/sessions/31216d23-c3d0-45f8-9374-045e9fcf3536 Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
|
@copilot fix test failure |
Agent-Logs-Url: https://github.com/microsoft/windows-rs/sessions/a1c3bafa-bb0d-4e5d-9928-80281fec0a9a Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Fixed in cb52490. The arm64 Windows test was failing on |
There was a problem hiding this comment.
Pull request overview
Adjusts windows-result’s From<windows::core::Error> for std::io::Error conversion so Win32-origin HRESULTs map to Win32 error codes in raw_os_error(), enabling meaningful std::io::Error::kind() matching on Windows.
Changes:
- Unwrap
FACILITY_WIN32HRESULTs to the underlying Win32 error code when convertingError -> std::io::Error. - Extend tests to validate
ErrorKindmapping for common Win32 codes and preserve non-Win32 HRESULT behavior. - Add a round-trip test to ensure Win32 HRESULT information remains recoverable via
std::io::Error -> windows::core::Error.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| crates/libs/result/src/error.rs | Updates From<Error> for std::io::Error to unwrap FACILITY_WIN32 HRESULTs to Win32 codes. |
| crates/tests/misc/error/tests/std.rs | Updates and expands conversion tests to cover ErrorKind decoding and round-trips. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // If the HRESULT wraps a Win32 error (FACILITY_WIN32), unwrap it to the | ||
| // underlying Win32 error code so that `std::io::Error::kind` can decode | ||
| // it into a meaningful `ErrorKind`. For HRESULTs from other facilities | ||
| // (such as COM `E_*` codes or custom facilities), preserve the full | ||
| // HRESULT value to avoid losing information. This mirrors the behavior | ||
| // of .NET's `Marshal.GetExceptionForHR` and the conventions used by | ||
| // Rust's own Win32 error decoding. | ||
| if let Some(win32) = WIN32_ERROR::from_error(&from) { | ||
| Self::from_raw_os_error(win32.0 as i32) | ||
| } else { |
The
From<Error> for std::io::Errorimpl inwindows-resultpreviously stored the full HRESULT intofrom_raw_os_error. Because Rust'sstd::io::Error::kind()on Windows decodes raw OS errors as Win32 error codes (small values), passing a full HRESULT meantErrorKindfor every Win32-origin error fell through toUncategorized, defeating pattern matching.This change unwraps HRESULTs whose facility is
FACILITY_WIN32into their underlying Win32 code via the existingWIN32_ERROR::from_errorhelper, while preserving the full HRESULT unchanged for HRESULTs from other facilities (E_FAIL,E_NOTIMPL, RPC/COM/custom facilities). This mirrors the conventions used by .NET'sMarshal.GetExceptionForHRand Rust's own internal Win32 error decoding (option 2 from the issue discussion).Tests
Updated
crates/tests/misc/error/tests/std.rsto cover:ERROR_FILE_NOT_FOUND→ErrorKind::NotFoundE_INVALIDARG(which isHRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)) unwraps to 87 →ErrorKind::InvalidInputERROR_INVALID_DATAunwraps to its Win32 code (13) and formats with the expected message (noErrorKindassertion, since Rust's std maps code 13 toUncategorized)E_NOTIMPL,E_FAIL(non-FACILITY_WIN32) preserve the full HRESULTERROR_INVALID_DATA→std::io::Error→windows::core::Erroris information-preservingNote on behavior change
This is a behavioral change to a public
Fromimpl: HRESULTs withFACILITY_WIN32now surface as their underlying Win32 code instd::io::Error::raw_os_error()rather than the full HRESULT. This is the explicit goal — to makeErrorKindmatching work — but it affects existing users that readraw_os_error()expecting the full HRESULT. Non-FACILITY_WIN32 HRESULTs are unaffected.