From 48b10feedbee5b8554fa82696ce5e836933f189c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Nov 2022 11:24:21 +1100 Subject: [PATCH] Split `MacArgs` in two. `MacArgs` is an enum with three variants: `Empty`, `Delimited`, and `Eq`. It's used in two ways: - For representing attribute macro arguments (e.g. in `AttrItem`), where all three variants are used. - For representing function-like macros (e.g. in `MacCall` and `MacroDef`), where only the `Delimited` variant is used. In other words, `MacArgs` is used in two quite different places due to them having partial overlap. I find this makes the code hard to read. It also leads to various unreachable code paths, and allows invalid values (such as accidentally using `MacArgs::Empty` in a `MacCall`). This commit splits `MacArgs` in two: - `DelimArgs` is a new struct just for the "delimited arguments" case. It is now used in `MacCall` and `MacroDef`. - `AttrArgs` is a renaming of the old `MacArgs` enum for the attribute macro case. Its `Delimited` variant now contains a `DelimArgs`. Various other related things are renamed as well. These changes make the code clearer, avoids several unreachable paths, and disallows the invalid values. --- clippy_lints/src/crate_in_macro_def.rs | 2 +- clippy_utils/src/ast_utils.rs | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index 20cc330e0..b2fe0386f 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/clippy_lints/src/crate_in_macro_def.rs @@ -55,7 +55,7 @@ impl EarlyLintPass for CrateInMacroDef { if_chain! { if item.attrs.iter().any(is_macro_export); if let ItemKind::MacroDef(macro_def) = &item.kind; - let tts = macro_def.body.inner_tokens(); + let tts = macro_def.body.tokens.clone(); if let Some(span) = contains_unhygienic_crate_reference(&tts); then { span_lint_and_sugg( diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 23aed4b5b..87b378bfd 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -388,7 +388,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) }, (MacCall(l), MacCall(r)) => eq_mac_call(l, r), - (MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_mac_args(&l.body, &r.body), + (MacroDef(l), MacroDef(r)) => l.macro_rules == r.macro_rules && eq_delim_args(&l.body, &r.body), _ => false, } } @@ -709,7 +709,7 @@ pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool { } pub fn eq_mac_call(l: &MacCall, r: &MacCall) -> bool { - eq_path(&l.path, &r.path) && eq_mac_args(&l.args, &r.args) + eq_path(&l.path, &r.path) && eq_delim_args(&l.args, &r.args) } pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool { @@ -717,18 +717,22 @@ pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool { l.style == r.style && match (&l.kind, &r.kind) { (DocComment(l1, l2), DocComment(r1, r2)) => l1 == r1 && l2 == r2, - (Normal(l), Normal(r)) => eq_path(&l.item.path, &r.item.path) && eq_mac_args(&l.item.args, &r.item.args), + (Normal(l), Normal(r)) => eq_path(&l.item.path, &r.item.path) && eq_attr_args(&l.item.args, &r.item.args), _ => false, } } -pub fn eq_mac_args(l: &MacArgs, r: &MacArgs) -> bool { - use MacArgs::*; +pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool { + use AttrArgs::*; match (l, r) { (Empty, Empty) => true, - (Delimited(_, ld, lts), Delimited(_, rd, rts)) => ld == rd && lts.eq_unspanned(rts), - (Eq(_, MacArgsEq::Ast(le)), Eq(_, MacArgsEq::Ast(re))) => eq_expr(le, re), - (Eq(_, MacArgsEq::Hir(ll)), Eq(_, MacArgsEq::Hir(rl))) => ll.kind == rl.kind, + (Delimited(la), Delimited(ra)) => eq_delim_args(la, ra), + (Eq(_, AttrArgsEq::Ast(le)), Eq(_, AttrArgsEq::Ast(re))) => eq_expr(le, re), + (Eq(_, AttrArgsEq::Hir(ll)), Eq(_, AttrArgsEq::Hir(rl))) => ll.kind == rl.kind, _ => false, } } + +pub fn eq_delim_args(l: &DelimArgs, r: &DelimArgs) -> bool { + l.delim == r.delim && l.tokens.eq_unspanned(&r.tokens) +}