What changed, and why it matters
This commit is a routine cleanup in the Rust Bitcoin library. It stops exporting a few internal helper macros that were already marked as hidden from documentation. The macros are still used inside the crate, just not made available to outside users. There is no security bug being fixed here.
No security action needed. Treat as normal maintenance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change removes #[macro_export] from three doc-hidden macros in units/src/parse.rs (impl_parse_str_from_int_infallible, impl_parse_str, impl_tryfrom_str) and re-exports them as pub(crate) instead. Callers within the units crate are updated from crate:: to parse:: paths. This is an API-visibility cleanup, not a patch for a vulnerability.
Changed components
units/src/parse.rsunits/src/block.rsunits/src/locktime/absolute/mod.rsunits/src/locktime/relative/mod.rsunits/src/sequence.rsunits/src/weight.rsInspect captured patch +19 / −18
diff --git a/units/CHANGELOG.md b/units/CHANGELOG.md
index 318c4942..a84692e4 100644
--- a/units/CHANGELOG.md
+++ b/units/CHANGELOG.md
@@ -1,3 +1,7 @@
+# Unreleased
+
+- Do not re-export doc hidden macros
+
# 1.0.0 - 2025-02-24
BOOM! A long time in the making but here goes, our first 1.0 crate release.
diff --git a/units/src/block.rs b/units/src/block.rs
index eb8854d2..be206550 100644
--- a/units/src/block.rs
+++ b/units/src/block.rs
@@ -34,7 +34,7 @@ macro_rules! impl_u32_wrapper {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
- crate::impl_parse_str_from_int_infallible!($newtype, u32, from);
+ crate::parse::impl_parse_str_from_int_infallible!($newtype, u32, from);
impl From<u32> for $newtype {
fn from(inner: u32) -> Self { Self::from_u32(inner) }
diff --git a/units/src/locktime/absolute/mod.rs b/units/src/locktime/absolute/mod.rs
index 65e10c64..f1a6fa27 100644
--- a/units/src/locktime/absolute/mod.rs
+++ b/units/src/locktime/absolute/mod.rs
@@ -399,7 +399,7 @@ impl LockTime {
}
}
-crate::impl_parse_str_from_int_infallible!(LockTime, u32, from_consensus);
+parse::impl_parse_str_from_int_infallible!(LockTime, u32, from_consensus);
impl From<Height> for LockTime {
#[inline]
@@ -546,7 +546,7 @@ impl fmt::Display for Height {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
-crate::impl_parse_str!(Height, ParseHeightError, parser(Height::from_u32));
+parse::impl_parse_str!(Height, ParseHeightError, parser(Height::from_u32));
#[deprecated(since = "TBD", note = "use `MedianTimePast` instead")]
#[doc(hidden)]
@@ -661,7 +661,7 @@ impl fmt::Display for MedianTimePast {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
-crate::impl_parse_str!(MedianTimePast, ParseTimeError, parser(MedianTimePast::from_u32));
+parse::impl_parse_str!(MedianTimePast, ParseTimeError, parser(MedianTimePast::from_u32));
fn parser<T, E, S, F>(f: F) -> impl FnOnce(S) -> Result<T, E>
where
diff --git a/units/src/locktime/relative/mod.rs b/units/src/locktime/relative/mod.rs
index c5fcecf5..ef348022 100644
--- a/units/src/locktime/relative/mod.rs
+++ b/units/src/locktime/relative/mod.rs
@@ -16,7 +16,7 @@ use internals::const_casts;
#[cfg(doc)]
use crate::relative;
-use crate::{BlockHeight, BlockMtp, Sequence};
+use crate::{parse, BlockHeight, BlockMtp, Sequence};
#[rustfmt::skip] // Keep public re-exports separate.
#[doc(no_inline)]
@@ -473,7 +473,7 @@ impl From<u16> for NumberOfBlocks {
fn from(value: u16) -> Self { NumberOfBlocks(value) }
}
-crate::impl_parse_str_from_int_infallible!(NumberOfBlocks, u16, from);
+parse::impl_parse_str_from_int_infallible!(NumberOfBlocks, u16, from);
impl fmt::Display for NumberOfBlocks {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
@@ -587,7 +587,7 @@ impl NumberOf512Seconds {
}
}
-crate::impl_parse_str_from_int_infallible!(NumberOf512Seconds, u16, from_512_second_intervals);
+parse::impl_parse_str_from_int_infallible!(NumberOf512Seconds, u16, from_512_second_intervals);
impl fmt::Display for NumberOf512Seconds {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
diff --git a/units/src/parse.rs b/units/src/parse.rs
index c0e0e848..ed33890e 100644
--- a/units/src/parse.rs
+++ b/units/src/parse.rs
@@ -148,8 +148,6 @@ fn int<T: Integer, S: AsRef<str> + Into<InputString>>(s: S) -> Result<T, ParseIn
/// # Errors
///
/// If parsing the string fails then a `units::parse::ParseIntError` is returned.
-#[macro_export]
-#[doc(hidden)] // This macro is stable but is considered internal to the `rust-bitcoin` repository.
macro_rules! impl_parse_str_from_int_infallible {
($to:ident, $inner:ident, $fn:ident) => {
impl $crate::_export::_core::str::FromStr for $to {
@@ -191,6 +189,7 @@ macro_rules! impl_parse_str_from_int_infallible {
}
};
}
+pub(crate) use impl_parse_str_from_int_infallible;
/// Implements standard parsing traits for `$type` by calling through to `$inner_fn`.
///
@@ -213,13 +212,11 @@ macro_rules! impl_parse_str_from_int_infallible {
/// # Errors
///
/// All functions use the error returned by `$inner_fn`.
-#[macro_export]
-#[doc(hidden)] // This macro is stable but is considered internal to the `rust-bitcoin` repository.
macro_rules! impl_parse_str {
($to:ty, $err:ty, $inner_fn:expr) => {
- $crate::impl_tryfrom_str!(&str, $to, $err, $inner_fn);
+ $crate::parse::impl_tryfrom_str!(&str, $to, $err, $inner_fn);
#[cfg(feature = "alloc")]
- $crate::impl_tryfrom_str!(alloc::string::String, $to, $err, $inner_fn; alloc::boxed::Box<str>, $to, $err, $inner_fn);
+ $crate::parse::impl_tryfrom_str!(alloc::string::String, $to, $err, $inner_fn; alloc::boxed::Box<str>, $to, $err, $inner_fn);
impl $crate::_export::_core::str::FromStr for $to {
type Err = $err;
@@ -230,10 +227,9 @@ macro_rules! impl_parse_str {
}
}
}
+pub(crate) use impl_parse_str;
/// Implements `TryFrom<$from> for $to`.
-#[macro_export]
-#[doc(hidden)] // Helper macro called by `impl_parse_str`.
macro_rules! impl_tryfrom_str {
($($from:ty, $to:ty, $err:ty, $inner_fn:expr);*) => {
$(
@@ -247,6 +243,7 @@ macro_rules! impl_tryfrom_str {
)*
}
}
+pub(crate) use impl_tryfrom_str;
/// Removes the prefix `0x` (or `0X`) from a hex string.
///
diff --git a/units/src/sequence.rs b/units/src/sequence.rs
index b6fe5709..5aba6829 100644
--- a/units/src/sequence.rs
+++ b/units/src/sequence.rs
@@ -262,7 +262,7 @@ impl fmt::Debug for Sequence {
}
#[cfg(feature = "alloc")]
-crate::impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus);
+parse::impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus);
#[cfg(feature = "arbitrary")]
#[cfg(feature = "alloc")]
diff --git a/units/src/weight.rs b/units/src/weight.rs
index 2c23c73e..3fa4852f 100644
--- a/units/src/weight.rs
+++ b/units/src/weight.rs
@@ -10,7 +10,7 @@ use arbitrary::{Arbitrary, Unstructured};
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
-use crate::{Amount, FeeRate, NumOpResult};
+use crate::{parse, Amount, FeeRate, NumOpResult};
/// The factor that non-witness serialization data is multiplied by during weight calculation.
pub const WITNESS_SCALE_FACTOR: usize = 4;
@@ -271,7 +271,7 @@ impl<'a> core::iter::Sum<&'a Weight> for Weight {
}
}
-crate::impl_parse_str_from_int_infallible!(Weight, u64, from_wu);
+parse::impl_parse_str_from_int_infallible!(Weight, u64, from_wu);
#[cfg(feature = "serde")]
impl Serialize for Weight {
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.