From 1de136078b1fe909c35f44fde7d0161fb0a3e9c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Fri, 26 Feb 2021 02:09:31 +0100
Subject: [PATCH] -Zunpretty: allow passing several printing modes as
 comma-separated list.

Modes that had a comma in them use "+" now:
-Zunpretty=expanded,hygiene => -Zunpretty=expanded+hygiene

You can print several modes back to back like this: -Zunpretty=expanded+hygiene,mir,hir,everybody_loops
---
 compiler/rustc_driver/src/lib.rs              |  42 ++++---
 compiler/rustc_driver/src/pretty.rs           | 118 +++++++++---------
 compiler/rustc_interface/src/passes.rs        |   8 +-
 compiler/rustc_session/src/config.rs          |  94 +++++++-------
 compiler/rustc_session/src/options.rs         |  10 +-
 src/test/pretty/issue-4264.pp                 |   2 +-
 src/test/pretty/issue-4264.rs                 |   2 +-
 src/test/ui/hygiene/unpretty-debug.rs         |   2 +-
 src/test/ui/hygiene/unpretty-debug.stdout     |   2 +-
 src/test/ui/proc-macro/meta-macro-hygiene.rs  |   2 +-
 .../ui/proc-macro/meta-macro-hygiene.stdout   |   2 +-
 .../proc-macro/nonterminal-token-hygiene.rs   |   2 +-
 .../nonterminal-token-hygiene.stdout          |   2 +-
 13 files changed, 150 insertions(+), 138 deletions(-)

diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 79bb21b29fc9b..6da68e4aea668 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -333,28 +333,30 @@ fn run_compiler(
             let early_exit = || sess.compile_status().map(|_| None);
             queries.parse()?;
 
-            if let Some(ppm) = &sess.opts.pretty {
-                if ppm.needs_ast_map() {
-                    queries.global_ctxt()?.peek_mut().enter(|tcx| {
-                        let expanded_crate = queries.expansion()?.take().0;
-                        pretty::print_after_hir_lowering(
-                            tcx,
-                            compiler.input(),
-                            &expanded_crate,
-                            *ppm,
+            if let Some(ppms) = &sess.opts.pretty {
+                for ppm in ppms {
+                    if ppm.needs_ast_map() {
+                        queries.global_ctxt()?.peek_mut().enter(|tcx| {
+                            let expanded_crate = queries.expansion()?.take().0;
+                            pretty::print_after_hir_lowering(
+                                tcx,
+                                compiler.input(),
+                                &expanded_crate,
+                                ppms,
+                                compiler.output_file().as_ref().map(|p| &**p),
+                            );
+                            Ok(())
+                        })?;
+                    } else {
+                        let krate = queries.parse()?.take();
+                        pretty::print_after_parsing(
+                            sess,
+                            &compiler.input(),
+                            &krate,
+                            ppms,
                             compiler.output_file().as_ref().map(|p| &**p),
                         );
-                        Ok(())
-                    })?;
-                } else {
-                    let krate = queries.parse()?.take();
-                    pretty::print_after_parsing(
-                        sess,
-                        &compiler.input(),
-                        &krate,
-                        *ppm,
-                        compiler.output_file().as_ref().map(|p| &**p),
-                    );
+                    }
                 }
                 trace!("finished pretty-printing");
                 return early_exit();
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index 1dcc4d147acf2..eb9a9499f2dcd 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -386,52 +386,15 @@ pub fn print_after_parsing(
     sess: &Session,
     input: &Input,
     krate: &ast::Crate,
-    ppm: PpMode,
-    ofile: Option<&Path>,
-) {
-    let (src, src_name) = get_source(input, sess);
-
-    let out = if let Source(s) = ppm {
-        // Silently ignores an identified node.
-        call_with_pp_support(&s, sess, None, move |annotation| {
-            debug!("pretty printing source code {:?}", s);
-            let sess = annotation.sess();
-            let parse = &sess.parse_sess;
-            pprust::print_crate(
-                sess.source_map(),
-                krate,
-                src_name,
-                src,
-                annotation.pp_ann(),
-                false,
-                parse.edition,
-            )
-        })
-    } else {
-        unreachable!()
-    };
-
-    write_or_print(&out, ofile);
-}
-
-pub fn print_after_hir_lowering<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    input: &Input,
-    krate: &ast::Crate,
-    ppm: PpMode,
+    ppms: &Vec<PpMode>,
     ofile: Option<&Path>,
 ) {
-    if ppm.needs_analysis() {
-        abort_on_err(print_with_analysis(tcx, ppm, ofile), tcx.sess);
-        return;
-    }
-
-    let (src, src_name) = get_source(input, tcx.sess);
+    ppms.iter().for_each(|ppm| {
+        let (src, src_name) = get_source(input, sess);
 
-    let out = match ppm {
-        Source(s) => {
+        let out = if let Source(s) = ppm {
             // Silently ignores an identified node.
-            call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| {
+            call_with_pp_support(&s, sess, None, move |annotation| {
                 debug!("pretty printing source code {:?}", s);
                 let sess = annotation.sess();
                 let parse = &sess.parse_sess;
@@ -441,28 +404,71 @@ pub fn print_after_hir_lowering<'tcx>(
                     src_name,
                     src,
                     annotation.pp_ann(),
-                    true,
+                    false,
                     parse.edition,
                 )
             })
+        } else {
+            unreachable!()
+        };
+
+        write_or_print(&out, ofile);
+    });
+}
+
+pub fn print_after_hir_lowering<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    input: &Input,
+    krate: &ast::Crate,
+    ppms: &Vec<PpMode>,
+    ofile: Option<&Path>,
+) {
+    ppms.iter().for_each(|ppm| {
+        if ppm.needs_analysis() {
+            abort_on_err(print_with_analysis(tcx, *ppm, ofile), tcx.sess);
+            return;
         }
 
-        Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, krate| {
-            debug!("pretty printing HIR {:?}", s);
-            let sess = annotation.sess();
-            let sm = sess.source_map();
-            pprust_hir::print_crate(sm, krate, src_name, src, annotation.pp_ann())
-        }),
+        let (src, src_name) = get_source(input, tcx.sess);
+
+        let out = match ppm {
+            Source(s) => {
+                // Silently ignores an identified node.
+                call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| {
+                    debug!("pretty printing source code {:?}", s);
+                    let sess = annotation.sess();
+                    let parse = &sess.parse_sess;
+                    pprust::print_crate(
+                        sess.source_map(),
+                        krate,
+                        src_name,
+                        src,
+                        annotation.pp_ann(),
+                        true,
+                        parse.edition,
+                    )
+                })
+            }
 
-        HirTree => call_with_pp_support_hir(&PpHirMode::Normal, tcx, move |_annotation, krate| {
-            debug!("pretty printing HIR tree");
-            format!("{:#?}", krate)
-        }),
+            Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, krate| {
+                debug!("pretty printing HIR {:?}", s);
+                let sess = annotation.sess();
+                let sm = sess.source_map();
+                pprust_hir::print_crate(sm, krate, src_name, src, annotation.pp_ann())
+            }),
+
+            HirTree => {
+                call_with_pp_support_hir(&PpHirMode::Normal, tcx, move |_annotation, krate| {
+                    debug!("pretty printing HIR tree");
+                    format!("{:#?}", krate)
+                })
+            }
 
-        _ => unreachable!(),
-    };
+            _ => unreachable!(),
+        };
 
-    write_or_print(&out, ofile);
+        write_or_print(&out, ofile);
+    });
 }
 
 // In an ideal world, this would be a public function called by the driver after
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 5217066bbefde..e2d0e07c03b08 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -350,9 +350,11 @@ fn configure_and_expand_inner<'a>(
         rustc_builtin_macros::test_harness::inject(&sess, &mut resolver, &mut krate)
     });
 
-    if let Some(PpMode::Source(PpSourceMode::EveryBodyLoops)) = sess.opts.pretty {
-        tracing::debug!("replacing bodies with loop {{}}");
-        util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
+    if let Some(ppmodes) = &sess.opts.pretty {
+        if ppmodes.contains(&PpMode::Source(PpSourceMode::EveryBodyLoops)) {
+            tracing::debug!("replacing bodies with loop {{}}");
+            util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
+        }
     }
 
     let has_proc_macro_decls = sess.time("AST_validation", || {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 38da52b88f369..2bd68fe18094c 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1178,7 +1178,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
             "Pretty-print the input instead of compiling;
                   valid types are: `normal` (un-annotated source),
                   `expanded` (crates expanded), or
-                  `expanded,identified` (fully parenthesized, AST nodes with IDs).",
+                  `expanded+identified` (fully parenthesized, AST nodes with IDs).",
             "TYPE",
         ),
         opt::multi_s(
@@ -2056,49 +2056,51 @@ fn parse_pretty(
     matches: &getopts::Matches,
     debugging_opts: &DebuggingOptions,
     efmt: ErrorOutputType,
-) -> Option<PpMode> {
-    fn parse_pretty_inner(efmt: ErrorOutputType, name: &str, extended: bool) -> PpMode {
+) -> Option<Vec<PpMode>> {
+    fn parse_pretty_inner(efmt: ErrorOutputType, list: &str, extended: bool) -> Vec<PpMode> {
         use PpMode::*;
-        let first = match (name, extended) {
-            ("normal", _) => Source(PpSourceMode::Normal),
-            ("identified", _) => Source(PpSourceMode::Identified),
-            ("everybody_loops", true) => Source(PpSourceMode::EveryBodyLoops),
-            ("expanded", _) => Source(PpSourceMode::Expanded),
-            ("expanded,identified", _) => Source(PpSourceMode::ExpandedIdentified),
-            ("expanded,hygiene", _) => Source(PpSourceMode::ExpandedHygiene),
-            ("hir", true) => Hir(PpHirMode::Normal),
-            ("hir,identified", true) => Hir(PpHirMode::Identified),
-            ("hir,typed", true) => Hir(PpHirMode::Typed),
-            ("hir-tree", true) => HirTree,
-            ("mir", true) => Mir,
-            ("mir-cfg", true) => MirCFG,
-            _ => {
-                if extended {
-                    early_error(
-                        efmt,
-                        &format!(
-                            "argument to `unpretty` must be one of `normal`, \
-                                        `expanded`, `identified`, `expanded,identified`, \
-                                        `expanded,hygiene`, `everybody_loops`, \
-                                        `hir`, `hir,identified`, `hir,typed`, `hir-tree`, \
-                                        `mir` or `mir-cfg`; got {}",
-                            name
-                        ),
-                    );
-                } else {
-                    early_error(
-                        efmt,
-                        &format!(
-                            "argument to `pretty` must be one of `normal`, \
-                                        `expanded`, `identified`, or `expanded,identified`; got {}",
-                            name
-                        ),
-                    );
+        list.split(",").map(|ppmode| {
+            let first = match (ppmode, extended) {
+                ("normal", _) => Source(PpSourceMode::Normal),
+                ("identified", _) => Source(PpSourceMode::Identified),
+                ("everybody_loops", true) => Source(PpSourceMode::EveryBodyLoops),
+                ("expanded", _) => Source(PpSourceMode::Expanded),
+                ("expanded+identified", _) => Source(PpSourceMode::ExpandedIdentified),
+                ("expanded+hygiene", _) => Source(PpSourceMode::ExpandedHygiene),
+                ("hir", true) => Hir(PpHirMode::Normal),
+                ("hir+identified", true) => Hir(PpHirMode::Identified),
+                ("hir+typed", true) => Hir(PpHirMode::Typed),
+                ("hir-tree", true) => HirTree,
+                ("mir", true) => Mir,
+                ("mir-cfg", true) => MirCFG,
+                _ => {
+                    if extended {
+                        early_error(
+                            efmt,
+                            &format!(
+                                "argument to `unpretty` must be one of `normal`, \
+                                            `expanded`, `identified`, `expanded+identified`, \
+                                            `expanded+hygiene`, `everybody_loops`, \
+                                            `hir`, `hir+identified`, `hir+typed`, `hir-tree`, \
+                                            `mir` or `mir-cfg`; got {}",
+                                ppmode
+                            ),
+                        );
+                    } else {
+                        early_error(
+                            efmt,
+                            &format!(
+                                "argument to `pretty` must be a comma-separated list or one of `normal`, \
+                                            `expanded`, `identified`, or `expanded+identified`; got {}",
+                                ppmode
+                            ),
+                        );
+                    }
                 }
-            }
-        };
-        tracing::debug!("got unpretty option: {:?}", first);
-        first
+            };
+            tracing::debug!("got unpretty option: {:?}", first);
+            first
+        }).collect()
     }
 
     if debugging_opts.unstable_options {
@@ -2227,9 +2229,9 @@ pub enum PpSourceMode {
     Expanded,
     /// `--pretty=identified`
     Identified,
-    /// `--pretty=expanded,identified`
+    /// `--pretty=expanded+identified`
     ExpandedIdentified,
-    /// `--pretty=expanded,hygiene`
+    /// `--pretty=expanded+hygiene`
     ExpandedHygiene,
 }
 
@@ -2237,9 +2239,9 @@ pub enum PpSourceMode {
 pub enum PpHirMode {
     /// `-Zunpretty=hir`
     Normal,
-    /// `-Zunpretty=hir,identified`
+    /// `-Zunpretty=hir+identified`
     Identified,
-    /// `-Zunpretty=hir,typed`
+    /// `-Zunpretty=hir+typed`
     Typed,
 }
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index d439753d042bb..addc995942cf8 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -147,7 +147,7 @@ top_level_options!(
         // by the compiler.
         json_artifact_notifications: bool [TRACKED],
 
-        pretty: Option<PpMode> [UNTRACKED],
+        pretty: Option<Vec<PpMode>> [UNTRACKED],
     }
 );
 
@@ -1153,11 +1153,11 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
         "present the input source, unstable (and less-pretty) variants;
         valid types are any of the types for `--pretty`, as well as:
-        `expanded`, `expanded,identified`,
-        `expanded,hygiene` (with internal representations),
+        `expanded`, `expanded+identified`,
+        `expanded+hygiene` (with internal representations),
         `everybody_loops` (all function bodies replaced with `loop {}`),
-        `hir` (the HIR), `hir,identified`,
-        `hir,typed` (HIR with types for each node),
+        `hir` (the HIR), `hir+identified`,
+        `hir+typed` (HIR with types for each node),
         `hir-tree` (dump the raw HIR),
         `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"),
     unsound_mir_opts: bool = (false, parse_bool, [TRACKED],
diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
index 7b0a00282fbb0..98ccf1df65be2 100644
--- a/src/test/pretty/issue-4264.pp
+++ b/src/test/pretty/issue-4264.pp
@@ -3,7 +3,7 @@
 #[macro_use]
 extern crate std;
 // pretty-compare-only
-// pretty-mode:hir,typed
+// pretty-mode:hir+typed
 // pp-exact:issue-4264.pp
 
 // #4264 fixed-length vector types
diff --git a/src/test/pretty/issue-4264.rs b/src/test/pretty/issue-4264.rs
index 3dea811298180..d1862bd594584 100644
--- a/src/test/pretty/issue-4264.rs
+++ b/src/test/pretty/issue-4264.rs
@@ -1,5 +1,5 @@
 // pretty-compare-only
-// pretty-mode:hir,typed
+// pretty-mode:hir+typed
 // pp-exact:issue-4264.pp
 
 // #4264 fixed-length vector types
diff --git a/src/test/ui/hygiene/unpretty-debug.rs b/src/test/ui/hygiene/unpretty-debug.rs
index 6e936bb3d830c..5dc92358926ee 100644
--- a/src/test/ui/hygiene/unpretty-debug.rs
+++ b/src/test/ui/hygiene/unpretty-debug.rs
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Zunpretty=expanded,hygiene
+// compile-flags: -Zunpretty=expanded+hygiene
 
 // Don't break whenever Symbol numbering changes
 // normalize-stdout-test "\d+#" -> "0#"
diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout
index 96044a8928946..9096abfcb3013 100644
--- a/src/test/ui/hygiene/unpretty-debug.stdout
+++ b/src/test/ui/hygiene/unpretty-debug.stdout
@@ -1,5 +1,5 @@
 // check-pass
-// compile-flags: -Zunpretty=expanded,hygiene
+// compile-flags: -Zunpretty=expanded+hygiene
 
 // Don't break whenever Symbol numbering changes
 // normalize-stdout-test "\d+#" -> "0#"
diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.rs b/src/test/ui/proc-macro/meta-macro-hygiene.rs
index 7e839f747f339..2a08bb57a6753 100644
--- a/src/test/ui/proc-macro/meta-macro-hygiene.rs
+++ b/src/test/ui/proc-macro/meta-macro-hygiene.rs
@@ -2,7 +2,7 @@
 // aux-build:make-macro.rs
 // aux-build:meta-macro.rs
 // edition:2018
-// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no
+// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded+hygiene -Z trim-diagnostic-paths=no
 // check-pass
 // normalize-stdout-test "\d+#" -> "0#"
 //
diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout
index a067b7b5411dd..880f3b2e8319e 100644
--- a/src/test/ui/proc-macro/meta-macro-hygiene.stdout
+++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout
@@ -6,7 +6,7 @@ Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro
 // aux-build:make-macro.rs
 // aux-build:meta-macro.rs
 // edition:2018
-// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no
+// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded+hygiene -Z trim-diagnostic-paths=no
 // check-pass
 // normalize-stdout-test "\d+#" -> "0#"
 //
diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.rs b/src/test/ui/proc-macro/nonterminal-token-hygiene.rs
index 98fd4306004e8..54824bea24cbc 100644
--- a/src/test/ui/proc-macro/nonterminal-token-hygiene.rs
+++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.rs
@@ -1,7 +1,7 @@
 // Make sure that marks from declarative macros are applied to tokens in nonterminal.
 
 // check-pass
-// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene
+// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded+hygiene
 // compile-flags: -Z trim-diagnostic-paths=no
 // normalize-stdout-test "\d+#" -> "0#"
 // aux-build:test-macros.rs
diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout
index 1623d67772639..67d9bc576ed7b 100644
--- a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout
+++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout
@@ -26,7 +26,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
 // Make sure that marks from declarative macros are applied to tokens in nonterminal.
 
 // check-pass
-// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene
+// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded+hygiene
 // compile-flags: -Z trim-diagnostic-paths=no
 // normalize-stdout-test "\d+#" -> "0#"
 // aux-build:test-macros.rs