]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/util/pretty.rs
New upstream version 1.27.1+dfsg1
[rustc.git] / src / librustc_mir / util / pretty.rs
CommitLineData
9cc50fc6
SL
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.
4//
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.
10
a7813a04 11use rustc::hir;
7cac9316 12use rustc::hir::def_id::{DefId, LOCAL_CRATE};
c30ab7b3 13use rustc::mir::*;
ff7c6d11
XL
14use rustc::mir::visit::Visitor;
15use rustc::ty::{self, TyCtxt};
7cac9316 16use rustc::ty::item_path;
476ff2be 17use rustc_data_structures::fx::FxHashMap;
ff7c6d11 18use rustc_data_structures::indexed_vec::Idx;
54a0048b
SL
19use std::fmt::Display;
20use std::fs;
9cc50fc6 21use std::io::{self, Write};
ff7c6d11 22use std::path::{Path, PathBuf};
abe05a73
XL
23use super::graphviz::write_mir_fn_graphviz;
24use transform::MirSource;
9cc50fc6
SL
25
26const INDENT: &'static str = " ";
a7813a04 27/// Alignment for lining up comments following MIR statements
ff7c6d11 28pub(crate) const ALIGN: usize = 40;
9cc50fc6 29
abe05a73
XL
30/// An indication of where we are in the control flow graph. Used for printing
31/// extra information in `dump_mir`
32pub enum PassWhere {
33 /// We have not started dumping the control flow graph, but we are about to.
34 BeforeCFG,
35
36 /// We just finished dumping the control flow graph. This is right before EOF
37 AfterCFG,
38
39 /// We are about to start dumping the given basic block.
40 BeforeBlock(BasicBlock),
41
ff7c6d11
XL
42 /// We are just about to dump the given statement or terminator.
43 BeforeLocation(Location),
44
45 /// We just dumped the given statement or terminator.
46 AfterLocation(Location),
abe05a73
XL
47}
48
54a0048b
SL
49/// If the session is properly configured, dumps a human-readable
50/// representation of the mir into:
51///
a7813a04 52/// ```text
7cac9316 53/// rustc.node<node_id>.<pass_num>.<pass_name>.<disambiguator>
54a0048b
SL
54/// ```
55///
56/// Output from this function is controlled by passing `-Z dump-mir=<filter>`,
57/// where `<filter>` takes the following forms:
58///
59/// - `all` -- dump MIR for all fns, all passes, all everything
ff7c6d11
XL
60/// - a filter defined by a set of substrings combined with `&` and `|`
61/// (`&` has higher precedence). At least one of the `|`-separated groups
62/// must match; an `|`-separated group matches if all of its `&`-separated
63/// substrings are matched.
64///
65/// Example:
66///
67/// - `nll` == match if `nll` appears in the name
68/// - `foo & nll` == match if `foo` and `nll` both appear in the name
69/// - `foo & nll | typeck` == match if `foo` and `nll` both appear in the name
70/// or `typeck` appears in the name.
71/// - `foo & nll | bar & typeck` == match if `foo` and `nll` both appear in the name
72/// or `typeck` and `bar` both appear in the name.
73pub fn dump_mir<'a, 'gcx, 'tcx, F>(
74 tcx: TyCtxt<'a, 'gcx, 'tcx>,
0531ce1d 75 pass_num: Option<&dyn Display>,
ff7c6d11 76 pass_name: &str,
0531ce1d 77 disambiguator: &dyn Display,
ff7c6d11
XL
78 source: MirSource,
79 mir: &Mir<'tcx>,
80 extra_data: F,
81) where
0531ce1d 82 F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
abe05a73 83{
7cac9316
XL
84 if !dump_enabled(tcx, pass_name, source) {
85 return;
86 }
87
ff7c6d11
XL
88 let node_path = item_path::with_forced_impl_filename_line(|| {
89 // see notes on #41697 below
abe05a73 90 tcx.item_path_str(source.def_id)
7cac9316 91 });
ff7c6d11
XL
92 dump_matched_mir_node(
93 tcx,
94 pass_num,
95 pass_name,
96 &node_path,
97 disambiguator,
98 source,
99 mir,
100 extra_data,
101 );
7cac9316
XL
102}
103
ff7c6d11
XL
104pub fn dump_enabled<'a, 'gcx, 'tcx>(
105 tcx: TyCtxt<'a, 'gcx, 'tcx>,
106 pass_name: &str,
107 source: MirSource,
108) -> bool {
54a0048b 109 let filters = match tcx.sess.opts.debugging_opts.dump_mir {
7cac9316 110 None => return false,
54a0048b
SL
111 Some(ref filters) => filters,
112 };
ff7c6d11
XL
113 let node_path = item_path::with_forced_impl_filename_line(|| {
114 // see notes on #41697 below
abe05a73 115 tcx.item_path_str(source.def_id)
7cac9316 116 });
ff7c6d11
XL
117 filters.split("|").any(|or_filter| {
118 or_filter.split("&").all(|and_filter| {
119 and_filter == "all" || pass_name.contains(and_filter) || node_path.contains(and_filter)
120 })
121 })
7cac9316 122}
54a0048b 123
7cac9316
XL
124// #41697 -- we use `with_forced_impl_filename_line()` because
125// `item_path_str()` would otherwise trigger `type_of`, and this can
126// run while we are already attempting to evaluate `type_of`.
127
ff7c6d11
XL
128fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(
129 tcx: TyCtxt<'a, 'gcx, 'tcx>,
0531ce1d 130 pass_num: Option<&dyn Display>,
ff7c6d11
XL
131 pass_name: &str,
132 node_path: &str,
0531ce1d 133 disambiguator: &dyn Display,
ff7c6d11
XL
134 source: MirSource,
135 mir: &Mir<'tcx>,
136 mut extra_data: F,
137) where
0531ce1d 138 F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
abe05a73 139{
83c7162d 140 let _: io::Result<()> = do_catch! {{
ff7c6d11
XL
141 let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?;
142 writeln!(file, "// MIR for `{}`", node_path)?;
143 writeln!(file, "// source = {:?}", source)?;
144 writeln!(file, "// pass_name = {}", pass_name)?;
145 writeln!(file, "// disambiguator = {}", disambiguator)?;
146 if let Some(ref layout) = mir.generator_layout {
147 writeln!(file, "// generator_layout = {:?}", layout)?;
148 }
149 writeln!(file, "")?;
150 extra_data(PassWhere::BeforeCFG, &mut file)?;
151 write_mir_fn(tcx, source, mir, &mut extra_data, &mut file)?;
152 extra_data(PassWhere::AfterCFG, &mut file)?;
83c7162d 153 }};
ff7c6d11
XL
154
155 if tcx.sess.opts.debugging_opts.dump_mir_graphviz {
83c7162d 156 let _: io::Result<()> = do_catch! {{
ff7c6d11
XL
157 let mut file =
158 create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?;
159 write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?;
83c7162d 160 }};
ff7c6d11
XL
161 }
162}
163
164/// Returns the path to the filename where we should dump a given MIR.
165/// Also used by other bits of code (e.g., NLL inference) that dump
166/// graphviz data or other things.
167fn dump_path(
168 tcx: TyCtxt<'_, '_, '_>,
169 extension: &str,
0531ce1d 170 pass_num: Option<&dyn Display>,
ff7c6d11 171 pass_name: &str,
0531ce1d 172 disambiguator: &dyn Display,
ff7c6d11
XL
173 source: MirSource,
174) -> PathBuf {
abe05a73
XL
175 let promotion_id = match source.promoted {
176 Some(id) => format!("-{:?}", id),
ff7c6d11 177 None => String::new(),
3157f602
XL
178 };
179
7cac9316
XL
180 let pass_num = if tcx.sess.opts.debugging_opts.dump_mir_exclude_pass_number {
181 format!("")
182 } else {
183 match pass_num {
184 None => format!(".-------"),
abe05a73 185 Some(pass_num) => format!(".{}", pass_num),
7cac9316
XL
186 }
187 };
188
5bcae85e 189 let mut file_path = PathBuf::new();
2c00a5a8 190 file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir));
abe05a73 191
ff7c6d11
XL
192 let item_name = tcx.hir
193 .def_path(source.def_id)
194 .to_filename_friendly_no_crate();
195
196 let file_name = format!(
197 "rustc.{}{}{}.{}.{}.{}",
198 item_name,
199 promotion_id,
200 pass_num,
201 pass_name,
202 disambiguator,
203 extension,
204 );
205
5bcae85e 206 file_path.push(&file_name);
abe05a73 207
ff7c6d11
XL
208 file_path
209}
210
211/// Attempts to open a file where we should dump a given MIR or other
212/// bit of MIR-related data. Used by `mir-dump`, but also by other
213/// bits of code (e.g., NLL inference) that dump graphviz data or
214/// other things, and hence takes the extension as an argument.
215pub(crate) fn create_dump_file(
216 tcx: TyCtxt<'_, '_, '_>,
217 extension: &str,
0531ce1d 218 pass_num: Option<&dyn Display>,
ff7c6d11 219 pass_name: &str,
0531ce1d 220 disambiguator: &dyn Display,
ff7c6d11
XL
221 source: MirSource,
222) -> io::Result<fs::File> {
223 let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, source);
224 if let Some(parent) = file_path.parent() {
225 fs::create_dir_all(parent)?;
abe05a73 226 }
ff7c6d11 227 fs::File::create(&file_path)
54a0048b
SL
228}
229
9cc50fc6 230/// Write out a human-readable textual representation for the given MIR.
ff7c6d11
XL
231pub fn write_mir_pretty<'a, 'gcx, 'tcx>(
232 tcx: TyCtxt<'a, 'gcx, 'tcx>,
233 single: Option<DefId>,
0531ce1d 234 w: &mut dyn Write,
ff7c6d11
XL
235) -> io::Result<()> {
236 writeln!(
237 w,
238 "// WARNING: This output format is intended for human consumers only"
239 )?;
240 writeln!(
241 w,
242 "// and is subject to change without notice. Knock yourself out."
243 )?;
cc61c64b 244
a7813a04 245 let mut first = true;
7cac9316
XL
246 for def_id in dump_mir_def_ids(tcx, single) {
247 let mir = &tcx.optimized_mir(def_id);
5bcae85e 248
a7813a04
XL
249 if first {
250 first = false;
251 } else {
252 // Put empty lines between all items
253 writeln!(w, "")?;
254 }
255
abe05a73 256 write_mir_fn(tcx, MirSource::item(def_id), mir, &mut |_, _| Ok(()), w)?;
a7813a04 257
3157f602 258 for (i, mir) in mir.promoted.iter_enumerated() {
a7813a04 259 writeln!(w, "")?;
abe05a73
XL
260 let src = MirSource {
261 def_id,
ff7c6d11 262 promoted: Some(i),
abe05a73
XL
263 };
264 write_mir_fn(tcx, src, mir, &mut |_, _| Ok(()), w)?;
a7813a04 265 }
54a0048b
SL
266 }
267 Ok(())
268}
9cc50fc6 269
ff7c6d11
XL
270pub fn write_mir_fn<'a, 'gcx, 'tcx, F>(
271 tcx: TyCtxt<'a, 'gcx, 'tcx>,
272 src: MirSource,
273 mir: &Mir<'tcx>,
274 extra_data: &mut F,
0531ce1d 275 w: &mut dyn Write,
ff7c6d11 276) -> io::Result<()>
abe05a73 277where
0531ce1d 278 F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
abe05a73 279{
a7813a04 280 write_mir_intro(tcx, src, mir, w)?;
3157f602 281 for block in mir.basic_blocks().indices() {
abe05a73
XL
282 extra_data(PassWhere::BeforeBlock(block), w)?;
283 write_basic_block(tcx, block, mir, extra_data, w)?;
3157f602
XL
284 if block.index() + 1 != mir.basic_blocks().len() {
285 writeln!(w, "")?;
286 }
54a0048b
SL
287 }
288
54a0048b
SL
289 writeln!(w, "}}")?;
290 Ok(())
9cc50fc6
SL
291}
292
293/// Write out a human-readable textual representation for the given basic block.
ff7c6d11
XL
294pub fn write_basic_block<'cx, 'gcx, 'tcx, F>(
295 tcx: TyCtxt<'cx, 'gcx, 'tcx>,
296 block: BasicBlock,
297 mir: &Mir<'tcx>,
298 extra_data: &mut F,
0531ce1d 299 w: &mut dyn Write,
ff7c6d11 300) -> io::Result<()>
abe05a73 301where
0531ce1d 302 F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>,
abe05a73 303{
3157f602 304 let data = &mir[block];
9cc50fc6
SL
305
306 // Basic block label at the top.
ea8adc8c
XL
307 let cleanup_text = if data.is_cleanup { " // cleanup" } else { "" };
308 let lbl = format!("{}{:?}: {{", INDENT, block);
309 writeln!(w, "{0:1$}{2}", lbl, ALIGN, cleanup_text)?;
9cc50fc6
SL
310
311 // List of statements in the middle.
ff7c6d11
XL
312 let mut current_location = Location {
313 block: block,
314 statement_index: 0,
315 };
9cc50fc6 316 for statement in &data.statements {
ff7c6d11 317 extra_data(PassWhere::BeforeLocation(current_location), w)?;
a7813a04 318 let indented_mir = format!("{0}{0}{1:?};", INDENT, statement);
ff7c6d11
XL
319 writeln!(
320 w,
321 "{:A$} // {:?}: {}",
322 indented_mir,
323 current_location,
324 comment(tcx, statement.source_info),
325 A = ALIGN,
326 )?;
327
328 write_extra(tcx, w, |visitor| {
329 visitor.visit_statement(current_location.block, statement, current_location);
330 })?;
331
332 extra_data(PassWhere::AfterLocation(current_location), w)?;
54a0048b
SL
333
334 current_location.statement_index += 1;
9cc50fc6
SL
335 }
336
337 // Terminator at the bottom.
ff7c6d11 338 extra_data(PassWhere::BeforeLocation(current_location), w)?;
a7813a04 339 let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind);
ff7c6d11
XL
340 writeln!(
341 w,
342 "{:A$} // {:?}: {}",
343 indented_terminator,
344 current_location,
345 comment(tcx, data.terminator().source_info),
346 A = ALIGN,
347 )?;
348
349 write_extra(tcx, w, |visitor| {
350 visitor.visit_terminator(current_location.block, data.terminator(), current_location);
351 })?;
352
353 extra_data(PassWhere::AfterLocation(current_location), w)?;
9cc50fc6 354
5bcae85e 355 writeln!(w, "{}}}", INDENT)
9cc50fc6
SL
356}
357
ff7c6d11
XL
358/// After we print the main statement, we sometimes dump extra
359/// information. There's often a lot of little things "nuzzled up" in
360/// a statement.
361fn write_extra<'cx, 'gcx, 'tcx, F>(
362 tcx: TyCtxt<'cx, 'gcx, 'tcx>,
0531ce1d 363 write: &mut dyn Write,
ff7c6d11
XL
364 mut visit_op: F,
365) -> io::Result<()>
366where
367 F: FnMut(&mut ExtraComments<'cx, 'gcx, 'tcx>),
368{
369 let mut extra_comments = ExtraComments {
370 _tcx: tcx,
371 comments: vec![],
372 };
373 visit_op(&mut extra_comments);
374 for comment in extra_comments.comments {
375 writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?;
376 }
377 Ok(())
378}
379
380struct ExtraComments<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
381 _tcx: TyCtxt<'cx, 'gcx, 'tcx>, // don't need it now, but bet we will soon
382 comments: Vec<String>,
383}
384
385impl<'cx, 'gcx, 'tcx> ExtraComments<'cx, 'gcx, 'tcx> {
386 fn push(&mut self, lines: &str) {
387 for line in lines.split("\n") {
388 self.comments.push(line.to_string());
389 }
390 }
391}
392
393impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> {
394 fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
395 self.super_constant(constant, location);
396 let Constant { span, ty, literal } = constant;
397 self.push(&format!("mir::Constant"));
2c00a5a8
XL
398 self.push(&format!("+ span: {:?}", span));
399 self.push(&format!("+ ty: {:?}", ty));
400 self.push(&format!("+ literal: {:?}", literal));
ff7c6d11
XL
401 }
402
403 fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
404 self.super_const(constant);
405 let ty::Const { ty, val } = constant;
406 self.push(&format!("ty::Const"));
2c00a5a8
XL
407 self.push(&format!("+ ty: {:?}", ty));
408 self.push(&format!("+ val: {:?}", val));
ff7c6d11
XL
409 }
410
411 fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
412 self.super_rvalue(rvalue, location);
413 match rvalue {
414 Rvalue::Aggregate(kind, _) => match **kind {
415 AggregateKind::Closure(def_id, substs) => {
416 self.push(&format!("closure"));
2c00a5a8
XL
417 self.push(&format!("+ def_id: {:?}", def_id));
418 self.push(&format!("+ substs: {:#?}", substs));
ff7c6d11
XL
419 }
420
421 AggregateKind::Generator(def_id, substs, interior) => {
422 self.push(&format!("generator"));
2c00a5a8
XL
423 self.push(&format!("+ def_id: {:?}", def_id));
424 self.push(&format!("+ substs: {:#?}", substs));
425 self.push(&format!("+ interior: {:?}", interior));
ff7c6d11
XL
426 }
427
428 _ => {}
429 },
430
431 _ => {}
432 }
433 }
434}
435
3157f602 436fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String {
ff7c6d11
XL
437 format!(
438 "scope {} at {}",
439 scope.index(),
440 tcx.sess.codemap().span_to_string(span)
441 )
54a0048b
SL
442}
443
c30ab7b3
SL
444/// Prints user-defined variables in a scope tree.
445///
446/// Returns the total number of variables printed.
ff7c6d11
XL
447fn write_scope_tree(
448 tcx: TyCtxt,
449 mir: &Mir,
450 scope_tree: &FxHashMap<VisibilityScope, Vec<VisibilityScope>>,
0531ce1d 451 w: &mut dyn Write,
ff7c6d11
XL
452 parent: VisibilityScope,
453 depth: usize,
454) -> io::Result<()> {
3157f602 455 let indent = depth * INDENT.len();
a7813a04
XL
456
457 let children = match scope_tree.get(&parent) {
458 Some(childs) => childs,
459 None => return Ok(()),
460 };
461
3157f602
XL
462 for &child in children {
463 let data = &mir.visibility_scopes[child];
464 assert_eq!(data.parent_scope, Some(parent));
465 writeln!(w, "{0:1$}scope {2} {{", "", indent, child.index())?;
a7813a04 466
3157f602 467 // User variable types (including the user's name in a comment).
c30ab7b3
SL
468 for local in mir.vars_iter() {
469 let var = &mir.local_decls[local];
cc61c64b
XL
470 let (name, source_info) = if var.source_info.scope == child {
471 (var.name.unwrap(), var.source_info)
c30ab7b3
SL
472 } else {
473 // Not a variable or not declared in this scope.
3157f602 474 continue;
c30ab7b3 475 };
54a0048b 476
3157f602
XL
477 let mut_str = if var.mutability == Mutability::Mut {
478 "mut "
479 } else {
480 ""
481 };
482
483 let indent = indent + INDENT.len();
ff7c6d11
XL
484 let indented_var = format!(
485 "{0:1$}let {2}{3:?}: {4:?};",
486 INDENT,
487 indent,
488 mut_str,
489 local,
490 var.ty
491 );
492 writeln!(
493 w,
494 "{0:1$} // \"{2}\" in {3}",
495 indented_var,
496 ALIGN,
497 name,
498 comment(tcx, source_info)
499 )?;
54a0048b
SL
500 }
501
3157f602 502 write_scope_tree(tcx, mir, scope_tree, w, child, depth + 1)?;
a7813a04 503
3157f602 504 writeln!(w, "{0:1$}}}", "", depth * INDENT.len())?;
54a0048b 505 }
a7813a04 506
54a0048b
SL
507 Ok(())
508}
509
9cc50fc6
SL
510/// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
511/// local variables (both user-defined bindings and compiler temporaries).
ff7c6d11
XL
512pub fn write_mir_intro<'a, 'gcx, 'tcx>(
513 tcx: TyCtxt<'a, 'gcx, 'tcx>,
514 src: MirSource,
515 mir: &Mir,
0531ce1d 516 w: &mut dyn Write,
ff7c6d11 517) -> io::Result<()> {
3157f602 518 write_mir_sig(tcx, src, mir, w)?;
2c00a5a8 519 writeln!(w, "{{")?;
3157f602
XL
520
521 // construct a scope tree and write it out
476ff2be 522 let mut scope_tree: FxHashMap<VisibilityScope, Vec<VisibilityScope>> = FxHashMap();
3157f602
XL
523 for (index, scope_data) in mir.visibility_scopes.iter().enumerate() {
524 if let Some(parent) = scope_data.parent_scope {
ff7c6d11
XL
525 scope_tree
526 .entry(parent)
527 .or_insert(vec![])
528 .push(VisibilityScope::new(index));
3157f602
XL
529 } else {
530 // Only the argument scope has no parent, because it's the root.
531 assert_eq!(index, ARGUMENT_VISIBILITY_SCOPE.index());
532 }
533 }
534
ff7c6d11 535 // Print return place
c30ab7b3
SL
536 let indented_retptr = format!("{}let mut {:?}: {};",
537 INDENT,
ff7c6d11
XL
538 RETURN_PLACE,
539 mir.local_decls[RETURN_PLACE].ty);
540 writeln!(w, "{0:1$} // return place",
c30ab7b3
SL
541 indented_retptr,
542 ALIGN)?;
543
3157f602
XL
544 write_scope_tree(tcx, mir, &scope_tree, w, ARGUMENT_VISIBILITY_SCOPE, 1)?;
545
c30ab7b3
SL
546 write_temp_decls(mir, w)?;
547
548 // Add an empty line before the first block is printed.
549 writeln!(w, "")?;
550
551 Ok(())
3157f602
XL
552}
553
0531ce1d 554fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> io::Result<()> {
abe05a73
XL
555 let id = tcx.hir.as_local_node_id(src.def_id).unwrap();
556 let body_owner_kind = tcx.hir.body_owner_kind(id);
557 match (body_owner_kind, src.promoted) {
558 (_, Some(i)) => write!(w, "{:?} in", i)?,
559 (hir::BodyOwnerKind::Fn, _) => write!(w, "fn")?,
560 (hir::BodyOwnerKind::Const, _) => write!(w, "const")?,
561 (hir::BodyOwnerKind::Static(hir::MutImmutable), _) => write!(w, "static")?,
562 (hir::BodyOwnerKind::Static(hir::MutMutable), _) => write!(w, "static mut")?,
9cc50fc6
SL
563 }
564
ff7c6d11
XL
565 item_path::with_forced_impl_filename_line(|| {
566 // see notes on #41697 elsewhere
abe05a73 567 write!(w, " {}", tcx.item_path_str(src.def_id))
7cac9316 568 })?;
a7813a04 569
abe05a73
XL
570 match (body_owner_kind, src.promoted) {
571 (hir::BodyOwnerKind::Fn, None) => {
ea8adc8c
XL
572 write!(w, "(")?;
573
574 // fn argument types.
575 for (i, arg) in mir.args_iter().enumerate() {
576 if i != 0 {
577 write!(w, ", ")?;
578 }
ff7c6d11 579 write!(w, "{:?}: {}", Place::Local(arg), mir.local_decls[arg].ty)?;
a7813a04 580 }
9cc50fc6 581
2c00a5a8 582 write!(w, ") -> {}", mir.return_ty())?;
ea8adc8c 583 }
ff7c6d11 584 (hir::BodyOwnerKind::Const, _) | (hir::BodyOwnerKind::Static(_), _) | (_, Some(_)) => {
ea8adc8c 585 assert_eq!(mir.arg_count, 0);
2c00a5a8 586 write!(w, ": {} =", mir.return_ty())?;
ea8adc8c 587 }
9cc50fc6 588 }
2c00a5a8
XL
589
590 if let Some(yield_ty) = mir.yield_ty {
591 writeln!(w)?;
592 writeln!(w, "yields {}", yield_ty)?;
593 }
594
595 Ok(())
3157f602 596}
9cc50fc6 597
0531ce1d 598fn write_temp_decls(mir: &Mir, w: &mut dyn Write) -> io::Result<()> {
9cc50fc6 599 // Compiler-introduced temporary types.
c30ab7b3 600 for temp in mir.temps_iter() {
ff7c6d11
XL
601 writeln!(
602 w,
603 "{}let mut {:?}: {};",
604 INDENT,
605 temp,
606 mir.local_decls[temp].ty
607 )?;
a7813a04
XL
608 }
609
9cc50fc6
SL
610 Ok(())
611}
7cac9316
XL
612
613pub fn dump_mir_def_ids(tcx: TyCtxt, single: Option<DefId>) -> Vec<DefId> {
614 if let Some(i) = single {
615 vec![i]
616 } else {
617 tcx.mir_keys(LOCAL_CRATE).iter().cloned().collect()
618 }
619}