Skip to content

MBE (macro_rules!) pattern-matching is unnecessarily O(n) even in simple cases. #68836

Open
@eddyb

Description

@eddyb

There are some crates which do something like this (e.g. string_cache_codegen):

macro_rules! foo {
    ("a") => (A);
    ("b") => (B);
    ("c") => (C);
    // ... etc. (maybe hundreds more)
}

(@nnethercote came across this when profiling html5ever's compilation)

Also, prefixing patterns with @foo to create "internal rules" is common.

But the current implementation (AFAICT) has to check each of the patterns in turn.

Instead, we could build something like a decision tree ahead of time, from the constant (i.e. $-less) prefix of all arms, using maps for operators/idents/literals, to make the pattern-matching of the prefix amortize to being linear in the number of input tokens.

We could keep it simple by limiting the constant prefix to leaf tokens (no (...), [...] or {...}).

For the example above, we'd pre-compute something like this:

DecisionTree::Match {
    op: {},
    ident: {},
    literal: {
        "a": DecisionTree::Done([0]),
        "b": DecisionTree::Done([1]),
        "c": DecisionTree::Done([2]),
        // ...
    },
}

Whereas for something using @foo rules it could be:

DecisionTree::Match {
    op: {
        '@': DecisionTree::Match {
            op: {},
            ident: {
                "foo": DecisionTree::Done([0, 1]),
                "bar": DecisionTree::Done([2, 3, 4]),
                "baz": DecisionTree::Done([5]),
            },
            literal: {},
        }
    },
    ident: {},
    literal: {},
}

(where DecisionTree::Done indicates the arms to continue with)

cc @rust-lang/compiler (this might need a design meeting?)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-enhancementCategory: An issue proposing an enhancement or a PR with one.I-compiletimeIssue: Problems and improvements with respect to compile times.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions