Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for log_syntax, trace_macros #29598

Open
aturon opened this issue Nov 5, 2015 · 18 comments
Open

Tracking issue for log_syntax, trace_macros #29598

aturon opened this issue Nov 5, 2015 · 18 comments
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. S-tracking-design-concerns Status: There are blocking ❌ design concerns. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@aturon
Copy link
Member

aturon commented Nov 5, 2015

The log_syntax feature gate allows use of the log_syntax macro attribute, and similarly for trace_macros. Both are "nasty hacks that will certainly be removed" (according to the reference manual).

@aturon aturon added T-lang Relevant to the language team, which will review and decide on the PR/issue. B-unstable Blocker: Implemented in the nightly compiler and unstable. labels Nov 5, 2015
@aturon aturon changed the title Tracking issue for log_syntax Tracking issue for log_syntax, trace_macros Nov 5, 2015
@brson
Copy link
Contributor

brson commented Jun 27, 2016

Does anybody care about either of these at all anymore? They are ancient debugging tools that seem unlikely to be stabilized without serious rethinking. Can we remove them?

cc #3065

@brson
Copy link
Contributor

brson commented Jun 27, 2016

f? @rust-lang/compiler

@brson
Copy link
Contributor

brson commented Jun 27, 2016

@durka says not to remove trace_macros!.

@durka
Copy link
Contributor

durka commented Jun 27, 2016

I realize it's a hack, but it's pretty much impossible to debug complex macros without using the trace functionality. As of now it's accessible both by the trace_macros "macro" and a compiler flag of the same name, both unstable. I think at least one of those needs to remain available. I also think the tracing output needs work (formatting), but that doesn't mean it should be killed. cc @DanielKeep

@SimonSapin
Copy link
Contributor

I used trace_macros!(true); yesterday and would have had a hard time without it or some kind of replacement. I just learned about the command-line option.

It’s only useful temporarily to see what’s going on, IMO never something I’d want to commit in git. So a command-line option instead of syntax extension would be ok (even slightly better) as long as how to use it with Cargo is documented in https://doc.rust-lang.org/book/macros.html#debugging-macro-code (cargo rustc -p my_crate -- -Z unstable-options -Z trace-macros ?)

@DanielKeep
Copy link
Contributor

The problem with the switch is that it turns it on for everything. Due to the way it's output is formatted (spread across multiple lines), this can make debugging a badly behaving macro in the midst of lots of other macro expansions completely hellish.

If we could keep only one, I'd keep trace_macros!. It's overwhelmingly more flexible.

And just to reiterate what durka said: this is, indeed, one of the very, very few tools we have to debug macros. It's not very good, but it's not like there's really any alternative.

@Mark-Simulacrum
Copy link
Member

Can we deprecate log_syntax? Or at least, can someone explain what the intent is? On #3065, it's not clear whether it's meant to provide an expansion "backtrace" or just print what it expanded to.

@durka
Copy link
Contributor

durka commented May 6, 2017

I'm not sure what log_syntax! was intended to do, but as it is it essentially calls stringify! on whatever you pass to it, and has the compiler println! that at compile time. It's sort of a dual -- as trace_macros! can show you the input of a macro, log_syntax! can help you debug the output:

macro_rules! some_broken_macro {
    (...) => {
        struct $whatever { $($foo: $bar),* }
        // Let's say this causes a compile error for some reason, so macro expansion never finishes.
        // To debug, I could wrap the macro output in log_syntax!(...) to see what it would output.
    }
}

I use log_syntax! less than I use trace_macros!. It also overlaps with --pretty=expanded (but that is being taken away too).

@ExpHP
Copy link
Contributor

ExpHP commented Jul 4, 2017

I was going to comment on this tracking issue a couple weeks back around when I made this issue, but I guess I eventually decided against it. Perhaps I wanted to give it more time to develop since the new format was so recent.

In any case, I have not been enjoying the new format.

I can't say that I've ever needed a debugging tool to see what a macro expanded into; in all of my time debugging macros, it has been easy enough to figure out the issue based simply on what it was expanded from. But now these two types of information are all tangled together into one giant bowl of spaghetti with hardly any visual cue to help my eyes pull them apart.

Frankly, the zig-zagging shape formed by the note headers is making me dizzy!

new output (nightly)
    = note: expanding `gen_test_funcs! { @ named test_21 [ "/**" , "*" , false ] }`
    = note: to `# [ test ] fn test_21 (  ) { gen_tests ! ( [ "/**" , "*" , false ] ) ; }`
    = note: expanding `gen_tests! { [ "/**" , "*" , false ] }`
    = note: to `gen_tests ! ( @ single [ "/**" , "*" , false ] ) ;`
    = note: expanding `gen_tests! { @ single [ "/**" , "*" , false ] }`
    = note: to `gen_tests ! { @ test [ "/**" , "*" , None :: < String > ] }`
    = note: expanding `gen_tests! { @ test [ "/**" , "*" , None :: < String > ] }`
    = note: to `use $crate :: intersect ; let d = intersect ( "/**" , "*" , (  ) ) ; if d !=
            None::<String> {
            panic ! (
            "Assertion failed:\nInput:  intersect({:?}, {:?})\nExpected:  {:?}\n  Actual:  {:?}\n"
            , "/**" , "*" , None::<String> , d ) ; }`
    = note: expanding `panic! { "Assertion failed:\nInput:  intersect({:?}, {:?})\nExpected:  {:?}\n  Actual:  {:?}\n"
            , "/**" , "*" , None::<String> , d }`
    = note: to `{
            $crate :: rt :: begin_panic_fmt (
            & format_args ! (
            "Assertion failed:\nInput:  intersect({:?}, {:?})\nExpected:  {:?}\n  Actual:  {:?}\n"
            , "/**" , "*" , None::<String> , d ) , {
            static _FILE_LINE : ( & 'static str , u32 ) = ( file ! (  ) , line ! (  ) ) ;
            & _FILE_LINE } ) }`
    = note: expanding `gen_test_funcs! { @ name_them [
            test_22 test_23 test_24 test_25 test_26 test_27 test_28 test_29 test_30
            test_31 test_32 test_33 test_34 test_35 test_36 test_37 test_38 test_39
            test_40 test_41 test_42 test_43 test_44 test_45 test_46 test_47 test_48
            test_49 ] [ [ "**/" , "*" , false ] ] }`
    = note: to `gen_test_funcs ! ( @ named test_22 [ "**/" , "*" , false ] ) ; gen_test_funcs
            ! (
            @ name_them [
            test_23 test_24 test_25 test_26 test_27 test_28 test_29 test_30 test_31
            test_32 test_33 test_34 test_35 test_36 test_37 test_38 test_39 test_40
            test_41 test_42 test_43 test_44 test_45 test_46 test_47 test_48 test_49 ] [  ]
            ) ;`
    = note: expanding `gen_test_funcs! { @ named test_22 [ "**/" , "*" , false ] }`
    = note: to `# [ test ] fn test_22 (  ) { gen_tests ! ( [ "**/" , "*" , false ] ) ; }`
    = note: expanding `gen_tests! { [ "**/" , "*" , false ] }`
    = note: to `gen_tests ! ( @ single [ "**/" , "*" , false ] ) ;`
    = note: expanding `gen_tests! { @ single [ "**/" , "*" , false ] }`
    = note: to `gen_tests ! { @ test [ "**/" , "*" , None :: < String > ] }`
    = note: expanding `gen_tests! { @ test [ "**/" , "*" , None :: < String > ] }`
    = note: to `use $crate :: intersect ; let d = intersect ( "**/" , "*" , (  ) ) ; if d !=
            None::<String> {
            panic ! (
            "Assertion failed:\nInput:  intersect({:?}, {:?})\nExpected:  {:?}\n  Actual:  {:?}\n"
            , "**/" , "*" , None::<String> , d ) ; }`
    = note: expanding `panic! { "Assertion failed:\nInput:  intersect({:?}, {:?})\nExpected:  {:?}\n  Actual:  {:?}\n"
            , "**/" , "*" , None::<String> , d }`
    = note: to `{
            $crate :: rt :: begin_panic_fmt (
            & format_args ! (
            "Assertion failed:\nInput:  intersect({:?}, {:?})\nExpected:  {:?}\n  Actual:  {:?}\n"
            , "**/" , "*" , None::<String> , d ) , {
            static _FILE_LINE : ( & 'static str , u32 ) = ( file ! (  ) , line ! (  ) ) ;
            & _FILE_LINE } ) }`
    = note: expanding `gen_test_funcs! { @ name_them [
            test_23 test_24 test_25 test_26 test_27 test_28 test_29 test_30 test_31
            test_32 test_33 test_34 test_35 test_36 test_37 test_38 test_39 test_40
            test_41 test_42 test_43 test_44 test_45 test_46 test_47 test_48 test_49 ] [  ] }`
    = note: to ``
old output (nightly-2017-03-01)
gen_test_funcs! { [ "{x,{a,b}}" , "*" , "{x,a,b}" ] [
"{{x,y},{ab{bc,{de}}}}" , "*" , "{x,y,ab{bc,de}}" ] [
"{{{},{{}}},{{{},{{}}}}}" , "*" , "" ] }
gen_test_funcs! { @ name_them [
test_01 test_02 test_03 test_04 test_05 test_06 test_07 test_08 test_09
test_10 test_11 test_12 test_13 test_14 test_15 test_16 test_17 test_18
test_19 test_20 test_21 test_22 test_23 test_24 test_25 test_26 test_27
test_28 test_29 test_30 test_31 test_32 test_33 test_34 test_35 test_36
test_37 test_38 test_39 test_40 test_41 test_42 test_43 test_44 test_45
test_46 test_47 test_48 test_49 ] [
[ "{x,{a,b}}" , "*" , "{x,a,b}" ] [
"{{x,y},{ab{bc,{de}}}}" , "*" , "{x,y,ab{bc,de}}" ] [
"{{{},{{}}},{{{},{{}}}}}" , "*" , "" ] ] }
gen_test_funcs! { @ named test_01 [ "{x,{a,b}}" , "*" , "{x,a,b}" ] }
gen_tests! { [ "{x,{a,b}}" , "*" , "{x,a,b}" ] }
gen_tests! { @ single [ "{x,{a,b}}" , "*" , "{x,a,b}" ] }
gen_tests! { @ test [ "{x,{a,b}}" , "*" , Some ( "{x,a,b}" . to_string (  ) ) ] }
panic! { "Assertion failed:\nInput:  intersect({:?}, {:?})\nExpected:  {:?}\n  Actual:  {:?}\n"
, "{x,{a,b}}" , "*" , Some("{x,a,b}".to_string()) , d }
gen_test_funcs! { @ name_them [
test_02 test_03 test_04 test_05 test_06 test_07 test_08 test_09 test_10
test_11 test_12 test_13 test_14 test_15 test_16 test_17 test_18 test_19
test_20 test_21 test_22 test_23 test_24 test_25 test_26 test_27 test_28
test_29 test_30 test_31 test_32 test_33 test_34 test_35 test_36 test_37
test_38 test_39 test_40 test_41 test_42 test_43 test_44 test_45 test_46
test_47 test_48 test_49 ] [
[ "{{x,y},{ab{bc,{de}}}}" , "*" , "{x,y,ab{bc,de}}" ] [
"{{{},{{}}},{{{},{{}}}}}" , "*" , "" ] ] }
gen_test_funcs! { @ named test_02 [ "{{x,y},{ab{bc,{de}}}}" , "*" , "{x,y,ab{bc,de}}" ] }
gen_tests! { [ "{{x,y},{ab{bc,{de}}}}" , "*" , "{x,y,ab{bc,de}}" ] }
gen_tests! { @ single [ "{{x,y},{ab{bc,{de}}}}" , "*" , "{x,y,ab{bc,de}}" ] }
gen_tests! { @ test [
"{{x,y},{ab{bc,{de}}}}" , "*" , Some ( "{x,y,ab{bc,de}}" . to_string (  ) ) ] }
panic! { "Assertion failed:\nInput:  intersect({:?}, {:?})\nExpected:  {:?}\n  Actual:  {:?}\n"
, "{{x,y},{ab{bc,{de}}}}" , "*" , Some("{x,y,ab{bc,de}}".to_string()) , d }
gen_test_funcs! { @ name_them [
test_03 test_04 test_05 test_06 test_07 test_08 test_09 test_10 test_11
test_12 test_13 test_14 test_15 test_16 test_17 test_18 test_19 test_20
test_21 test_22 test_23 test_24 test_25 test_26 test_27 test_28 test_29
test_30 test_31 test_32 test_33 test_34 test_35 test_36 test_37 test_38
test_39 test_40 test_41 test_42 test_43 test_44 test_45 test_46 test_47
test_48 test_49 ] [ [ "{{{},{{}}},{{{},{{}}}}}" , "*" , "" ] ] }
gen_test_funcs! { @ named test_03 [ "{{{},{{}}},{{{},{{}}}}}" , "*" , "" ] }
gen_tests! { [ "{{{},{{}}},{{{},{{}}}}}" , "*" , "" ] }
gen_tests! { @ single [ "{{{},{{}}},{{{},{{}}}}}" , "*" , "" ] }
gen_tests! { @ test [ "{{{},{{}}},{{{},{{}}}}}" , "*" , Some ( "" . to_string (  ) ) ] }
panic! { "Assertion failed:\nInput:  intersect({:?}, {:?})\nExpected:  {:?}\n  Actual:  {:?}\n"
, "{{{},{{}}},{{{},{{}}}}}" , "*" , Some("".to_string()) , d }
gen_test_funcs! { @ name_them [
test_04 test_05 test_06 test_07 test_08 test_09 test_10 test_11 test_12
test_13 test_14 test_15 test_16 test_17 test_18 test_19 test_20 test_21
test_22 test_23 test_24 test_25 test_26 test_27 test_28 test_29 test_30
test_31 test_32 test_33 test_34 test_35 test_36 test_37 test_38 test_39
test_40 test_41 test_42 test_43 test_44 test_45 test_46 test_47 test_48
test_49 ] [  ] }

The old output was chaotic, but at least it tells a story. You can read the gen_tests! lines right from top to bottom to see how the macro evolves over time.

There is a note about this with plans to eliminate redundant "expanding" lines, but I am suspicious as to whether that is enough to make the output comprehensible.

@ExpHP
Copy link
Contributor

ExpHP commented Jul 4, 2017

I see the motivating issue here but to me it would have seemed sufficient to just fix the misleading "expands to" to "expanding".

Is there a home-run example of a problem that would be difficult to debug without the added information of what a macro expanded into?

cc @jorendorff

@durka
Copy link
Contributor

durka commented Jul 4, 2017 via email

@jorendorff
Copy link
Contributor

Is there a home-run example of a problem that would be difficult to debug without the added information of what a macro expanded into?

I don't know if it's a "home run", but I'll give an example. First some background. There are two cases where I think the output is helpful:

  1. Usually if I'm debugging a macro, it is because something is not expanding the way I expect. To fix this, I need to know (a) which expansion is misbehaving; (b) what part of the expansion is wrong. Seeing the output helps tremendously with both.

  2. Sometimes a macro expands to rather a lot of code (often an impl) and something in there triggers a compile error. The error message shows the line number of the original macro call in the source—useless. I want to see what the Rust compiler sees.

Now my example. Once in a while I write $x:expr in a macro template when of course I should write $x. Dumb; but for some reason I tend to overlook this bug when I'm staring at the macro definition. If I use trace_macros!, the to: output makes it really jump out at me. The :expr in the buggy output is a dead giveaway; it doesn't look anything like correct Rust code.

@jorendorff
Copy link
Contributor

There are definitely some things in the trace_macros! output that are less than ideal: the redundancy is bad, and the nondeterministic order is worse. Both fixable!

@nikomatsakis
Copy link
Contributor

I have often wanted both the inputs/outputs as well, no question. Not to say that the current output is the easiest to parse.

@Mark-Simulacrum Mark-Simulacrum added the C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. label Jul 22, 2017
@ExpHP
Copy link
Contributor

ExpHP commented Jul 1, 2018

An issue where the new trace_macros! fails to show anything: #51754 (edit: Gave it its own issue: #51960)

As the compiler never hits an error, nothing is ever shown.

@steveklabnik
Copy link
Member

Triage: I'm not aware of any movement on this feature, neither to remove, fix up, nor stabilize.

@crlf0710
Copy link
Member

crlf0710 commented May 8, 2021

It seems this would be covered by rust-lang/rust-analyzer#5949

@joshtriplett joshtriplett added S-tracking-perma-unstable Status: The feature will stay unstable indefinitely. S-tracking-design-concerns Status: There are blocking ❌ design concerns. and removed S-tracking-perma-unstable Status: The feature will stay unstable indefinitely. labels Nov 10, 2021
@joshtriplett
Copy link
Member

From today's @rust-lang/lang meeting:
We definitely want something for debugging macro expansion. We're not sure it looks like this. This needs some design consideration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. S-tracking-design-concerns Status: There are blocking ❌ design concerns. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests