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