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}