1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The various pretty print routines.
13 pub use self::UserIdentifiedItem
::*;
14 pub use self::PpSourceMode
::*;
15 pub use self::PpMode
::*;
16 use self::NodesMatchingUII
::*;
18 use rustc_trans
::back
::link
;
20 use {driver, abort_on_err}
;
22 use rustc
::dep_graph
::DepGraph
;
23 use rustc
::ty
::{self, TyCtxt}
;
25 use rustc
::cfg
::graphviz
::LabelledCFG
;
26 use rustc
::session
::Session
;
27 use rustc
::session
::config
::Input
;
28 use rustc_borrowck
as borrowck
;
29 use rustc_borrowck
::graphviz
as borrowck_dot
;
30 use rustc_resolve
as resolve
;
31 use rustc_metadata
::cstore
::CStore
;
33 use rustc_mir
::pretty
::write_mir_pretty
;
34 use rustc_mir
::graphviz
::write_mir_graphviz
;
36 use syntax
::ast
::{self, BlockCheckMode}
;
38 use syntax
::fold
::{self, Folder}
;
39 use syntax
::print
::{pp, pprust}
;
40 use syntax
::print
::pprust
::PrintState
;
42 use syntax
::util
::small_vector
::SmallVector
;
47 use std
::io
::{self, Write}
;
50 use std
::path
::PathBuf
;
51 use std
::str::FromStr
;
53 use rustc
::hir
::map
as hir_map
;
54 use rustc
::hir
::map
::{blocks, NodePrinter}
;
56 use rustc
::hir
::lowering
::{lower_crate, LoweringContext}
;
57 use rustc
::hir
::print
as pprust_hir
;
59 use rustc
::mir
::mir_map
::MirMap
;
61 #[derive(Copy, Clone, PartialEq, Debug)]
62 pub enum PpSourceMode
{
67 PpmExpandedIdentified
,
72 #[derive(Copy, Clone, PartialEq, Debug)]
73 pub enum PpFlowGraphMode
{
75 /// Drops the labels from the edges in the flowgraph output. This
76 /// is mostly for use in the --unpretty flowgraph run-make tests,
77 /// since the labels are largely uninteresting in those cases and
78 /// have become a pain to maintain.
81 #[derive(Copy, Clone, PartialEq, Debug)]
83 PpmSource(PpSourceMode
),
85 PpmFlowGraph(PpFlowGraphMode
),
90 pub fn parse_pretty(sess
: &Session
,
93 -> (PpMode
, Option
<UserIdentifiedItem
>) {
94 let mut split
= name
.splitn(2, '
='
);
95 let first
= split
.next().unwrap();
96 let opt_second
= split
.next();
97 let first
= match (first
, extended
) {
98 ("normal", _
) => PpmSource(PpmNormal
),
99 ("identified", _
) => PpmSource(PpmIdentified
),
100 ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops
),
101 ("expanded", _
) => PpmSource(PpmExpanded
),
102 ("expanded,identified", _
) => PpmSource(PpmExpandedIdentified
),
103 ("expanded,hygiene", _
) => PpmSource(PpmExpandedHygiene
),
104 ("hir", true) => PpmHir(PpmNormal
),
105 ("hir,identified", true) => PpmHir(PpmIdentified
),
106 ("hir,typed", true) => PpmHir(PpmTyped
),
107 ("mir", true) => PpmMir
,
108 ("mir-cfg", true) => PpmMirCFG
,
109 ("flowgraph", true) => PpmFlowGraph(PpFlowGraphMode
::Default
),
110 ("flowgraph,unlabelled", true) => PpmFlowGraph(PpFlowGraphMode
::UnlabelledEdges
),
113 sess
.fatal(&format
!("argument to `unpretty` must be one of `normal`, \
114 `expanded`, `flowgraph[,unlabelled]=<nodeid>`, \
115 `identified`, `expanded,identified`, `everybody_loops`, \
116 `hir`, `hir,identified`, `hir,typed`, or `mir`; got {}",
119 sess
.fatal(&format
!("argument to `pretty` must be one of `normal`, `expanded`, \
120 `identified`, or `expanded,identified`; got {}",
125 let opt_second
= opt_second
.and_then(|s
| s
.parse
::<UserIdentifiedItem
>().ok());
131 // This slightly awkward construction is to allow for each PpMode to
132 // choose whether it needs to do analyses (which can consume the
133 // Session) and then pass through the session (now attached to the
134 // analysis results) on to the chosen pretty-printer, along with the
137 // Note that since the `&PrinterSupport` is freshly constructed on each
138 // call, it would not make sense to try to attach the lifetime of `self`
139 // to the lifetime of the `&PrinterObject`.
141 // (The `use_once_payload` is working around the current lack of once
142 // functions in the compiler.)
145 /// Constructs a `PrinterSupport` object and passes it to `f`.
146 fn call_with_pp_support
<'tcx
, A
, B
, F
>(&self,
148 ast_map
: Option
<hir_map
::Map
<'tcx
>>,
152 where F
: FnOnce(&PrinterSupport
, B
) -> A
155 PpmNormal
| PpmEveryBodyLoops
| PpmExpanded
=> {
156 let annotation
= NoAnn
{
160 f(&annotation
, payload
)
163 PpmIdentified
| PpmExpandedIdentified
=> {
164 let annotation
= IdentifiedAnnotation
{
168 f(&annotation
, payload
)
170 PpmExpandedHygiene
=> {
171 let annotation
= HygieneAnnotation
{
175 f(&annotation
, payload
)
177 _
=> panic
!("Should use call_with_pp_support_hir"),
180 fn call_with_pp_support_hir
<'tcx
, A
, B
, F
>(&self,
183 ast_map
: &hir_map
::Map
<'tcx
>,
184 arenas
: &'tcx ty
::CtxtArenas
<'tcx
>,
189 where F
: FnOnce(&HirPrinterSupport
, B
, &hir
::Crate
) -> A
193 let annotation
= NoAnn
{
195 ast_map
: Some(ast_map
.clone()),
197 f(&annotation
, payload
, ast_map
.forest
.krate())
201 let annotation
= IdentifiedAnnotation
{
203 ast_map
: Some(ast_map
.clone()),
205 f(&annotation
, payload
, ast_map
.forest
.krate())
208 abort_on_err(driver
::phase_3_run_analysis_passes(sess
,
213 resolve
::MakeGlobMap
::No
,
215 let annotation
= TypedAnnotation
{
218 let _ignore
= tcx
.dep_graph
.in_ignore();
221 ast_map
.forest
.krate())
224 _
=> panic
!("Should use call_with_pp_support"),
229 trait PrinterSupport
<'ast
>: pprust
::PpAnn
{
230 /// Provides a uniform interface for re-extracting a reference to a
231 /// `Session` from a value that now owns it.
232 fn sess
<'a
>(&'a
self) -> &'a Session
;
234 /// Provides a uniform interface for re-extracting a reference to an
235 /// `hir_map::Map` from a value that now owns it.
236 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>>;
238 /// Produces the pretty-print annotation object.
240 /// (Rust does not yet support upcasting from a trait object to
241 /// an object for one of its super-traits.)
242 fn pp_ann
<'a
>(&'a
self) -> &'a pprust
::PpAnn
;
245 trait HirPrinterSupport
<'ast
>: pprust_hir
::PpAnn
{
246 /// Provides a uniform interface for re-extracting a reference to a
247 /// `Session` from a value that now owns it.
248 fn sess
<'a
>(&'a
self) -> &'a Session
;
250 /// Provides a uniform interface for re-extracting a reference to an
251 /// `hir_map::Map` from a value that now owns it.
252 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>>;
254 /// Produces the pretty-print annotation object.
256 /// (Rust does not yet support upcasting from a trait object to
257 /// an object for one of its super-traits.)
258 fn pp_ann
<'a
>(&'a
self) -> &'a pprust_hir
::PpAnn
;
260 /// Computes an user-readable representation of a path, if possible.
261 fn node_path(&self, id
: ast
::NodeId
) -> Option
<String
> {
262 self.ast_map().and_then(|map
| map
.def_path_from_id(id
)).map(|path
| {
263 path
.data
.into_iter().map(|elem
| {
264 elem
.data
.to_string()
265 }).collect
::<Vec
<_
>>().join("::")
272 ast_map
: Option
<hir_map
::Map
<'ast
>>,
275 impl<'ast
> PrinterSupport
<'ast
> for NoAnn
<'ast
> {
276 fn sess
<'a
>(&'a
self) -> &'a Session
{
280 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
281 self.ast_map
.as_ref()
284 fn pp_ann
<'a
>(&'a
self) -> &'a pprust
::PpAnn
{
289 impl<'ast
> HirPrinterSupport
<'ast
> for NoAnn
<'ast
> {
290 fn sess
<'a
>(&'a
self) -> &'a Session
{
294 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
295 self.ast_map
.as_ref()
298 fn pp_ann
<'a
>(&'a
self) -> &'a pprust_hir
::PpAnn
{
303 impl<'ast
> pprust
::PpAnn
for NoAnn
<'ast
> {}
304 impl<'ast
> pprust_hir
::PpAnn
for NoAnn
<'ast
> {}
306 struct IdentifiedAnnotation
<'ast
> {
308 ast_map
: Option
<hir_map
::Map
<'ast
>>,
311 impl<'ast
> PrinterSupport
<'ast
> for IdentifiedAnnotation
<'ast
> {
312 fn sess
<'a
>(&'a
self) -> &'a Session
{
316 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
317 self.ast_map
.as_ref()
320 fn pp_ann
<'a
>(&'a
self) -> &'a pprust
::PpAnn
{
325 impl<'ast
> pprust
::PpAnn
for IdentifiedAnnotation
<'ast
> {
326 fn pre(&self, s
: &mut pprust
::State
, node
: pprust
::AnnNode
) -> io
::Result
<()> {
328 pprust
::NodeExpr(_
) => s
.popen(),
332 fn post(&self, s
: &mut pprust
::State
, node
: pprust
::AnnNode
) -> io
::Result
<()> {
334 pprust
::NodeIdent(_
) | pprust
::NodeName(_
) => Ok(()),
336 pprust
::NodeItem(item
) => {
337 pp
::space(&mut s
.s
)?
;
338 s
.synth_comment(item
.id
.to_string())
340 pprust
::NodeSubItem(id
) => {
341 pp
::space(&mut s
.s
)?
;
342 s
.synth_comment(id
.to_string())
344 pprust
::NodeBlock(blk
) => {
345 pp
::space(&mut s
.s
)?
;
346 s
.synth_comment(format
!("block {}", blk
.id
))
348 pprust
::NodeExpr(expr
) => {
349 pp
::space(&mut s
.s
)?
;
350 s
.synth_comment(expr
.id
.to_string())?
;
353 pprust
::NodePat(pat
) => {
354 pp
::space(&mut s
.s
)?
;
355 s
.synth_comment(format
!("pat {}", pat
.id
))
361 impl<'ast
> HirPrinterSupport
<'ast
> for IdentifiedAnnotation
<'ast
> {
362 fn sess
<'a
>(&'a
self) -> &'a Session
{
366 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
367 self.ast_map
.as_ref()
370 fn pp_ann
<'a
>(&'a
self) -> &'a pprust_hir
::PpAnn
{
375 impl<'ast
> pprust_hir
::PpAnn
for IdentifiedAnnotation
<'ast
> {
376 fn pre(&self, s
: &mut pprust_hir
::State
, node
: pprust_hir
::AnnNode
) -> io
::Result
<()> {
378 pprust_hir
::NodeExpr(_
) => s
.popen(),
382 fn post(&self, s
: &mut pprust_hir
::State
, node
: pprust_hir
::AnnNode
) -> io
::Result
<()> {
384 pprust_hir
::NodeName(_
) => Ok(()),
385 pprust_hir
::NodeItem(item
) => {
386 pp
::space(&mut s
.s
)?
;
387 s
.synth_comment(item
.id
.to_string())
389 pprust_hir
::NodeSubItem(id
) => {
390 pp
::space(&mut s
.s
)?
;
391 s
.synth_comment(id
.to_string())
393 pprust_hir
::NodeBlock(blk
) => {
394 pp
::space(&mut s
.s
)?
;
395 s
.synth_comment(format
!("block {}", blk
.id
))
397 pprust_hir
::NodeExpr(expr
) => {
398 pp
::space(&mut s
.s
)?
;
399 s
.synth_comment(expr
.id
.to_string())?
;
402 pprust_hir
::NodePat(pat
) => {
403 pp
::space(&mut s
.s
)?
;
404 s
.synth_comment(format
!("pat {}", pat
.id
))
410 struct HygieneAnnotation
<'ast
> {
412 ast_map
: Option
<hir_map
::Map
<'ast
>>,
415 impl<'ast
> PrinterSupport
<'ast
> for HygieneAnnotation
<'ast
> {
416 fn sess
<'a
>(&'a
self) -> &'a Session
{
420 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'ast
>> {
421 self.ast_map
.as_ref()
424 fn pp_ann
<'a
>(&'a
self) -> &'a pprust
::PpAnn
{
429 impl<'ast
> pprust
::PpAnn
for HygieneAnnotation
<'ast
> {
430 fn post(&self, s
: &mut pprust
::State
, node
: pprust
::AnnNode
) -> io
::Result
<()> {
432 pprust
::NodeIdent(&ast
::Ident { name: ast::Name(nm), ctxt }
) => {
433 pp
::space(&mut s
.s
)?
;
434 // FIXME #16420: this doesn't display the connections
435 // between syntax contexts
436 s
.synth_comment(format
!("{}#{}", nm
, ctxt
.0))
438 pprust
::NodeName(&ast
::Name(nm
)) => {
439 pp
::space(&mut s
.s
)?
;
440 s
.synth_comment(nm
.to_string())
448 struct TypedAnnotation
<'a
, 'tcx
: 'a
> {
449 tcx
: &'a TyCtxt
<'tcx
>,
452 impl<'b
, 'tcx
> HirPrinterSupport
<'tcx
> for TypedAnnotation
<'b
, 'tcx
> {
453 fn sess
<'a
>(&'a
self) -> &'a Session
{
457 fn ast_map
<'a
>(&'a
self) -> Option
<&'a hir_map
::Map
<'tcx
>> {
461 fn pp_ann
<'a
>(&'a
self) -> &'a pprust_hir
::PpAnn
{
465 fn node_path(&self, id
: ast
::NodeId
) -> Option
<String
> {
466 Some(self.tcx
.node_path_str(id
))
470 impl<'a
, 'tcx
> pprust_hir
::PpAnn
for TypedAnnotation
<'a
, 'tcx
> {
471 fn pre(&self, s
: &mut pprust_hir
::State
, node
: pprust_hir
::AnnNode
) -> io
::Result
<()> {
473 pprust_hir
::NodeExpr(_
) => s
.popen(),
477 fn post(&self, s
: &mut pprust_hir
::State
, node
: pprust_hir
::AnnNode
) -> io
::Result
<()> {
479 pprust_hir
::NodeExpr(expr
) => {
480 pp
::space(&mut s
.s
)?
;
481 pp
::word(&mut s
.s
, "as")?
;
482 pp
::space(&mut s
.s
)?
;
483 pp
::word(&mut s
.s
, &self.tcx
.expr_ty(expr
).to_string())?
;
491 fn gather_flowgraph_variants(sess
: &Session
) -> Vec
<borrowck_dot
::Variant
> {
492 let print_loans
= sess
.opts
.debugging_opts
.flowgraph_print_loans
;
493 let print_moves
= sess
.opts
.debugging_opts
.flowgraph_print_moves
;
494 let print_assigns
= sess
.opts
.debugging_opts
.flowgraph_print_assigns
;
495 let print_all
= sess
.opts
.debugging_opts
.flowgraph_print_all
;
496 let mut variants
= Vec
::new();
497 if print_all
|| print_loans
{
498 variants
.push(borrowck_dot
::Loans
);
500 if print_all
|| print_moves
{
501 variants
.push(borrowck_dot
::Moves
);
503 if print_all
|| print_assigns
{
504 variants
.push(borrowck_dot
::Assigns
);
509 #[derive(Clone, Debug)]
510 pub enum UserIdentifiedItem
{
511 ItemViaNode(ast
::NodeId
),
512 ItemViaPath(Vec
<String
>),
515 impl FromStr
for UserIdentifiedItem
{
517 fn from_str(s
: &str) -> Result
<UserIdentifiedItem
, ()> {
520 .unwrap_or_else(|_
| ItemViaPath(s
.split("::").map(|s
| s
.to_string()).collect())))
524 enum NodesMatchingUII
<'a
, 'ast
: 'a
> {
525 NodesMatchingDirect(option
::IntoIter
<ast
::NodeId
>),
526 NodesMatchingSuffix(hir_map
::NodesMatchingSuffix
<'a
, 'ast
>),
529 impl<'a
, 'ast
> Iterator
for NodesMatchingUII
<'a
, 'ast
> {
530 type Item
= ast
::NodeId
;
532 fn next(&mut self) -> Option
<ast
::NodeId
> {
534 &mut NodesMatchingDirect(ref mut iter
) => iter
.next(),
535 &mut NodesMatchingSuffix(ref mut iter
) => iter
.next(),
540 impl UserIdentifiedItem
{
541 fn reconstructed_input(&self) -> String
{
543 ItemViaNode(node_id
) => node_id
.to_string(),
544 ItemViaPath(ref parts
) => parts
.join("::"),
548 fn all_matching_node_ids
<'a
, 'ast
>(&'a
self,
549 map
: &'a hir_map
::Map
<'ast
>)
550 -> NodesMatchingUII
<'a
, 'ast
> {
552 ItemViaNode(node_id
) => NodesMatchingDirect(Some(node_id
).into_iter()),
553 ItemViaPath(ref parts
) => NodesMatchingSuffix(map
.nodes_matching_suffix(&parts
[..])),
557 fn to_one_node_id(self, user_option
: &str, sess
: &Session
, map
: &hir_map
::Map
) -> ast
::NodeId
{
558 let fail_because
= |is_wrong_because
| -> ast
::NodeId
{
559 let message
= format
!("{} needs NodeId (int) or unique path suffix (b::c::d); got \
562 self.reconstructed_input(),
564 sess
.fatal(&message
[..])
567 let mut saw_node
= ast
::DUMMY_NODE_ID
;
569 for node
in self.all_matching_node_ids(map
) {
573 fail_because("does not resolve uniquely");
577 fail_because("does not resolve to any item");
585 fn needs_ast_map(ppm
: &PpMode
, opt_uii
: &Option
<UserIdentifiedItem
>) -> bool
{
587 PpmSource(PpmNormal
) |
588 PpmSource(PpmEveryBodyLoops
) |
589 PpmSource(PpmIdentified
) => opt_uii
.is_some(),
591 PpmSource(PpmExpanded
) |
592 PpmSource(PpmExpandedIdentified
) |
593 PpmSource(PpmExpandedHygiene
) |
597 PpmFlowGraph(_
) => true,
598 PpmSource(PpmTyped
) => panic
!("invalid state"),
602 fn needs_expansion(ppm
: &PpMode
) -> bool
{
604 PpmSource(PpmNormal
) |
605 PpmSource(PpmEveryBodyLoops
) |
606 PpmSource(PpmIdentified
) => false,
608 PpmSource(PpmExpanded
) |
609 PpmSource(PpmExpandedIdentified
) |
610 PpmSource(PpmExpandedHygiene
) |
614 PpmFlowGraph(_
) => true,
615 PpmSource(PpmTyped
) => panic
!("invalid state"),
619 struct ReplaceBodyWithLoop
{
620 within_static_or_const
: bool
,
623 impl ReplaceBodyWithLoop
{
624 fn new() -> ReplaceBodyWithLoop
{
625 ReplaceBodyWithLoop { within_static_or_const: false }
629 impl fold
::Folder
for ReplaceBodyWithLoop
{
630 fn fold_item_kind(&mut self, i
: ast
::ItemKind
) -> ast
::ItemKind
{
632 ast
::ItemKind
::Static(..) | ast
::ItemKind
::Const(..) => {
633 self.within_static_or_const
= true;
634 let ret
= fold
::noop_fold_item_kind(i
, self);
635 self.within_static_or_const
= false;
639 fold
::noop_fold_item_kind(i
, self)
644 fn fold_trait_item(&mut self, i
: ast
::TraitItem
) -> SmallVector
<ast
::TraitItem
> {
646 ast
::TraitItemKind
::Const(..) => {
647 self.within_static_or_const
= true;
648 let ret
= fold
::noop_fold_trait_item(i
, self);
649 self.within_static_or_const
= false;
652 _
=> fold
::noop_fold_trait_item(i
, self),
656 fn fold_impl_item(&mut self, i
: ast
::ImplItem
) -> SmallVector
<ast
::ImplItem
> {
658 ast
::ImplItemKind
::Const(..) => {
659 self.within_static_or_const
= true;
660 let ret
= fold
::noop_fold_impl_item(i
, self);
661 self.within_static_or_const
= false;
664 _
=> fold
::noop_fold_impl_item(i
, self),
668 fn fold_block(&mut self, b
: P
<ast
::Block
>) -> P
<ast
::Block
> {
669 fn expr_to_block(rules
: ast
::BlockCheckMode
, e
: Option
<P
<ast
::Expr
>>) -> P
<ast
::Block
> {
674 id
: ast
::DUMMY_NODE_ID
,
675 span
: codemap
::DUMMY_SP
,
679 if !self.within_static_or_const
{
681 let empty_block
= expr_to_block(BlockCheckMode
::Default
, None
);
682 let loop_expr
= P(ast
::Expr
{
683 node
: ast
::ExprKind
::Loop(empty_block
, None
),
684 id
: ast
::DUMMY_NODE_ID
,
685 span
: codemap
::DUMMY_SP
,
689 expr_to_block(b
.rules
, Some(loop_expr
))
692 fold
::noop_fold_block(b
, self)
696 // in general the pretty printer processes unexpanded code, so
697 // we override the default `fold_mac` method which panics.
698 fn fold_mac(&mut self, mac
: ast
::Mac
) -> ast
::Mac
{
699 fold
::noop_fold_mac(mac
, self)
703 pub fn pretty_print_input(sess
: Session
,
705 cfg
: ast
::CrateConfig
,
708 opt_uii
: Option
<UserIdentifiedItem
>,
709 ofile
: Option
<PathBuf
>) {
710 let krate
= panictry
!(driver
::phase_1_parse_input(&sess
, cfg
, input
));
712 let krate
= if let PpmSource(PpmEveryBodyLoops
) = ppm
{
713 let mut fold
= ReplaceBodyWithLoop
::new();
714 fold
.fold_crate(krate
)
719 let id
= link
::find_crate_name(Some(&sess
), &krate
.attrs
, input
);
721 let is_expanded
= needs_expansion(&ppm
);
722 let compute_ast_map
= needs_ast_map(&ppm
, &opt_uii
);
723 let krate
= if compute_ast_map
{
724 match driver
::phase_2_configure_and_expand(&sess
, &cstore
, krate
, &id
[..], None
) {
726 Ok(k
) => driver
::assign_node_ids(&sess
, k
),
732 // There is some twisted, god-forsaken tangle of lifetimes here which makes
733 // the ordering of stuff super-finicky.
735 let lcx
= LoweringContext
::new(&sess
, Some(&krate
));
736 let arenas
= ty
::CtxtArenas
::new();
737 let dep_graph
= DepGraph
::new(false);
738 let _ignore
= dep_graph
.in_ignore();
739 let ast_map
= if compute_ast_map
{
740 hir_forest
= hir_map
::Forest
::new(lower_crate(&lcx
, &krate
), dep_graph
.clone());
741 let map
= driver
::make_map(&sess
, &mut hir_forest
);
747 let src_name
= driver
::source_name(input
);
748 let src
= sess
.codemap()
749 .get_filemap(&src_name
[..])
755 let mut rdr
= &src
[..];
757 let mut out
= Vec
::new();
759 match (ppm
, opt_uii
) {
760 (PpmSource(s
), _
) => {
761 // Silently ignores an identified node.
762 let out
: &mut Write
= &mut out
;
763 s
.call_with_pp_support(&sess
, ast_map
, box out
, |annotation
, out
| {
764 debug
!("pretty printing source code {:?}", s
);
765 let sess
= annotation
.sess();
766 pprust
::print_crate(sess
.codemap(),
769 src_name
.to_string(),
777 (PpmHir(s
), None
) => {
778 let out
: &mut Write
= &mut out
;
779 s
.call_with_pp_support_hir(&sess
,
785 |annotation
, out
, krate
| {
786 debug
!("pretty printing source code {:?}", s
);
787 let sess
= annotation
.sess();
788 pprust_hir
::print_crate(sess
.codemap(),
791 src_name
.to_string(),
799 (PpmHir(s
), Some(uii
)) => {
800 let out
: &mut Write
= &mut out
;
801 s
.call_with_pp_support_hir(&sess
,
807 |annotation
, (out
,uii
), _
| {
808 debug
!("pretty printing source code {:?}", s
);
809 let sess
= annotation
.sess();
810 let ast_map
= annotation
.ast_map().expect("--unpretty missing HIR map");
812 pprust_hir
::State
::new_from_input(sess
.codemap(),
814 src_name
.to_string(),
819 Some(ast_map
.krate()));
820 for node_id
in uii
.all_matching_node_ids(ast_map
) {
821 let node
= ast_map
.get(node_id
);
822 pp_state
.print_node(&node
)?
;
823 pp
::space(&mut pp_state
.s
)?
;
824 let path
= annotation
.node_path(node_id
)
825 .expect("--unpretty missing node paths");
826 pp_state
.synth_comment(path
)?
;
827 pp
::hardbreak(&mut pp_state
.s
)?
;
829 pp
::eof(&mut pp_state
.s
)
833 (pp_type@PpmMir
, uii
) | (pp_type@PpmMirCFG
, uii
) => {
834 let ast_map
= ast_map
.expect("--unpretty missing ast_map");
835 let nodeid
= if let Some(uii
) = uii
{
836 debug
!("pretty printing MIR for {:?}", uii
);
837 Some(uii
.to_one_node_id("--unpretty", &sess
, &ast_map
))
839 debug
!("pretty printing MIR for whole crate");
842 abort_on_err(driver
::phase_3_run_analysis_passes(&sess
,
847 resolve
::MakeGlobMap
::No
,
848 |tcx
, mir_map
, _
, _
| {
849 if let Some(mir_map
) = mir_map
{
850 if let Some(nodeid
) = nodeid
{
851 let mir
= mir_map
.map
.get(&nodeid
).unwrap_or_else(|| {
852 sess
.fatal(&format
!("no MIR map entry for node {}", nodeid
))
855 PpmMir
=> write_mir_pretty(tcx
, iter
::once((&nodeid
, mir
)), &mut out
),
856 _
=> write_mir_graphviz(tcx
, iter
::once((&nodeid
, mir
)), &mut out
)
860 PpmMir
=> write_mir_pretty(tcx
, mir_map
.map
.iter(), &mut out
),
861 _
=> write_mir_graphviz(tcx
, mir_map
.map
.iter(), &mut out
)
869 (PpmFlowGraph(mode
), opt_uii
) => {
870 debug
!("pretty printing flow graph for {:?}", opt_uii
);
871 let uii
= opt_uii
.unwrap_or_else(|| {
872 sess
.fatal(&format
!("`pretty flowgraph=..` needs NodeId (int) or
874 unique path suffix (b::c::d)"))
877 let ast_map
= ast_map
.expect("--pretty flowgraph missing ast_map");
878 let nodeid
= uii
.to_one_node_id("--pretty", &sess
, &ast_map
);
880 let node
= ast_map
.find(nodeid
).unwrap_or_else(|| {
881 sess
.fatal(&format
!("--pretty flowgraph couldn't find id: {}", nodeid
))
884 let code
= blocks
::Code
::from_node(node
);
885 let out
: &mut Write
= &mut out
;
888 let variants
= gather_flowgraph_variants(&sess
);
889 abort_on_err(driver
::phase_3_run_analysis_passes(&sess
,
894 resolve
::MakeGlobMap
::No
,
895 |tcx
, mir_map
, _
, _
| {
896 print_flowgraph(variants
,
905 let message
= format
!("--pretty=flowgraph needs block, fn, or method; got \
909 // point to what was found, if there's an
911 match ast_map
.opt_span(nodeid
) {
912 Some(sp
) => sess
.span_fatal(sp
, &message
[..]),
913 None
=> sess
.fatal(&message
[..]),
922 None
=> print
!("{}", String
::from_utf8(out
).unwrap()),
924 match File
::create(&p
) {
925 Ok(mut w
) => w
.write_all(&out
).unwrap(),
926 Err(e
) => panic
!("print-print failed to open {} due to {}", p
.display(), e
),
932 fn print_flowgraph
<'tcx
, W
: Write
>(variants
: Vec
<borrowck_dot
::Variant
>,
934 mir_map
: Option
<&MirMap
<'tcx
>>,
936 mode
: PpFlowGraphMode
,
939 let cfg
= match code
{
940 blocks
::BlockCode(block
) => cfg
::CFG
::new(tcx
, &block
),
941 blocks
::FnLikeCode(fn_like
) => cfg
::CFG
::new(tcx
, &fn_like
.body()),
943 let labelled_edges
= mode
!= PpFlowGraphMode
::UnlabelledEdges
;
944 let lcfg
= LabelledCFG
{
947 name
: format
!("node_{}", code
.id()),
948 labelled_edges
: labelled_edges
,
952 _
if variants
.is_empty() => {
953 let r
= dot
::render(&lcfg
, &mut out
);
954 return expand_err_details(r
);
956 blocks
::BlockCode(_
) => {
957 tcx
.sess
.err("--pretty flowgraph with -Z flowgraph-print annotations requires \
961 blocks
::FnLikeCode(fn_like
) => {
962 let (bccx
, analysis_data
) =
963 borrowck
::build_borrowck_dataflow_data_for_fn(tcx
,
965 fn_like
.to_fn_parts(),
968 let lcfg
= borrowck_dot
::DataflowLabeller
{
971 borrowck_ctxt
: &bccx
,
972 analysis_data
: &analysis_data
,
974 let r
= dot
::render(&lcfg
, &mut out
);
975 return expand_err_details(r
);
979 fn expand_err_details(r
: io
::Result
<()>) -> io
::Result
<()> {
981 io
::Error
::new(io
::ErrorKind
::Other
,
982 &format
!("graphviz::render failed: {}", ioerr
)[..])