diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7cb1a33d..124bb284 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -290,6 +290,7 @@ More specifically an error should - derive `Debug, Clone, PartialEq, Eq` (and `Copy` iff not `non_exhaustive`). - implement Display using `write_err!()` macro if a variant contains an inner error source. - have `Error` suffix +- call `internals::impl_from_infallible! - implement `std::error::Error` if they are public (feature gated on "std"). ```rust @@ -302,6 +303,9 @@ pub enum Error { /// Documentation for variant B. B, } + +internals::impl_from_infallible!(Error); + ``` diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock index 89b7982d..7e6c3026 100644 --- a/Cargo-minimal.lock +++ b/Cargo-minimal.lock @@ -12,6 +12,7 @@ checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" name = "base58check" version = "0.1.0" dependencies = [ + "bitcoin-internals", "bitcoin_hashes", "hex-conservative", ] diff --git a/Cargo-recent.lock b/Cargo-recent.lock index 29642168..196e597d 100644 --- a/Cargo-recent.lock +++ b/Cargo-recent.lock @@ -12,6 +12,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" name = "base58check" version = "0.1.0" dependencies = [ + "bitcoin-internals", "bitcoin_hashes", "hex-conservative", ] diff --git a/base58/Cargo.toml b/base58/Cargo.toml index d51fb5bd..7c294a5f 100644 --- a/base58/Cargo.toml +++ b/base58/Cargo.toml @@ -22,6 +22,7 @@ rustdoc-args = ["--cfg", "docsrs"] [dependencies] hashes = { package = "bitcoin_hashes", version = "0.13.0", default-features = false, features = ["alloc"] } +internals = { package = "bitcoin-internals", version = "0.2.0" } [dev-dependencies] hex = { package = "hex-conservative", version = "0.1.1", default-features = false, features = ["alloc"] } diff --git a/base58/src/lib.rs b/base58/src/lib.rs index a0aa04ca..f40e64e8 100644 --- a/base58/src/lib.rs +++ b/base58/src/lib.rs @@ -228,6 +228,8 @@ pub enum Error { TooShort(usize), } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; diff --git a/bitcoin/src/address/error.rs b/bitcoin/src/address/error.rs index a5be763e..ac0073d5 100644 --- a/bitcoin/src/address/error.rs +++ b/bitcoin/src/address/error.rs @@ -41,6 +41,8 @@ pub enum FromScriptError { WitnessVersion(witness_version::TryFromError), } +internals::impl_from_infallible!(FromScriptError); + impl fmt::Display for FromScriptError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use FromScriptError::*; @@ -82,6 +84,8 @@ pub enum P2shError { ExcessiveScriptSize, } +internals::impl_from_infallible!(P2shError); + impl fmt::Display for P2shError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use P2shError::*; @@ -135,6 +139,8 @@ pub enum ParseError { UnknownHrp(UnknownHrpError), } +internals::impl_from_infallible!(ParseError); + impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use ParseError::*; diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index 8c71a01f..db871dfa 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -28,6 +28,8 @@ pub enum Error { InvalidPrefill, } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs index ee9ea7c3..66bef777 100644 --- a/bitcoin/src/bip158.rs +++ b/bitcoin/src/bip158.rs @@ -77,6 +77,8 @@ pub enum Error { Io(io::Error), } +internals::impl_from_infallible!(Error); + impl Display for Error { fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { use Error::*; diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs index d18eb590..22242f12 100644 --- a/bitcoin/src/bip32.rs +++ b/bitcoin/src/bip32.rs @@ -491,6 +491,8 @@ pub enum Error { InvalidPublicKeyHexLength(usize), } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 66d7efa3..504813bf 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -420,6 +420,8 @@ pub enum Bip34Error { NegativeHeight, } +internals::impl_from_infallible!(Bip34Error); + impl fmt::Display for Bip34Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Bip34Error::*; @@ -456,6 +458,8 @@ pub enum ValidationError { BadTarget, } +internals::impl_from_infallible!(ValidationError); + impl fmt::Display for ValidationError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use ValidationError::*; diff --git a/bitcoin/src/blockdata/locktime/absolute.rs b/bitcoin/src/blockdata/locktime/absolute.rs index ec1451a0..6cb52c85 100644 --- a/bitcoin/src/blockdata/locktime/absolute.rs +++ b/bitcoin/src/blockdata/locktime/absolute.rs @@ -626,6 +626,8 @@ pub enum Error { Parse(ParseIntError), } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; @@ -723,6 +725,8 @@ pub enum OperationError { InvalidComparison, } +internals::impl_from_infallible!(OperationError); + impl fmt::Display for OperationError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use OperationError::*; @@ -754,6 +758,8 @@ enum ParseError { Conversion(i64), } +internals::impl_from_infallible!(ParseError); + impl ParseError { fn invalid_int>(s: S) -> impl FnOnce(core::num::ParseIntError) -> Self { move |source| Self::InvalidInteger { source, input: s.into() } diff --git a/bitcoin/src/blockdata/locktime/relative.rs b/bitcoin/src/blockdata/locktime/relative.rs index 8a0496cb..8127f0b6 100644 --- a/bitcoin/src/blockdata/locktime/relative.rs +++ b/bitcoin/src/blockdata/locktime/relative.rs @@ -282,6 +282,8 @@ pub enum Error { IncompatibleTime(LockTime, Time), } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs index 697ddbc2..d0662d99 100644 --- a/bitcoin/src/blockdata/script/mod.rs +++ b/bitcoin/src/blockdata/script/mod.rs @@ -699,6 +699,8 @@ pub enum Error { Serialization, } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; @@ -737,6 +739,8 @@ enum UintError { NumericOverflow, } +internals::impl_from_infallible!(UintError); + impl From for Error { fn from(error: UintError) -> Self { match error { diff --git a/bitcoin/src/blockdata/script/witness_program.rs b/bitcoin/src/blockdata/script/witness_program.rs index 7572c515..9b76becc 100644 --- a/bitcoin/src/blockdata/script/witness_program.rs +++ b/bitcoin/src/blockdata/script/witness_program.rs @@ -135,6 +135,8 @@ pub enum Error { InvalidSegwitV0Length(usize), } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; diff --git a/bitcoin/src/blockdata/script/witness_version.rs b/bitcoin/src/blockdata/script/witness_version.rs index 05ee2846..a172a60d 100644 --- a/bitcoin/src/blockdata/script/witness_version.rs +++ b/bitcoin/src/blockdata/script/witness_version.rs @@ -175,6 +175,8 @@ pub enum FromStrError { Invalid(TryFromError), } +internals::impl_from_infallible!(FromStrError); + impl fmt::Display for FromStrError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use FromStrError::*; @@ -216,6 +218,8 @@ pub enum TryFromInstructionError { DataPush, } +internals::impl_from_infallible!(TryFromInstructionError); + impl fmt::Display for TryFromInstructionError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use TryFromInstructionError::*; diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 94e3131a..f957e702 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -130,6 +130,8 @@ pub enum ParseOutPointError { VoutNotCanonical, } +internals::impl_from_infallible!(ParseOutPointError); + impl fmt::Display for ParseOutPointError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use ParseOutPointError::*; diff --git a/bitcoin/src/consensus/encode.rs b/bitcoin/src/consensus/encode.rs index 3fc036dd..fc5626b7 100644 --- a/bitcoin/src/consensus/encode.rs +++ b/bitcoin/src/consensus/encode.rs @@ -61,6 +61,8 @@ pub enum Error { UnsupportedSegwitFlag(u8), } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; diff --git a/bitcoin/src/consensus/serde.rs b/bitcoin/src/consensus/serde.rs index a6b88aed..eb5acfd4 100644 --- a/bitcoin/src/consensus/serde.rs +++ b/bitcoin/src/consensus/serde.rs @@ -368,6 +368,8 @@ enum DecodeError { Other(E), } +internals::impl_from_infallible!(DecodeError); + // not a trait impl because we panic on some variants fn consensus_error_into_serde(error: ConsensusError) -> E { match error { diff --git a/bitcoin/src/consensus/validation.rs b/bitcoin/src/consensus/validation.rs index e55a0bd0..32b5d5d0 100644 --- a/bitcoin/src/consensus/validation.rs +++ b/bitcoin/src/consensus/validation.rs @@ -209,6 +209,8 @@ pub enum TxVerifyError { UnknownSpentOutput(OutPoint), } +internals::impl_from_infallible!(TxVerifyError); + impl fmt::Display for TxVerifyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use TxVerifyError::*; diff --git a/bitcoin/src/crypto/ecdsa.rs b/bitcoin/src/crypto/ecdsa.rs index fd5cb4ae..4e1a8400 100644 --- a/bitcoin/src/crypto/ecdsa.rs +++ b/bitcoin/src/crypto/ecdsa.rs @@ -213,6 +213,8 @@ pub enum Error { Secp256k1(secp256k1::Error), } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index fd363813..48ac319c 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -896,6 +896,8 @@ pub enum FromSliceError { InvalidLength(usize), } +internals::impl_from_infallible!(FromSliceError); + impl fmt::Display for FromSliceError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use FromSliceError::*; @@ -934,6 +936,8 @@ pub enum FromWifError { Secp256k1(secp256k1::Error), } +internals::impl_from_infallible!(FromWifError); + impl fmt::Display for FromWifError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use FromWifError::*; @@ -974,6 +978,8 @@ pub enum ParsePublicKeyError { InvalidHexLength(usize), } +internals::impl_from_infallible!(ParsePublicKeyError); + impl fmt::Display for ParsePublicKeyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use ParsePublicKeyError::*; @@ -1010,6 +1016,8 @@ pub enum ParseCompressedPublicKeyError { Hex(hex::HexToArrayError), } +internals::impl_from_infallible!(ParseCompressedPublicKeyError); + impl fmt::Display for ParseCompressedPublicKeyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use ParseCompressedPublicKeyError::*; diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs index 197f3728..142a02ba 100644 --- a/bitcoin/src/crypto/sighash.rs +++ b/bitcoin/src/crypto/sighash.rs @@ -275,6 +275,8 @@ pub enum PrevoutsIndexError { InvalidAllIndex, } +internals::impl_from_infallible!(PrevoutsIndexError); + impl fmt::Display for PrevoutsIndexError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use PrevoutsIndexError::*; @@ -1151,6 +1153,8 @@ pub enum TaprootError { InvalidSighashType(u32), } +internals::impl_from_infallible!(TaprootError); + impl fmt::Display for TaprootError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use TaprootError::*; @@ -1208,6 +1212,8 @@ pub enum P2wpkhError { NotP2wpkhScript, } +internals::impl_from_infallible!(P2wpkhError); + impl From for P2wpkhError { fn from(value: transaction::InputsIndexError) -> Self { P2wpkhError::Sighash(value) @@ -1273,6 +1279,8 @@ pub enum AnnexError { IncorrectPrefix(u8), } +internals::impl_from_infallible!(AnnexError); + impl fmt::Display for AnnexError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use AnnexError::*; @@ -1379,6 +1387,8 @@ pub enum SigningDataError { Sighash(E), } +internals::impl_from_infallible!(SigningDataError); + impl SigningDataError { /// Returns the sighash variant, panicking if it's IO. /// diff --git a/bitcoin/src/crypto/taproot.rs b/bitcoin/src/crypto/taproot.rs index fb941e7c..dee10f78 100644 --- a/bitcoin/src/crypto/taproot.rs +++ b/bitcoin/src/crypto/taproot.rs @@ -97,6 +97,8 @@ pub enum SigFromSliceError { InvalidSignatureSize(usize), } +internals::impl_from_infallible!(SigFromSliceError); + impl fmt::Display for SigFromSliceError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use SigFromSliceError::*; diff --git a/bitcoin/src/merkle_tree/block.rs b/bitcoin/src/merkle_tree/block.rs index 8df17f2b..563966d7 100644 --- a/bitcoin/src/merkle_tree/block.rs +++ b/bitcoin/src/merkle_tree/block.rs @@ -498,6 +498,8 @@ pub enum MerkleBlockError { IdenticalHashesFound, } +internals::impl_from_infallible!(MerkleBlockError); + impl fmt::Display for MerkleBlockError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use MerkleBlockError::*; diff --git a/bitcoin/src/psbt/error.rs b/bitcoin/src/psbt/error.rs index 64f0faa5..d0e3cdea 100644 --- a/bitcoin/src/psbt/error.rs +++ b/bitcoin/src/psbt/error.rs @@ -103,6 +103,8 @@ pub enum Error { Io(io::Error), } +internals::impl_from_infallible!(Error); + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index 29a99f2c..d14e186a 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -675,6 +675,8 @@ pub enum GetKeyError { NotSupported, } +internals::impl_from_infallible!(GetKeyError); + impl fmt::Display for GetKeyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use GetKeyError::*; @@ -784,6 +786,8 @@ pub enum SignError { Unsupported, } +internals::impl_from_infallible!(SignError); + impl fmt::Display for SignError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use SignError::*; @@ -865,6 +869,8 @@ pub enum ExtractTxError { }, } +internals::impl_from_infallible!(ExtractTxError); + impl fmt::Display for ExtractTxError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use ExtractTxError::*; @@ -915,6 +921,8 @@ pub enum IndexOutOfBoundsError { }, } +internals::impl_from_infallible!(IndexOutOfBoundsError); + impl fmt::Display for IndexOutOfBoundsError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use IndexOutOfBoundsError::*; @@ -966,6 +974,8 @@ mod display_from_str { Base64Encoding(::base64::DecodeError), } + internals::impl_from_infallible!(PsbtParseError); + impl Display for PsbtParseError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { use self::PsbtParseError::*; diff --git a/bitcoin/src/sign_message.rs b/bitcoin/src/sign_message.rs index f907a7a7..b8232dab 100644 --- a/bitcoin/src/sign_message.rs +++ b/bitcoin/src/sign_message.rs @@ -43,6 +43,8 @@ mod message_signing { UnsupportedAddressType(AddressType), } + internals::impl_from_infallible!(MessageSignatureError); + impl fmt::Display for MessageSignatureError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use MessageSignatureError::*; diff --git a/bitcoin/src/taproot/mod.rs b/bitcoin/src/taproot/mod.rs index 9c87218f..a84d1620 100644 --- a/bitcoin/src/taproot/mod.rs +++ b/bitcoin/src/taproot/mod.rs @@ -587,6 +587,8 @@ pub enum IncompleteBuilderError { HiddenParts(TaprootBuilder), } +internals::impl_from_infallible!(IncompleteBuilderError); + impl IncompleteBuilderError { /// Converts error into the original incomplete [`TaprootBuilder`] instance. pub fn into_builder(self) -> TaprootBuilder { @@ -631,6 +633,8 @@ pub enum HiddenNodesError { HiddenParts(NodeInfo), } +internals::impl_from_infallible!(HiddenNodesError); + impl HiddenNodesError { /// Converts error into the original incomplete [`NodeInfo`] instance. pub fn into_node_info(self) -> NodeInfo { @@ -1324,6 +1328,8 @@ pub enum TaprootBuilderError { EmptyTree, } +internals::impl_from_infallible!(TaprootBuilderError); + impl fmt::Display for TaprootBuilderError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use TaprootBuilderError::*; @@ -1384,6 +1390,8 @@ pub enum TaprootError { EmptyTree, } +internals::impl_from_infallible!(TaprootError); + impl fmt::Display for TaprootError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use TaprootError::*; diff --git a/internals/src/macros.rs b/internals/src/macros.rs index 91e60a1c..8e69335b 100644 --- a/internals/src/macros.rs +++ b/internals/src/macros.rs @@ -113,3 +113,59 @@ macro_rules! const_assert { const _: [(); 0 - !$x as usize] = []; }}; } + +/// Derives `From` for the given type. +/// +/// Supports types with arbitrary combinations of lifetimes and type parameters. +/// +/// Note: Paths are not supported (for ex. impl_from_infallible!(Hello). +/// +/// ## Examples +/// +/// ```rust +/// # use core::fmt::{Display, Debug}; +/// use bitcoin_internals::impl_from_infallible; +/// +/// enum AlphaEnum { Item } +/// impl_from_infallible!(AlphaEnum); +/// +/// enum BetaEnum<'b> { Item(&'b usize) } +/// impl_from_infallible!(BetaEnum<'b>); +/// +/// enum GammaEnum { Item(T) }; +/// impl_from_infallible!(GammaEnum); +/// +/// enum DeltaEnum<'b, 'a: 'static + 'b, T: 'a, D: Debug + Display + 'a> { +/// Item((&'b usize, &'a usize, T, D)) +/// } +/// impl_from_infallible!(DeltaEnum<'b, 'a: 'static + 'b, T: 'a, D: Debug + Display + 'a>); +/// +/// struct AlphaStruct; +/// impl_from_infallible!(AlphaStruct); +/// +/// struct BetaStruct<'b>(&'b usize); +/// impl_from_infallible!(BetaStruct<'b>); +/// +/// struct GammaStruct(T); +/// impl_from_infallible!(GammaStruct); +/// +/// struct DeltaStruct<'b, 'a: 'static + 'b, T: 'a, D: Debug + Display + 'a> { +/// hello: &'a T, +/// what: &'b D, +/// } +/// impl_from_infallible!(DeltaStruct<'b, 'a: 'static + 'b, T: 'a, D: Debug + Display + 'a>); +/// ``` +/// +/// See for more information about this macro. +#[macro_export] +macro_rules! impl_from_infallible { + ( $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ) => { + impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? + From + for $name + $(< $( $lt ),+ >)? + { + fn from(never: core::convert::Infallible) -> Self { match never {} } + } + } +} diff --git a/io/src/error.rs b/io/src/error.rs index 0218de5a..5e5e12d1 100644 --- a/io/src/error.rs +++ b/io/src/error.rs @@ -116,6 +116,10 @@ macro_rules! define_errorkind { ),* } + impl From for ErrorKind { + fn from(never: core::convert::Infallible) -> Self { match never {} } + } + impl ErrorKind { fn description(&self) -> &'static str { match self { diff --git a/units/src/amount.rs b/units/src/amount.rs index 21c1b713..268ee6ca 100644 --- a/units/src/amount.rs +++ b/units/src/amount.rs @@ -161,6 +161,8 @@ pub enum ParseError { MissingDenomination(MissingDenominationError), } +internals::impl_from_infallible!(ParseError); + impl From for ParseError { fn from(e: ParseAmountError) -> Self { Self::Amount(e) } } @@ -255,6 +257,8 @@ impl From for ParseAmountError { } } +internals::impl_from_infallible!(ParseAmountError); + impl fmt::Display for ParseAmountError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use ParseAmountError::*; @@ -447,6 +451,8 @@ pub enum ParseDenominationError { PossiblyConfusing(PossiblyConfusingDenominationError), } +internals::impl_from_infallible!(ParseDenominationError); + impl fmt::Display for ParseDenominationError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use ParseDenominationError::*; @@ -621,6 +627,8 @@ enum InnerParseError { InvalidCharacter(InvalidCharacterError), } +internals::impl_from_infallible!(InnerParseError); + impl InnerParseError { fn convert(self, is_signed: bool) -> ParseAmountError { match self {