Skip to content
Merged
Changes from 1 commit
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
38 changes: 27 additions & 11 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
//! Module with hacks for creating error variants for standard library errors
//! without public interfaces.
//! Module with safe helpers for creating error variants for standard library
//! errors without public constructors.

use core::{
mem,
num::{IntErrorKind, ParseIntError, TryFromIntError},
};
use core::num::{IntErrorKind, ParseIntError, TryFromIntError};

/// Returns a `ParseIntError` from an `IntErrorKind`.
pub const fn pie(kind: IntErrorKind) -> ParseIntError {
unsafe { mem::transmute(kind) }
/// Returns a `ParseIntError` with the specified `IntErrorKind`.
pub fn pie(kind: IntErrorKind) -> ParseIntError {
match kind {
IntErrorKind::Empty => u8_parse_error(""),
IntErrorKind::InvalidDigit => u8_parse_error("?"),
IntErrorKind::PosOverflow => u8_parse_error("256"),
IntErrorKind::NegOverflow => i8_parse_error("-129"),
IntErrorKind::Zero => zero_parse_error(),

@nlordell nlordell Apr 19, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Zero is only used in the test below, so it can be removed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed. Also dropped the NonZeroU32 import that was only there for the Zero test.

_ => u8_parse_error("?"), // fallback for future variants

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be unreachable!() IMO - the input kind is limited to the uses of this function internal to the library, so we know that this branch will never be reached.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, switched to unreachable\!().

}
}

fn u8_parse_error(s: &str) -> ParseIntError {
s.parse::<u8>().unwrap_err()
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use https://doc.rust-lang.org/stable/std/primitive.u8.html#method.from_str_radix, then the function can stay const:

const fn u8_parse_error(s: &str) -> std::num::ParseIntError {
    let Err(err) = u8::from_str_radix(s, 10) else {
        panic!("not a parse error!");
    };
    err
}

fn main() {
    let x = u8_parse_error("-1");
    println!("{x:?}!");
}

Same for the i8_parse_error function, (allowing pie to stay const).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, from_str_radix works perfectly here. pie() and the helpers are const fn again. tfie() stays non-const since TryFrom is not const-stable yet, but no call site needs it in const context anyway.


fn i8_parse_error(s: &str) -> ParseIntError {
s.parse::<i8>().unwrap_err()
}

fn zero_parse_error() -> ParseIntError {
"0".parse::<core::num::NonZeroU8>().unwrap_err()
}

/// Returns a `TryFromIntError`.
pub const fn tfie() -> TryFromIntError {
unsafe { mem::transmute(()) }
pub fn tfie() -> TryFromIntError {
u8::try_from(-1i8).unwrap_err()
}

#[cfg(test)]
Expand Down