From dd6df0d20ed94b46125e7b2039205674f01c95b9 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 3 Nov 2019 21:42:03 -0500 Subject: [PATCH] Move pretty parsing into Session options This allows us to query whether PpmEveryBodyLoops is set during expansion and run the everybody loops pass. --- Cargo.lock | 1 + src/librustc/session/config.rs | 220 +++++++++++++++++++++ src/librustc_driver/lib.rs | 32 +-- src/librustc_driver/pretty.rs | 324 +++++++------------------------ src/librustc_interface/passes.rs | 7 +- 5 files changed, 302 insertions(+), 282 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f770f3eadb..8b157d2b3f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3506,6 +3506,7 @@ dependencies = [ "rustc_mir", "rustc_plugin", "rustc_plugin_impl", + "rustc_resolve", "rustc_save_analysis", "rustc_target", "serialize", diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index eb5654e80a8..4a14960aa69 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1,10 +1,13 @@ //! Contains infrastructure for configuring the compiler, including parsing //! command-line options. +// ignore-tidy-filelength + use crate::lint; use crate::middle::cstore; use crate::session::{early_error, early_warn, Session}; use crate::session::search_paths::SearchPath; +use crate::hir::map as hir_map; use rustc_data_structures::fx::FxHashSet; @@ -440,6 +443,8 @@ top_level_options!( // `true` if we're emitting JSON blobs about each artifact produced // by the compiler. json_artifact_notifications: bool [TRACKED], + + pretty: Option<(PpMode, Option)> [UNTRACKED], } ); @@ -621,6 +626,7 @@ impl Default for Options { remap_path_prefix: Vec::new(), edition: DEFAULT_EDITION, json_artifact_notifications: false, + pretty: None, } } } @@ -2516,6 +2522,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let remap_path_prefix = parse_remap_path_prefix(matches, error_format); + let pretty = parse_pretty(matches, &debugging_opts, error_format); + Options { crate_types, optimize: opt_level, @@ -2546,6 +2554,73 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { remap_path_prefix, edition, json_artifact_notifications, + pretty, + } +} + +fn parse_pretty( + matches: &getopts::Matches, + debugging_opts: &DebuggingOptions, + efmt: ErrorOutputType, +) -> Option<(PpMode, Option)> { + let pretty = if debugging_opts.unstable_options { + matches.opt_default("pretty", "normal").map(|a| { + // stable pretty-print variants only + parse_pretty_inner(efmt, &a, false) + }) + } else { + None + }; + + return if pretty.is_none() { + debugging_opts.unpretty.as_ref().map(|a| { + // extended with unstable pretty-print variants + parse_pretty_inner(efmt, &a, true) + }) + } else { + pretty + }; + + fn parse_pretty_inner( + efmt: ErrorOutputType, + name: &str, + extended: bool, + ) -> (PpMode, Option) { + use PpMode::*; + use PpSourceMode::*; + let mut split = name.splitn(2, '='); + let first = split.next().unwrap(); + let opt_second = split.next(); + let first = match (first, extended) { + ("normal", _) => PpmSource(PpmNormal), + ("identified", _) => PpmSource(PpmIdentified), + ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops), + ("expanded", _) => PpmSource(PpmExpanded), + ("expanded,identified", _) => PpmSource(PpmExpandedIdentified), + ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene), + ("hir", true) => PpmHir(PpmNormal), + ("hir,identified", true) => PpmHir(PpmIdentified), + ("hir,typed", true) => PpmHir(PpmTyped), + ("hir-tree", true) => PpmHirTree(PpmNormal), + ("mir", true) => PpmMir, + ("mir-cfg", true) => PpmMirCFG, + _ => { + 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)); + } + } + }; + let opt_second = opt_second.and_then(|s| s.parse::().ok()); + (first, opt_second) } } @@ -2656,6 +2731,151 @@ impl fmt::Display for CrateType { } } +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum PpSourceMode { + PpmNormal, + PpmEveryBodyLoops, + PpmExpanded, + PpmIdentified, + PpmExpandedIdentified, + PpmExpandedHygiene, + PpmTyped, +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum PpMode { + PpmSource(PpSourceMode), + PpmHir(PpSourceMode), + PpmHirTree(PpSourceMode), + PpmMir, + PpmMirCFG, +} + +impl PpMode { + pub fn needs_ast_map(&self, opt_uii: &Option) -> bool { + use PpMode::*; + use PpSourceMode::*; + match *self { + PpmSource(PpmNormal) | + PpmSource(PpmEveryBodyLoops) | + PpmSource(PpmIdentified) => opt_uii.is_some(), + + PpmSource(PpmExpanded) | + PpmSource(PpmExpandedIdentified) | + PpmSource(PpmExpandedHygiene) | + PpmHir(_) | + PpmHirTree(_) | + PpmMir | + PpmMirCFG => true, + PpmSource(PpmTyped) => panic!("invalid state"), + } + } + + pub fn needs_analysis(&self) -> bool { + use PpMode::*; + match *self { + PpmMir | PpmMirCFG => true, + _ => false, + } + } +} + +#[derive(Clone, Debug)] +pub enum UserIdentifiedItem { + ItemViaNode(ast::NodeId), + ItemViaPath(Vec), +} + +impl FromStr for UserIdentifiedItem { + type Err = (); + fn from_str(s: &str) -> Result { + use UserIdentifiedItem::*; + Ok(s.parse() + .map(ast::NodeId::from_u32) + .map(ItemViaNode) + .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect()))) + } +} + +pub enum NodesMatchingUII<'a> { + NodesMatchingDirect(std::option::IntoIter), + NodesMatchingSuffix(Box + 'a>), +} + +impl<'a> Iterator for NodesMatchingUII<'a> { + type Item = ast::NodeId; + + fn next(&mut self) -> Option { + use NodesMatchingUII::*; + match self { + &mut NodesMatchingDirect(ref mut iter) => iter.next(), + &mut NodesMatchingSuffix(ref mut iter) => iter.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + use NodesMatchingUII::*; + match self { + &NodesMatchingDirect(ref iter) => iter.size_hint(), + &NodesMatchingSuffix(ref iter) => iter.size_hint(), + } + } +} + +impl UserIdentifiedItem { + pub fn reconstructed_input(&self) -> String { + use UserIdentifiedItem::*; + match *self { + ItemViaNode(node_id) => node_id.to_string(), + ItemViaPath(ref parts) => parts.join("::"), + } + } + + pub fn all_matching_node_ids<'a, 'hir>(&'a self, + map: &'a hir_map::Map<'hir>) + -> NodesMatchingUII<'a> { + use UserIdentifiedItem::*; + use NodesMatchingUII::*; + match *self { + ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), + ItemViaPath(ref parts) => { + NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts))) + } + } + } + + pub fn to_one_node_id(self, + user_option: &str, + sess: &Session, + map: &hir_map::Map<'_>) + -> ast::NodeId { + let fail_because = |is_wrong_because| -> ast::NodeId { + let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \ + {}, which {}", + user_option, + self.reconstructed_input(), + is_wrong_because); + sess.fatal(&message) + }; + + let mut saw_node = ast::DUMMY_NODE_ID; + let mut seen = 0; + for node in self.all_matching_node_ids(map) { + saw_node = node; + seen += 1; + if seen > 1 { + fail_because("does not resolve uniquely"); + } + } + if seen == 0 { + fail_because("does not resolve to any item"); + } + + assert!(seen == 1); + return saw_node; + } +} + /// Command-line arguments passed to the compiler have to be incorporated with /// the dependency tracking system for incremental compilation. This module /// provides some utilities to make this more convenient. diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 478868579c7..7973a804f1a 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -25,8 +25,6 @@ extern crate lazy_static; pub extern crate rustc_plugin_impl as plugin; -use pretty::{PpMode, UserIdentifiedItem}; - //use rustc_resolve as resolve; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; @@ -285,11 +283,9 @@ pub fn run_compiler( return sess.compile_status(); } - let pretty_info = parse_pretty(sess, &matches); - compiler.parse()?; - if let Some((ppm, opt_uii)) = pretty_info { + if let Some((ppm, opt_uii)) = &sess.opts.pretty { if ppm.needs_ast_map(&opt_uii) { compiler.global_ctxt()?.peek_mut().enter(|tcx| { let expanded_crate = compiler.expansion()?.take().0; @@ -297,7 +293,7 @@ pub fn run_compiler( tcx, compiler.input(), &expanded_crate, - ppm, + *ppm, opt_uii.clone(), compiler.output_file().as_ref().map(|p| &**p), ); @@ -309,7 +305,7 @@ pub fn run_compiler( sess, &compiler.input(), &krate, - ppm, + *ppm, compiler.output_file().as_ref().map(|p| &**p), ); } @@ -468,28 +464,6 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option, Option } } -fn parse_pretty(sess: &Session, - matches: &getopts::Matches) - -> Option<(PpMode, Option)> { - let pretty = if sess.opts.debugging_opts.unstable_options { - matches.opt_default("pretty", "normal").map(|a| { - // stable pretty-print variants only - pretty::parse_pretty(sess, &a, false) - }) - } else { - None - }; - - if pretty.is_none() { - sess.opts.debugging_opts.unpretty.as_ref().map(|a| { - // extended with unstable pretty-print variants - pretty::parse_pretty(sess, &a, true) - }) - } else { - pretty - } -} - // Whether to stop or continue compilation. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Compilation { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 42941f25061..23253dc4dad 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -5,7 +5,7 @@ use rustc::hir::map as hir_map; use rustc::hir::print as pprust_hir; use rustc::hir::def_id::LOCAL_CRATE; use rustc::session::Session; -use rustc::session::config::Input; +use rustc::session::config::{PpMode, PpSourceMode, UserIdentifiedItem, Input}; use rustc::ty::{self, TyCtxt}; use rustc::util::common::ErrorReported; use rustc_mir::util::{write_mir_pretty, write_mir_graphviz}; @@ -17,103 +17,15 @@ use syntax_pos::FileName; use std::cell::Cell; use std::fs::File; use std::io::Write; -use std::option; use std::path::Path; -use std::str::FromStr; pub use self::UserIdentifiedItem::*; pub use self::PpSourceMode::*; pub use self::PpMode::*; -use self::NodesMatchingUII::*; use crate::abort_on_err; use crate::source_name; -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum PpSourceMode { - PpmNormal, - PpmEveryBodyLoops, - PpmExpanded, - PpmIdentified, - PpmExpandedIdentified, - PpmExpandedHygiene, - PpmTyped, -} - -#[derive(Copy, Clone, PartialEq, Debug)] -pub enum PpMode { - PpmSource(PpSourceMode), - PpmHir(PpSourceMode), - PpmHirTree(PpSourceMode), - PpmMir, - PpmMirCFG, -} - -impl PpMode { - pub fn needs_ast_map(&self, opt_uii: &Option) -> bool { - match *self { - PpmSource(PpmNormal) | - PpmSource(PpmEveryBodyLoops) | - PpmSource(PpmIdentified) => opt_uii.is_some(), - - PpmSource(PpmExpanded) | - PpmSource(PpmExpandedIdentified) | - PpmSource(PpmExpandedHygiene) | - PpmHir(_) | - PpmHirTree(_) | - PpmMir | - PpmMirCFG => true, - PpmSource(PpmTyped) => panic!("invalid state"), - } - } - - pub fn needs_analysis(&self) -> bool { - match *self { - PpmMir | PpmMirCFG => true, - _ => false, - } - } -} - -pub fn parse_pretty(sess: &Session, - name: &str, - extended: bool) - -> (PpMode, Option) { - let mut split = name.splitn(2, '='); - let first = split.next().unwrap(); - let opt_second = split.next(); - let first = match (first, extended) { - ("normal", _) => PpmSource(PpmNormal), - ("identified", _) => PpmSource(PpmIdentified), - ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops), - ("expanded", _) => PpmSource(PpmExpanded), - ("expanded,identified", _) => PpmSource(PpmExpandedIdentified), - ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene), - ("hir", true) => PpmHir(PpmNormal), - ("hir,identified", true) => PpmHir(PpmIdentified), - ("hir,typed", true) => PpmHir(PpmTyped), - ("hir-tree", true) => PpmHirTree(PpmNormal), - ("mir", true) => PpmMir, - ("mir-cfg", true) => PpmMirCFG, - _ => { - if extended { - sess.fatal(&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 { - sess.fatal(&format!("argument to `pretty` must be one of `normal`, `expanded`, \ - `identified`, or `expanded,identified`; got {}", - name)); - } - } - }; - let opt_second = opt_second.and_then(|s| s.parse::().ok()); - (first, opt_second) -} - // This slightly awkward construction is to allow for each PpMode to @@ -129,76 +41,74 @@ pub fn parse_pretty(sess: &Session, // (The `use_once_payload` is working around the current lack of once // functions in the compiler.) -impl PpSourceMode { - /// Constructs a `PrinterSupport` object and passes it to `f`. - fn call_with_pp_support<'tcx, A, F>( - &self, - sess: &'tcx Session, - tcx: Option>, - f: F, - ) -> A - where - F: FnOnce(&dyn PrinterSupport) -> A, - { - match *self { - PpmNormal | PpmEveryBodyLoops | PpmExpanded => { - let annotation = NoAnn { - sess, - tcx, - }; - f(&annotation) - } - - PpmIdentified | PpmExpandedIdentified => { - let annotation = IdentifiedAnnotation { - sess, - tcx, - }; - f(&annotation) - } - PpmExpandedHygiene => { - let annotation = HygieneAnnotation { - sess, - }; - f(&annotation) - } - _ => panic!("Should use call_with_pp_support_hir"), +/// Constructs a `PrinterSupport` object and passes it to `f`. +fn call_with_pp_support<'tcx, A, F>( + ppmode: &PpSourceMode, + sess: &'tcx Session, + tcx: Option>, + f: F, +) -> A +where + F: FnOnce(&dyn PrinterSupport) -> A, +{ + match *ppmode { + PpmNormal | PpmEveryBodyLoops | PpmExpanded => { + let annotation = NoAnn { + sess, + tcx, + }; + f(&annotation) } + + PpmIdentified | PpmExpandedIdentified => { + let annotation = IdentifiedAnnotation { + sess, + tcx, + }; + f(&annotation) + } + PpmExpandedHygiene => { + let annotation = HygieneAnnotation { + sess, + }; + f(&annotation) + } + _ => panic!("Should use call_with_pp_support_hir"), } - fn call_with_pp_support_hir(&self, tcx: TyCtxt<'_>, f: F) -> A - where - F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A, - { - match *self { - PpmNormal => { - let annotation = NoAnn { - sess: tcx.sess, - tcx: Some(tcx), - }; - f(&annotation, tcx.hir().forest.krate()) - } - - PpmIdentified => { - let annotation = IdentifiedAnnotation { - sess: tcx.sess, - tcx: Some(tcx), - }; - f(&annotation, tcx.hir().forest.krate()) - } - PpmTyped => { - abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess); - - let empty_tables = ty::TypeckTables::empty(None); - let annotation = TypedAnnotation { - tcx, - tables: Cell::new(&empty_tables) - }; - tcx.dep_graph.with_ignore(|| { - f(&annotation, tcx.hir().forest.krate()) - }) - } - _ => panic!("Should use call_with_pp_support"), +} +fn call_with_pp_support_hir(ppmode: &PpSourceMode, tcx: TyCtxt<'_>, f: F) -> A +where + F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A, +{ + match *ppmode { + PpmNormal => { + let annotation = NoAnn { + sess: tcx.sess, + tcx: Some(tcx), + }; + f(&annotation, tcx.hir().forest.krate()) } + + PpmIdentified => { + let annotation = IdentifiedAnnotation { + sess: tcx.sess, + tcx: Some(tcx), + }; + f(&annotation, tcx.hir().forest.krate()) + } + PpmTyped => { + abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess); + + let empty_tables = ty::TypeckTables::empty(None); + let annotation = TypedAnnotation { + tcx, + tables: Cell::new(&empty_tables) + }; + tcx.dep_graph.with_ignore(|| { + f(&annotation, tcx.hir().forest.krate()) + }) + } + _ => panic!("Should use call_with_pp_support"), } } @@ -480,96 +390,6 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { } } -#[derive(Clone, Debug)] -pub enum UserIdentifiedItem { - ItemViaNode(ast::NodeId), - ItemViaPath(Vec), -} - -impl FromStr for UserIdentifiedItem { - type Err = (); - fn from_str(s: &str) -> Result { - Ok(s.parse() - .map(ast::NodeId::from_u32) - .map(ItemViaNode) - .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect()))) - } -} - -enum NodesMatchingUII<'a> { - NodesMatchingDirect(option::IntoIter), - NodesMatchingSuffix(Box + 'a>), -} - -impl<'a> Iterator for NodesMatchingUII<'a> { - type Item = ast::NodeId; - - fn next(&mut self) -> Option { - match self { - &mut NodesMatchingDirect(ref mut iter) => iter.next(), - &mut NodesMatchingSuffix(ref mut iter) => iter.next(), - } - } - - fn size_hint(&self) -> (usize, Option) { - match self { - &NodesMatchingDirect(ref iter) => iter.size_hint(), - &NodesMatchingSuffix(ref iter) => iter.size_hint(), - } - } -} - -impl UserIdentifiedItem { - fn reconstructed_input(&self) -> String { - match *self { - ItemViaNode(node_id) => node_id.to_string(), - ItemViaPath(ref parts) => parts.join("::"), - } - } - - fn all_matching_node_ids<'a, 'hir>(&'a self, - map: &'a hir_map::Map<'hir>) - -> NodesMatchingUII<'a> { - match *self { - ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), - ItemViaPath(ref parts) => { - NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts))) - } - } - } - - fn to_one_node_id(self, - user_option: &str, - sess: &Session, - map: &hir_map::Map<'_>) - -> ast::NodeId { - let fail_because = |is_wrong_because| -> ast::NodeId { - let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \ - {}, which {}", - user_option, - self.reconstructed_input(), - is_wrong_because); - sess.fatal(&message) - }; - - let mut saw_node = ast::DUMMY_NODE_ID; - let mut seen = 0; - for node in self.all_matching_node_ids(map) { - saw_node = node; - seen += 1; - if seen > 1 { - fail_because("does not resolve uniquely"); - } - } - if seen == 0 { - fail_because("does not resolve to any item"); - } - - assert!(seen == 1); - return saw_node; - } -} - fn get_source(input: &Input, sess: &Session) -> (String, FileName) { let src_name = source_name(input); let src = String::clone(&sess.source_map() @@ -605,7 +425,7 @@ pub fn print_after_parsing(sess: &Session, if let PpmSource(s) = ppm { // Silently ignores an identified node. let out = &mut out; - s.call_with_pp_support(sess, None, move |annotation| { + call_with_pp_support(&s, sess, None, move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); *out = pprust::print_crate(sess.source_map(), @@ -650,7 +470,7 @@ pub fn print_after_hir_lowering<'tcx>( // Silently ignores an identified node. let out = &mut out; let src = src.clone(); - s.call_with_pp_support(tcx.sess, Some(tcx), move |annotation| { + call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); *out = pprust::print_crate(sess.source_map(), @@ -666,7 +486,7 @@ pub fn print_after_hir_lowering<'tcx>( (PpmHir(s), None) => { let out = &mut out; let src = src.clone(); - s.call_with_pp_support_hir(tcx, move |annotation, krate| { + call_with_pp_support_hir(&s, tcx, move |annotation, krate| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); *out = pprust_hir::print_crate(sess.source_map(), @@ -680,7 +500,7 @@ pub fn print_after_hir_lowering<'tcx>( (PpmHirTree(s), None) => { let out = &mut out; - s.call_with_pp_support_hir(tcx, move |_annotation, krate| { + call_with_pp_support_hir(&s, tcx, move |_annotation, krate| { debug!("pretty printing source code {:?}", s); *out = format!("{:#?}", krate); }); @@ -689,7 +509,7 @@ pub fn print_after_hir_lowering<'tcx>( (PpmHir(s), Some(uii)) => { let out = &mut out; let src = src.clone(); - s.call_with_pp_support_hir(tcx, move |annotation, _| { + call_with_pp_support_hir(&s, tcx, move |annotation, _| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); let hir_map = annotation.hir_map().expect("-Z unpretty missing HIR map"); @@ -714,7 +534,7 @@ pub fn print_after_hir_lowering<'tcx>( (PpmHirTree(s), Some(uii)) => { let out = &mut out; - s.call_with_pp_support_hir(tcx, move |_annotation, _krate| { + call_with_pp_support_hir(&s, tcx, move |_annotation, _krate| { debug!("pretty printing source code {:?}", s); for node_id in uii.all_matching_node_ids(tcx.hir()) { let hir_id = tcx.hir().node_to_hir_id(node_id); diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 048b5cff2bf..04a0b0e7619 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -16,6 +16,7 @@ use rustc::traits; use rustc::util::common::{time, ErrorReported}; use rustc::session::Session; use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType}; +use rustc::session::config::{PpMode, PpSourceMode}; use rustc::session::search_paths::PathKind; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_utils::codegen_backend::CodegenBackend; @@ -394,7 +395,11 @@ fn configure_and_expand_inner<'a>( // If we're actually rustdoc then there's no need to actually compile // anything, so switch everything to just looping - if sess.opts.actually_rustdoc { + let mut should_loop = sess.opts.actually_rustdoc; + if let Some((PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops), _)) = sess.opts.pretty { + should_loop |= true; + } + if should_loop { util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate); }