Skip to content

Commit cdfbf14

Browse files
authored
Rollup merge of rust-lang#59600 - tobia:master, r=pnkfelix
Replaced linear token counting macros with optimized implementation There are currently two distinct token-counting macros in the source. Both implement the trivial algorithm, with linear complexity. They may or may not be adequate for their use case, but considering that other people are probably going to copy and paste them whenever they need a token-counting macro, I replaced them with an optimized implementation with logarithmic complexity.
2 parents 5d4aef6 + a4a07e0 commit cdfbf14

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

src/librustc/hir/map/definitions.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -582,9 +582,17 @@ impl DefPathData {
582582
}
583583
}
584584

585+
/// Evaluates to the number of tokens passed to it.
586+
///
587+
/// Logarithmic counting: every one or two recursive expansions, the number of
588+
/// tokens to count is divided by two, instead of being reduced by one.
589+
/// Therefore, the recursion depth is the binary logarithm of the number of
590+
/// tokens to count, and the expanded tree is likewise very small.
585591
macro_rules! count {
586-
() => (0usize);
587-
( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
592+
() => (0usize);
593+
($one:tt) => (1usize);
594+
($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize);
595+
($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize);
588596
}
589597

590598
// We define the GlobalMetaDataKind enum with this macro because we want to

src/libserialize/serialize.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -723,10 +723,17 @@ macro_rules! peel {
723723
($name:ident, $($other:ident,)*) => (tuple! { $($other,)* })
724724
}
725725

726-
/// Evaluates to the number of identifiers passed to it, for example: `count_idents!(a, b, c) == 3
727-
macro_rules! count_idents {
728-
() => { 0 };
729-
($_i:ident, $($rest:ident,)*) => { 1 + count_idents!($($rest,)*) }
726+
/// Evaluates to the number of tokens passed to it.
727+
///
728+
/// Logarithmic counting: every one or two recursive expansions, the number of
729+
/// tokens to count is divided by two, instead of being reduced by one.
730+
/// Therefore, the recursion depth is the binary logarithm of the number of
731+
/// tokens to count, and the expanded tree is likewise very small.
732+
macro_rules! count {
733+
() => (0usize);
734+
($one:tt) => (1usize);
735+
($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize);
736+
($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize);
730737
}
731738

732739
macro_rules! tuple {
@@ -735,7 +742,7 @@ macro_rules! tuple {
735742
impl<$($name:Decodable),*> Decodable for ($($name,)*) {
736743
#[allow(non_snake_case)]
737744
fn decode<D: Decoder>(d: &mut D) -> Result<($($name,)*), D::Error> {
738-
let len: usize = count_idents!($($name,)*);
745+
let len: usize = count!($($name)*);
739746
d.read_tuple(len, |d| {
740747
let mut i = 0;
741748
let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name, D::Error> {

0 commit comments

Comments
 (0)