expandable_impl/
error.rs

1// Architectural invariant: this module contains types that are useful for error
2// reporting and nothing else.
3
4use crate::{RepetitionQuantifierKind, Terminal, grammar::TokenDescription};
5
6/// An error that is generated when checking an incorrect macro.
7///
8/// This enum allows crate users to handle and report errors detected by
9/// [`check_macro`].
10///
11/// Everything in this enum in marked as `non_exhaustive`, in order to partially
12/// mitigate future variant additions.
13///
14/// [`check_macro`]: crate::check_macro
15#[derive(Debug)]
16#[non_exhaustive]
17pub enum Error<Span> {
18    /// Generated when the macro definition itself doesn't parse correctly.
19    ///
20    /// The Rust compiler is likely to emit an error anyway. Below is an
21    /// example of code that triggers this error:
22    ///
23    /// ```rust,compile_fail
24    /// macro_rules! blatant_error {
25    ///     () => =>;
26    ///     //    |
27    ///     //    error: macro rhs must be delimited.
28    /// }
29    /// ```
30    ///
31    /// This prevents us from doing any analyses.
32    #[non_exhaustive]
33    ParsingFailed {
34        /// What was expected.
35        what: Vec<MacroRuleNode>,
36        /// Where it was expected.
37        where_: Span,
38    },
39
40    /// An EOF was reached when it was not expected.
41    #[non_exhaustive]
42    UnexpectedEnd {
43        /// The position the parser was at when it reached EOF.
44        last_token: Option<Span>,
45    },
46
47    /// The macro may expand to invalid AST.
48    ///
49    /// This variant is very minimal for now. We may add more information to
50    /// it in the future. Please open an issue if you have opinions on what
51    /// to add!
52    #[non_exhaustive]
53    InvalidProducedAst {
54        /// Where the error happens.
55        span: Span,
56        /// What tokens are expected here.
57        expected: Vec<TokenDescription>,
58        /// A possible expansion of the macro that exhibits a parsing error.
59        ///
60        /// The expansion may contain fragments.
61        counter_example: Vec<(TokenDescription, Span)>,
62    },
63
64    /// A macro expansion refers to a metavariable that is not defined in the
65    /// macro match arm.
66    ///
67    /// If you ever hit this error on a macro that works, then please file an
68    /// issue.
69    #[non_exhaustive]
70    UnboundMetavariable {
71        /// The name of the metavariable that was used.
72        name: String,
73        /// Where it was used.
74        where_: Span,
75    },
76
77    /// A variable is being repeated with a sequence of operator that does not
78    /// match the one used when the variable was declared.
79    ///
80    /// # Example
81    ///
82    /// ```rust,compile_fail
83    /// macro_rules! subtraction {
84    ///     ( $( $first:literal $( - $then:literal )* )? ) => {
85    ///         $first $( - $then )*
86    ///     };
87    /// }
88    ///
89    /// subtraction!(101 - 42);
90    /// ```
91    ///
92    /// In this example, the repetition nesting of the matched metavariable
93    /// `then` is `?*`, while the nesting of the metavariable indication
94    /// `then` is `*`.
95    ///
96    /// This variant represents both the case where the amount of repetitions
97    /// does not match (which is an error) and the case where the repetition
98    /// operators used do not match (which is allowed, but can lead to confusing
99    /// errors).
100    InvalidRepetitionNesting {
101        /// The name of the metavariable.
102        metavariable_name: String,
103        /// Where the metavariable was declared.
104        decl_span: Span,
105        /// Where the metavariable was used with an incorrect nesting.
106        usage_span: Span,
107        /// The nesting used when the metavariable was declared.
108        expected_nesting: Vec<RepetitionQuantifierKind>,
109        /// The nesting encountered when the metavariable was used.
110        got_nesting: Vec<RepetitionQuantifierKind>,
111    },
112}
113
114/// Various nodes that can be expected in a `macro_rules!` invocation.
115#[derive(Clone, Debug, PartialEq)]
116#[non_exhaustive]
117pub enum MacroRuleNode {
118    /// A matcher (everything that comes _before_ the `=>` of a macro rule.
119    Matcher,
120    /// A transcriber (everything that comes _after_ the `=>` of a macro rule.
121    Transcriber,
122    /// A repetition.
123    Repetition,
124    /// A fragment name.
125    FragmentName,
126    /// A fragment type specifier (`ident`, `expr`, ...).
127    FragmentSpecifier,
128    /// A meta variable match, such as `$a:ident`.
129    MetaVariableMatch,
130    /// A repetition quantifier (`?`, `*`, `+`).
131    RepetitionQuantifier,
132    /// A repetition separator (the `,` in `$( $expr ),*`).
133    RepetitionSeparator,
134    /// Any terminal.
135    Terminal(Terminal),
136}