Skip to content

Commit

Permalink
Rollup merge of rust-lang#59600 - tobia:master, r=pnkfelix
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Centril committed Jun 10, 2019
2 parents 1cbd8a4 + a4a07e0 commit 97df867
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 7 deletions.
12 changes: 10 additions & 2 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,9 +582,17 @@ impl DefPathData {
}
}

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

// We define the GlobalMetaDataKind enum with this macro because we want to
Expand Down
17 changes: 12 additions & 5 deletions src/libserialize/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,10 +723,17 @@ macro_rules! peel {
($name:ident, $($other:ident,)*) => (tuple! { $($other,)* })
}

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

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

0 comments on commit 97df867

Please sign in to comment.