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

Define a dedicated error type for HandleOrNull and HandleOrInvalid. #95387

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 44 additions & 8 deletions library/std/src/os/windows/io/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub struct OwnedHandle {
/// `NULL`. This ensures that such FFI calls cannot start using the handle without
/// checking for `NULL` first.
///
/// This type concerns any value other than `NULL` to be valid, including `INVALID_HANDLE_VALUE`.
/// This type considers any value other than `NULL` to be valid, including `INVALID_HANDLE_VALUE`.
/// This is because APIs that use `NULL` as their sentry value don't treat `INVALID_HANDLE_VALUE`
/// as special.
///
Expand All @@ -96,7 +96,7 @@ pub struct HandleOrNull(OwnedHandle);
/// `INVALID_HANDLE_VALUE`. This ensures that such FFI calls cannot start using the handle without
/// checking for `INVALID_HANDLE_VALUE` first.
///
/// This type concerns any value other than `INVALID_HANDLE_VALUE` to be valid, including `NULL`.
/// This type considers any value other than `INVALID_HANDLE_VALUE` to be valid, including `NULL`.
/// This is because APIs that use `INVALID_HANDLE_VALUE` as their sentry value may return `NULL`
/// under `windows_subsystem = "windows"` or other situations where I/O devices are detached.
///
Expand Down Expand Up @@ -143,17 +143,17 @@ impl BorrowedHandle<'_> {
}

impl TryFrom<HandleOrNull> for OwnedHandle {
type Error = ();
type Error = NullHandleError;

#[inline]
fn try_from(handle_or_null: HandleOrNull) -> Result<Self, ()> {
fn try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError> {
let owned_handle = handle_or_null.0;
if owned_handle.handle.is_null() {
// Don't call `CloseHandle`; it'd be harmless, except that it could
// overwrite the `GetLastError` error.
forget(owned_handle);

Err(())
Err(NullHandleError(()))
} else {
Ok(owned_handle)
}
Expand Down Expand Up @@ -201,23 +201,59 @@ impl OwnedHandle {
}

impl TryFrom<HandleOrInvalid> for OwnedHandle {
type Error = ();
type Error = InvalidHandleError;

#[inline]
fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, ()> {
fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> {
let owned_handle = handle_or_invalid.0;
if owned_handle.handle == c::INVALID_HANDLE_VALUE {
// Don't call `CloseHandle`; it'd be harmless, except that it could
// overwrite the `GetLastError` error.
forget(owned_handle);

Err(())
Err(InvalidHandleError(()))
} else {
Ok(owned_handle)
}
}
}

/// This is the error type used by [`HandleOrNull`] when attempting to convert
/// into a handle, to indicate that the value is null.
// The empty field prevents constructing this, and allows extending it in the future.
#[unstable(feature = "io_safety", issue = "87074")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NullHandleError(());
joshtriplett marked this conversation as resolved.
Show resolved Hide resolved

#[unstable(feature = "io_safety", issue = "87074")]
impl fmt::Display for NullHandleError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"A HandleOrNull could not be converted to a handle because it was null".fmt(fmt)
}
}

#[unstable(feature = "io_safety", issue = "87074")]
impl crate::error::Error for NullHandleError {}

/// This is the error type used by [`HandleOrInvalid`] when attempting to
/// convert into a handle, to indicate that the value is
/// `INVALID_HANDLE_VALUE`.
// The empty field prevents constructing this, and allows extending it in the future.
#[unstable(feature = "io_safety", issue = "87074")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InvalidHandleError(());
joshtriplett marked this conversation as resolved.
Show resolved Hide resolved

#[unstable(feature = "io_safety", issue = "87074")]
impl fmt::Display for InvalidHandleError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"A HandleOrInvalid could not be converted to a handle because it was INVALID_HANDLE_VALUE"
.fmt(fmt)
}
}

#[unstable(feature = "io_safety", issue = "87074")]
impl crate::error::Error for InvalidHandleError {}

impl AsRawHandle for BorrowedHandle<'_> {
#[inline]
fn as_raw_handle(&self) -> RawHandle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x
BorrowError
BorrowMutError
Box<T>
and 43 others
and 45 others
= note: required for the cast to the object type `dyn std::error::Error`

error[E0277]: the trait bound `(): std::error::Error` is not satisfied
Expand All @@ -31,7 +31,7 @@ LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
BorrowError
BorrowMutError
Box<T>
and 43 others
and 45 others
= note: required for the cast to the object type `(dyn std::error::Error + 'static)`

error: aborting due to 2 previous errors
Expand Down