Repository: rust
Issue: `-Zmacro-backtrace` gets confused when macros define other macros
Labels: A-diagnostics,A-macros,T-compiler,E-needs-mcve

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=49b4f59c6307c22b5f5705f3bbf48205

<details>

```rust
#![crate_type = "lib"]

macro_rules! define_state_group {
    ( $name:ident = { $($states:tt)+ } ) => {
        macro_rules! $name {
            () => {
                state!($($states)+);
            };
        }
    };
}

macro_rules! state {
    (
        $name:ident $(<-- ( $($enter_actions:tt)* ))* {
            $($arms:tt)*
        }

        $($rest:tt)*
    ) => {
        fn $name(&mut self, input: &[u8]) -> StateResult {
            loop {
                let ch = self.consume_ch(input);

                state_body!(|[self, input, ch]|> [$($arms)*], [$($($enter_actions)*)*]);
            }
        }

        state!($($rest)*);
    };

    // NOTE: end of the state list
    () => ();
}

macro_rules! state_body {
    ( | [ $self:tt, $input:ident, $ch:ident ] |> [$($arms:tt)+], [$($enter_actions:tt)*] ) => {
        action_list!(@state_enter |$self, $input|> $($enter_actions)*);
        state_body!(@map_arms | [$self, $input, $ch] |> [$($arms)+], [])
    };


    // Recursively expand each arm's pattern
    //--------------------------------------------------------------------
    ( @map_arms
        | $scope_vars:tt |>
        [ $pat:tt => ( $($actions:tt)* ) $($rest:tt)* ], [ $($expanded:tt)* ]
    ) => {
        arm_pattern!(|[ $scope_vars, [$($rest)*], [$($expanded)*] ]|> $pat => ( $($actions)* ))
    };

    ( @map_arms
        | $scope_vars:tt |>
        [], [$($expanded:tt)*]
    ) => {
        state_body!(@match_block |$scope_vars|> $($expanded)*);
    };


    // Callback for the expand_arm_pattern
    //--------------------------------------------------------------------
    ( @callback
        | [ $scope_vars:tt, [$($pending:tt)*], [$($expanded:tt)*] ] |>
        $($expanded_arm:tt)*
    ) => {
        state_body!(@map_arms | $scope_vars |> [$($pending)*], [$($expanded)* $($expanded_arm)*])
    };


    // Character match block
    //--------------------------------------------------------------------
    ( @match_block
        | [ $self:tt, $input:ident, $ch:ident ] |>
        $( $pat:pat $(|$pat_cont:pat)* $(if $pat_expr:expr)* => ( $($actions:tt)* ) )*
    ) => {
        // NOTE: guard against unreachable patterns
        // (e.g. such may occur if `eof => ...` arm comes before `eoc => ...` arm.)
        #[deny(unreachable_patterns)]
        match $ch {
            $(
                $pat $(| $pat_cont)* $(if $pat_expr)* => {
                    action_list!(|$self, $input|> $($actions)*);
                }
            )*
        }
    };
}

macro_rules! action_list {
    ( | $self:tt, $input:ident |>
        if $cond:ident
            ( $($if_actions:tt)* )
        else
            ( $($else_actions:tt)* )
    ) => {
        if $self.$cond() {
            action_list!(| $self, $input |> $($if_actions)*);
        } else {
            action_list!(| $self, $input |> $($else_actions)*);
        }
    };

    ( | $self:tt, $input:ident |> { $($code_block:tt)* } ) => ( $($code_block)* );

    ( | $self:tt, $input:ident |> $action:ident $($args:expr),*; $($rest:tt)* ) => {
        trace!(@actions $action $($args:expr)*);
        action!(| $self, $input |> $action $($args),*);
        action_list!(| $self, $input |> $($rest)*);
    };

     ( | $self:tt, $input:ident |> $action:ident ? $($args:expr),*; $($rest:tt)* ) => {
        trace!(@actions $action $($args:expr)*);
        action!(| $self, $input |> $action ? $($args),*);
        action_list!(| $self, $input |> $($rest)*);
    };

    // NOTE: state transition should always be in the end of the action list
    ( | $self:tt, $input:ident|> $($transition:tt)+ ) => {
        trace!(@actions $($transition)+);
        action!(@state_transition | $self, $input |> $($transition)+);
    };

    // NOTE: end of the action list
    ( | $self:tt, $input:ident |> ) => ();


    // State enter action list
    //--------------------------------------------------------------------
    ( @state_enter | $self:tt, $input:ident |> $($actions:tt)+ ) => {
        if $self.is_state_enter() {
            action_list!(|$self, $input|> $($actions)*);
            $self.set_is_state_enter(false);
        }
    };

    // NOTE: don't generate any code for the empty action list
    ( @state_enter | $self:tt, $input:ident |> ) => ();
}

define_state_group!(rawtext_states_group = {

    rawtext_state {
        b'<' => ( emit_text?; mark_tag_start; --> rawtext_less_than_sign_state )
        eoc  => ( emit_text?; )
        eof  => ( emit_text?; emit_eof?; )
        _    => ()
    }

    rawtext_less_than_sign_state {
        b'/' => ( --> rawtext_end_tag_open_state )
        eof  => ( emit_text?; emit_eof?; )
        _    => ( unmark_tag_start; emit_text?; reconsume in rawtext_state )
    }

    rawtext_end_tag_open_state {
        alpha => ( create_end_tag; start_token_part; update_tag_name_hash; --> rawtext_end_tag_name_state )
        eof   => ( emit_text?; emit_eof?; )
        _     => ( unmark_tag_start; emit_text?; reconsume in rawtext_state )
    }

    rawtext_end_tag_name_state {
        whitespace => (
            if is_appropriate_end_tag
                ( finish_tag_name?; --> before_attribute_name_state )
            else
                ( unmark_tag_start; emit_text?; reconsume in rawtext_state )
        )

        b'/' => (
            if is_appropriate_end_tag
                ( --> self_closing_start_tag_state )
            else
                ( unmark_tag_start; emit_text?; reconsume in rawtext_state )
        )

        b'>' => (
            if is_appropriate_end_tag
                ( emit_tag?; --> dyn next_text_parsing_state )
            else
                ( unmark_tag_start; emit_text?; reconsume in rawtext_state )
        )

        alpha => ( update_tag_name_hash; )
        eof   => ( emit_text?; emit_eof?; )
        _     => ( unmark_tag_start; emit_text?; reconsume in rawtext_state )
    }

});

// #[macro_use]
// mod ch_sequence;

macro_rules! arm_pattern {
    ( | $cb_args:tt |>
         alpha => $actions:tt
    ) => {
        state_body!(@callback | $cb_args |> Some(b'a'..=b'z') | Some(b'A'..=b'Z') => $actions);
    };

    ( | $cb_args:tt |>
        whitespace => $actions:tt
    ) => {
        state_body!(@callback | $cb_args |>
            Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') | Some(b'\x0C') => $actions
        );
    };

    ( | [ [$self:tt, $input_chunk:ident, $ch:ident ], $($rest_cb_args:tt)+ ] |>
        closing_quote => $actions:tt
    ) => {
        state_body!(@callback | [ [$self, $input_chunk, $ch], $($rest_cb_args)+ ] |>
            Some(ch) if ch == $self.closing_quote() => $actions
        );
    };


    ( | [ [$self:tt, $input:ident, $ch:ident ], $($rest_cb_args:tt)+ ] |>
        eoc => ( $($actions:tt)* )
    ) => {
        state_body!(@callback | [ [$self, $input, $ch], $($rest_cb_args)+ ] |>
            None if !$self.is_last_input() => ({
                action_list!(|$self, $input|> $($actions)* );

                return $self.break_on_end_of_input($input);
            })
        );
    };

    // NOTE: this arm is always enforced by the compiler to make match exhaustive,
    // so it's safe to break parsing loop here, since we don't have any input left
    // to parse. We execute EOF actions only if it's a last input, otherwise we just
    // break the parsing loop if it hasn't been done by the explicit EOC arm.
    ( | [ [$self:tt, $input:ident, $ch:ident ], $($rest_cb_args:tt)+ ] |>
        eof => ( $($actions:tt)* )
    ) => {
        state_body!(@callback | [ [$self, $input, $ch], $($rest_cb_args)+ ] |>
            None => ({
                if $self.is_last_input() {
                    action_list!(|$self, $input|> $($actions)* );
                }

                return $self.break_on_end_of_input($input);
            })
        );
    };

    ( | [ $scope_vars:tt, $($rest_cb_args:tt)+ ] |>
        [ $seq_pat:tt $(; $case_mod:ident)* ] => $actions:tt
    ) => {
        // NOTE: character sequence arm should be expanded in
        // place before we hit the character match block.
        ch_sequence_arm_pattern!(|$scope_vars|> $seq_pat, $actions, $($case_mod)* );
        state_body!(@callback | [ $scope_vars, $($rest_cb_args)+ ] |>);
    };

    ( | $cb_args:tt |> $pat:pat => $actions:tt ) => {
        state_body!(@callback | $cb_args |> Some($pat) => $actions);
    };
}

macro_rules! action {
    (| $self:tt, $input:ident | > $action_fn:ident ? $($args:expr),* ) => {
        $self.$action_fn($input $(,$args),*).map_err(ParsingTermination::ActionError)?;
    };

    (| $self:tt, $input:ident | > $action_fn:ident $($args:expr),* ) => {
        $self.$action_fn($input $(,$args),*);
    };

    ( @state_transition | $self:tt, $input:ident | > reconsume in $state:ident) => {
        $self.unconsume_ch();
        action!(@state_transition | $self, $input | > --> $state);
    };

    ( @state_transition | $self:tt, $input:ident | > - -> $state:ident) => {
        $self.switch_state(Self::$state);
        return Ok(());
    };

    ( @state_transition | $self:tt, $input:ident | > - -> dyn $state_getter:ident) => {
        {
            let state = $self.$state_getter();
            $self.switch_state(state);
        }

        return Ok(());
    };
}

macro_rules! trace {
    ( $($args:tt)+ ) => {
    }
}

use std::error::Error;

type StateResult = Result<(), ParsingTermination>;
type ActionResult = Result<(), Box<dyn Error>>;
// type ActionResult = Result<(), Box<dyn Error>>;
struct Parser;
type State = fn(&mut Parser, &[u8]) -> StateResult;
enum ParsingTermination {
    ActionError(Box<dyn Error>)
}

impl Parser {
    rawtext_states_group!();

    fn consume_ch(&mut self, input: &[u8]) -> Option<u8> {
        loop {}
    }
    fn unconsume_ch(&mut self) {}
    fn break_on_end_of_input(&mut self, input: &[u8]) -> StateResult {
        loop {}
    }
    fn is_last_input(&mut self) -> bool {
        loop {}
    }
    fn is_appropriate_end_tag(&mut self) -> bool {
        loop {}
    }
    fn switch_state(&mut self, state: State) {}
    fn emit_text(&mut self, input: &[u8]) -> ActionResult {
        loop {}
    }
    fn unmark_tag_start(&mut self, _input: &[u8]) {}
    fn emit_eof(&mut self, input: &[u8]) -> ActionResult {
        loop {}
    }
    fn update_tag_name_hash(&mut self, input: &[u8]) {}
    fn emit_tag(&mut self, _input: &[u8]) -> ActionResult {
        loop {}
    }
    fn next_text_parsing_state(&self) -> fn(&mut Self, &[u8]) -> StateResult {
        loop {}
    }
    fn finish_tag_name<S>(&mut self, input: &[u8], tag_hint_sink: S) -> ActionResult {
        loop {}
    }
    fn self_closing_start_tag_state(&mut self, input: &[u8]) -> StateResult {
        loop {}
    }
    fn before_attribute_name_state(&mut self, input: &[u8]) -> StateResult {
        loop {}
    }
    fn start_token_part(&mut self, input: &[u8]) -> StateResult {
        loop {}
    }
    fn create_end_tag(&mut self, _input: &[u8]) {
        loop {}
    }
    fn mark_tag_start(&mut self, input: &[u8]) {
        loop {}
    }
}
```

</details>

The current output with `-Zmacro-backtrace=yes`:

```
error[E0061]: this function takes 2 arguments but 1 argument was supplied
   --> src/parser/state_machine/syntax_dsl/backtrace.rs:164:19
    |
5   | /         macro_rules! $name {
6   | |             () => {
7   | |                 state!($($states)+);
8   | |             };
9   | |         }
    | |_________- in this expansion of `rawtext_states_group!`
...
164 |                   ( finish_tag_name?; --> before_attribute_name_state )
    |                     ^^^^^^^^^^^^^^^ expected 2 arguments
...
263 |           $self.$action_fn($input $(,$args),*).map_err(ParsingTermination::ActionErr...
    |                            ------ supplied 1 argument
...
307 |       rawtext_states_group!();
    |       ----------------------- in this macro invocation
    |
note: associated function defined here
   --> src/parser/state_machine/syntax_dsl/backtrace.rs:337:8
    |
337 |     fn finish_tag_name<S>(&mut self, input: &[u8], tag_hint_sink: S) -> ActionResult {
    |        ^^^^^^^^^^^^^^^    ---------  ------------  ----------------=
```

<!-- The following is not always necessary. -->
Ideally the output should include at least the expansion of `state!` and `state_body!`; right now it only shows `define_state_group!`, `rawtext_states_group!`, and `action!`.

(I'll try to reduce this, but I only have so much time to work on this.)

cc @estebank