]> git.proxmox.com Git - rustc.git/blame - src/librustc_driver/pretty.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc_driver / pretty.rs
CommitLineData
0731742a 1//! The various pretty-printing routines.
1a4d82fc 2
0731742a
XL
3use rustc::hir;
4use rustc::hir::map as hir_map;
0731742a 5use rustc::hir::print as pprust_hir;
532ac7d7 6use rustc::hir::def_id::LOCAL_CRATE;
1a4d82fc 7use rustc::session::Session;
60c5eb7d 8use rustc::session::config::{PpMode, PpSourceMode, Input};
532ac7d7
XL
9use rustc::ty::{self, TyCtxt};
10use rustc::util::common::ErrorReported;
cc61c64b 11use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};
7453a54e 12
532ac7d7 13use syntax::ast;
041b39d2 14use syntax::print::{pprust};
532ac7d7 15use syntax_pos::FileName;
1a4d82fc 16
32a655c1 17use std::cell::Cell;
c34b1796 18use std::fs::File;
e74abb32 19use std::io::Write;
a7813a04 20use std::path::Path;
1a4d82fc 21
0731742a
XL
22pub use self::PpSourceMode::*;
23pub use self::PpMode::*;
532ac7d7
XL
24use crate::abort_on_err;
25
1a4d82fc
JJ
26// This slightly awkward construction is to allow for each PpMode to
27// choose whether it needs to do analyses (which can consume the
28// Session) and then pass through the session (now attached to the
29// analysis results) on to the chosen pretty-printer, along with the
30// `&PpAnn` object.
31//
32// Note that since the `&PrinterSupport` is freshly constructed on each
33// call, it would not make sense to try to attach the lifetime of `self`
34// to the lifetime of the `&PrinterObject`.
35//
36// (The `use_once_payload` is working around the current lack of once
37// functions in the compiler.)
38
60c5eb7d
XL
39/// Constructs a `PrinterSupport` object and passes it to `f`.
40fn call_with_pp_support<'tcx, A, F>(
41 ppmode: &PpSourceMode,
42 sess: &'tcx Session,
43 tcx: Option<TyCtxt<'tcx>>,
44 f: F,
45) -> A
46where
47 F: FnOnce(&dyn PrinterSupport) -> A,
48{
49 match *ppmode {
50 PpmNormal | PpmEveryBodyLoops | PpmExpanded => {
51 let annotation = NoAnn {
52 sess,
53 tcx,
54 };
55 f(&annotation)
56 }
1a4d82fc 57
60c5eb7d
XL
58 PpmIdentified | PpmExpandedIdentified => {
59 let annotation = IdentifiedAnnotation {
60 sess,
61 tcx,
62 };
63 f(&annotation)
64 }
65 PpmExpandedHygiene => {
66 let annotation = HygieneAnnotation {
67 sess,
68 };
69 f(&annotation)
70 }
71 _ => panic!("Should use call_with_pp_support_hir"),
72 }
73}
74fn call_with_pp_support_hir<A, F>(ppmode: &PpSourceMode, tcx: TyCtxt<'_>, f: F) -> A
75where
76 F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A,
77{
78 match *ppmode {
79 PpmNormal => {
80 let annotation = NoAnn {
81 sess: tcx.sess,
82 tcx: Some(tcx),
83 };
84 f(&annotation, tcx.hir().forest.krate())
e9174d1e 85 }
e9174d1e 86
60c5eb7d
XL
87 PpmIdentified => {
88 let annotation = IdentifiedAnnotation {
89 sess: tcx.sess,
90 tcx: Some(tcx),
91 };
92 f(&annotation, tcx.hir().forest.krate())
93 }
94 PpmTyped => {
95 abort_on_err(tcx.analysis(LOCAL_CRATE), tcx.sess);
96
97 let empty_tables = ty::TypeckTables::empty(None);
98 let annotation = TypedAnnotation {
99 tcx,
100 tables: Cell::new(&empty_tables)
101 };
102 tcx.dep_graph.with_ignore(|| {
532ac7d7 103 f(&annotation, tcx.hir().forest.krate())
60c5eb7d 104 })
1a4d82fc 105 }
60c5eb7d 106 _ => panic!("Should use call_with_pp_support"),
1a4d82fc
JJ
107 }
108}
109
32a655c1 110trait PrinterSupport: pprust::PpAnn {
1a4d82fc
JJ
111 /// Provides a uniform interface for re-extracting a reference to a
112 /// `Session` from a value that now owns it.
416331ca 113 fn sess(&self) -> &Session;
1a4d82fc 114
1a4d82fc
JJ
115 /// Produces the pretty-print annotation object.
116 ///
117 /// (Rust does not yet support upcasting from a trait object to
118 /// an object for one of its super-traits.)
8faf50e0 119 fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn;
1a4d82fc
JJ
120}
121
32a655c1 122trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
e9174d1e
SL
123 /// Provides a uniform interface for re-extracting a reference to a
124 /// `Session` from a value that now owns it.
416331ca 125 fn sess(&self) -> &Session;
e9174d1e
SL
126
127 /// Provides a uniform interface for re-extracting a reference to an
128 /// `hir_map::Map` from a value that now owns it.
32a655c1 129 fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>>;
e9174d1e
SL
130
131 /// Produces the pretty-print annotation object.
132 ///
133 /// (Rust does not yet support upcasting from a trait object to
134 /// an object for one of its super-traits.)
8faf50e0 135 fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn;
54a0048b
SL
136
137 /// Computes an user-readable representation of a path, if possible.
dc9dc135 138 fn node_path(&self, id: hir::HirId) -> Option<String> {
48663c56 139 self.hir_map().and_then(|map| {
dc9dc135 140 map.def_path_from_hir_id(id)
48663c56 141 }).map(|path| {
c30ab7b3
SL
142 path.data
143 .into_iter()
144 .map(|elem| elem.data.to_string())
145 .collect::<Vec<_>>()
146 .join("::")
54a0048b
SL
147 })
148 }
e9174d1e
SL
149}
150
32a655c1
SL
151struct NoAnn<'hir> {
152 sess: &'hir Session,
dc9dc135 153 tcx: Option<TyCtxt<'hir>>,
1a4d82fc
JJ
154}
155
32a655c1 156impl<'hir> PrinterSupport for NoAnn<'hir> {
416331ca 157 fn sess(&self) -> &Session {
92a42be0
SL
158 self.sess
159 }
1a4d82fc 160
8faf50e0 161 fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn {
92a42be0
SL
162 self
163 }
1a4d82fc
JJ
164}
165
32a655c1 166impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
416331ca 167 fn sess(&self) -> &Session {
92a42be0
SL
168 self.sess
169 }
e9174d1e 170
32a655c1 171 fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
532ac7d7 172 self.tcx.map(|tcx| tcx.hir())
e9174d1e
SL
173 }
174
8faf50e0 175 fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
92a42be0
SL
176 self
177 }
e9174d1e
SL
178}
179
32a655c1
SL
180impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
181impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
416331ca 182 fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
532ac7d7
XL
183 if let Some(tcx) = self.tcx {
184 pprust_hir::PpAnn::nested(tcx.hir(), state, nested)
32a655c1
SL
185 }
186 }
187}
1a4d82fc 188
32a655c1
SL
189struct IdentifiedAnnotation<'hir> {
190 sess: &'hir Session,
dc9dc135 191 tcx: Option<TyCtxt<'hir>>,
1a4d82fc
JJ
192}
193
32a655c1 194impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
416331ca 195 fn sess(&self) -> &Session {
92a42be0
SL
196 self.sess
197 }
1a4d82fc 198
8faf50e0 199 fn pp_ann<'a>(&'a self) -> &'a dyn pprust::PpAnn {
92a42be0
SL
200 self
201 }
1a4d82fc
JJ
202}
203
32a655c1 204impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
416331ca 205 fn pre(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
1a4d82fc 206 match node {
b7449926 207 pprust::AnnNode::Expr(_) => s.popen(),
416331ca 208 _ => {}
1a4d82fc
JJ
209 }
210 }
416331ca 211 fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
1a4d82fc 212 match node {
e1599b0c 213 pprust::AnnNode::Crate(_) |
b7449926 214 pprust::AnnNode::Ident(_) |
416331ca 215 pprust::AnnNode::Name(_) => {},
1a4d82fc 216
b7449926 217 pprust::AnnNode::Item(item) => {
416331ca 218 s.s.space();
1a4d82fc
JJ
219 s.synth_comment(item.id.to_string())
220 }
b7449926 221 pprust::AnnNode::SubItem(id) => {
416331ca 222 s.s.space();
c34b1796
AL
223 s.synth_comment(id.to_string())
224 }
b7449926 225 pprust::AnnNode::Block(blk) => {
416331ca 226 s.s.space();
1a4d82fc
JJ
227 s.synth_comment(format!("block {}", blk.id))
228 }
b7449926 229 pprust::AnnNode::Expr(expr) => {
416331ca
XL
230 s.s.space();
231 s.synth_comment(expr.id.to_string());
1a4d82fc
JJ
232 s.pclose()
233 }
b7449926 234 pprust::AnnNode::Pat(pat) => {
416331ca
XL
235 s.s.space();
236 s.synth_comment(format!("pat {}", pat.id));
1a4d82fc
JJ
237 }
238 }
239 }
240}
241
32a655c1 242impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
416331ca 243 fn sess(&self) -> &Session {
92a42be0
SL
244 self.sess
245 }
e9174d1e 246
32a655c1 247 fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'hir>> {
532ac7d7 248 self.tcx.map(|tcx| tcx.hir())
e9174d1e
SL
249 }
250
8faf50e0 251 fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
92a42be0
SL
252 self
253 }
e9174d1e
SL
254}
255
32a655c1 256impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
416331ca 257 fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
532ac7d7
XL
258 if let Some(ref tcx) = self.tcx {
259 pprust_hir::PpAnn::nested(tcx.hir(), state, nested)
32a655c1
SL
260 }
261 }
416331ca 262 fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
e9174d1e 263 match node {
b7449926 264 pprust_hir::AnnNode::Expr(_) => s.popen(),
416331ca 265 _ => {}
e9174d1e
SL
266 }
267 }
416331ca 268 fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
e9174d1e 269 match node {
416331ca 270 pprust_hir::AnnNode::Name(_) => {},
b7449926 271 pprust_hir::AnnNode::Item(item) => {
416331ca
XL
272 s.s.space();
273 s.synth_comment(format!("hir_id: {}", item.hir_id));
e9174d1e 274 }
b7449926 275 pprust_hir::AnnNode::SubItem(id) => {
416331ca
XL
276 s.s.space();
277 s.synth_comment(id.to_string());
e9174d1e 278 }
b7449926 279 pprust_hir::AnnNode::Block(blk) => {
416331ca
XL
280 s.s.space();
281 s.synth_comment(format!("block hir_id: {}", blk.hir_id));
e9174d1e 282 }
b7449926 283 pprust_hir::AnnNode::Expr(expr) => {
416331ca
XL
284 s.s.space();
285 s.synth_comment(format!("expr hir_id: {}", expr.hir_id));
286 s.pclose();
e9174d1e 287 }
b7449926 288 pprust_hir::AnnNode::Pat(pat) => {
416331ca
XL
289 s.s.space();
290 s.synth_comment(format!("pat hir_id: {}", pat.hir_id));
291 }
292 pprust_hir::AnnNode::Arm(arm) => {
293 s.s.space();
294 s.synth_comment(format!("arm hir_id: {}", arm.hir_id));
e9174d1e
SL
295 }
296 }
297 }
298}
299
32a655c1
SL
300struct HygieneAnnotation<'a> {
301 sess: &'a Session
1a4d82fc
JJ
302}
303
32a655c1
SL
304impl<'a> PrinterSupport for HygieneAnnotation<'a> {
305 fn sess(&self) -> &Session {
92a42be0
SL
306 self.sess
307 }
1a4d82fc 308
8faf50e0 309 fn pp_ann(&self) -> &dyn pprust::PpAnn {
92a42be0
SL
310 self
311 }
1a4d82fc
JJ
312}
313
32a655c1 314impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
416331ca 315 fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
1a4d82fc 316 match node {
b7449926 317 pprust::AnnNode::Ident(&ast::Ident { name, span }) => {
416331ca 318 s.s.space();
83c7162d 319 s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
1a4d82fc 320 }
b7449926 321 pprust::AnnNode::Name(&name) => {
416331ca 322 s.s.space();
476ff2be 323 s.synth_comment(name.as_u32().to_string())
1a4d82fc 324 }
e1599b0c
XL
325 pprust::AnnNode::Crate(_) => {
326 s.s.hardbreak();
327 let verbose = self.sess.verbose();
328 s.synth_comment(syntax_pos::hygiene::debug_hygiene_data(verbose));
329 s.s.hardbreak_if_not_bol();
330 }
416331ca 331 _ => {}
1a4d82fc
JJ
332 }
333 }
334}
335
dc9dc135
XL
336struct TypedAnnotation<'a, 'tcx> {
337 tcx: TyCtxt<'tcx>,
32a655c1 338 tables: Cell<&'a ty::TypeckTables<'tcx>>,
1a4d82fc
JJ
339}
340
e9174d1e 341impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
416331ca 342 fn sess(&self) -> &Session {
92a42be0
SL
343 &self.tcx.sess
344 }
1a4d82fc 345
32a655c1 346 fn hir_map<'a>(&'a self) -> Option<&'a hir_map::Map<'tcx>> {
0731742a 347 Some(&self.tcx.hir())
1a4d82fc
JJ
348 }
349
8faf50e0 350 fn pp_ann<'a>(&'a self) -> &'a dyn pprust_hir::PpAnn {
92a42be0
SL
351 self
352 }
54a0048b 353
dc9dc135 354 fn node_path(&self, id: hir::HirId) -> Option<String> {
416331ca 355 Some(self.tcx.def_path_str(self.tcx.hir().local_def_id(id)))
54a0048b 356 }
1a4d82fc
JJ
357}
358
e9174d1e 359impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
416331ca 360 fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
32a655c1
SL
361 let old_tables = self.tables.get();
362 if let pprust_hir::Nested::Body(id) = nested {
363 self.tables.set(self.tcx.body_tables(id));
364 }
416331ca 365 pprust_hir::PpAnn::nested(self.tcx.hir(), state, nested);
32a655c1 366 self.tables.set(old_tables);
32a655c1 367 }
416331ca 368 fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
1a4d82fc 369 match node {
b7449926 370 pprust_hir::AnnNode::Expr(_) => s.popen(),
416331ca 371 _ => {}
1a4d82fc
JJ
372 }
373 }
416331ca 374 fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
1a4d82fc 375 match node {
b7449926 376 pprust_hir::AnnNode::Expr(expr) => {
416331ca
XL
377 s.s.space();
378 s.s.word("as");
379 s.s.space();
380 s.s.word(self.tables.get().expr_ty(expr).to_string());
381 s.pclose();
1a4d82fc 382 }
416331ca 383 _ => {},
1a4d82fc
JJ
384 }
385 }
386}
387
416331ca 388fn get_source(input: &Input, sess: &Session) -> (String, FileName) {
60c5eb7d 389 let src_name = input.source_name();
416331ca 390 let src = String::clone(&sess.source_map()
b7449926 391 .get_source_file(&src_name)
c30ab7b3
SL
392 .unwrap()
393 .src
394 .as_ref()
416331ca 395 .unwrap());
a7813a04
XL
396 (src, src_name)
397}
398
399fn write_output(out: Vec<u8>, ofile: Option<&Path>) {
400 match ofile {
401 None => print!("{}", String::from_utf8(out).unwrap()),
402 Some(p) => {
403 match File::create(p) {
404 Ok(mut w) => w.write_all(&out).unwrap(),
405 Err(e) => panic!("print-print failed to open {} due to {}", p.display(), e),
406 }
407 }
408 }
409}
1a4d82fc 410
a7813a04
XL
411pub fn print_after_parsing(sess: &Session,
412 input: &Input,
413 krate: &ast::Crate,
414 ppm: PpMode,
415 ofile: Option<&Path>) {
a7813a04
XL
416 let (src, src_name) = get_source(input, sess);
417
416331ca 418 let mut out = String::new();
a7813a04
XL
419
420 if let PpmSource(s) = ppm {
421 // Silently ignores an identified node.
416331ca 422 let out = &mut out;
60c5eb7d 423 call_with_pp_support(&s, sess, None, move |annotation| {
0bf4aa26
XL
424 debug!("pretty printing source code {:?}", s);
425 let sess = annotation.sess();
416331ca 426 *out = pprust::print_crate(sess.source_map(),
0bf4aa26
XL
427 &sess.parse_sess,
428 krate,
429 src_name,
416331ca 430 src,
0bf4aa26
XL
431 annotation.pp_ann(),
432 false)
416331ca 433 })
a7813a04
XL
434 } else {
435 unreachable!();
436 };
437
416331ca 438 write_output(out.into_bytes(), ofile);
a7813a04
XL
439}
440
532ac7d7 441pub fn print_after_hir_lowering<'tcx>(
dc9dc135 442 tcx: TyCtxt<'tcx>,
532ac7d7
XL
443 input: &Input,
444 krate: &ast::Crate,
445 ppm: PpMode,
dc9dc135
XL
446 ofile: Option<&Path>,
447) {
a7813a04 448 if ppm.needs_analysis() {
532ac7d7
XL
449 abort_on_err(print_with_analysis(
450 tcx,
451 ppm,
532ac7d7
XL
452 ofile
453 ), tcx.sess);
a7813a04
XL
454 return;
455 }
456
532ac7d7 457 let (src, src_name) = get_source(input, tcx.sess);
a7813a04 458
416331ca 459 let mut out = String::new();
1a4d82fc 460
60c5eb7d
XL
461 match ppm {
462 PpmSource(s) => {
c30ab7b3 463 // Silently ignores an identified node.
416331ca
XL
464 let out = &mut out;
465 let src = src.clone();
60c5eb7d 466 call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| {
c30ab7b3
SL
467 debug!("pretty printing source code {:?}", s);
468 let sess = annotation.sess();
416331ca 469 *out = pprust::print_crate(sess.source_map(),
32a655c1 470 &sess.parse_sess,
c30ab7b3 471 krate,
ff7c6d11 472 src_name,
416331ca 473 src,
c30ab7b3
SL
474 annotation.pp_ann(),
475 true)
476 })
477 }
1a4d82fc 478
60c5eb7d 479 PpmHir(s) => {
416331ca
XL
480 let out = &mut out;
481 let src = src.clone();
60c5eb7d 482 call_with_pp_support_hir(&s, tcx, move |annotation, krate| {
c30ab7b3
SL
483 debug!("pretty printing source code {:?}", s);
484 let sess = annotation.sess();
416331ca 485 *out = pprust_hir::print_crate(sess.source_map(),
32a655c1 486 &sess.parse_sess,
c30ab7b3 487 krate,
ff7c6d11 488 src_name,
416331ca 489 src,
48663c56 490 annotation.pp_ann())
c30ab7b3
SL
491 })
492 }
e9174d1e 493
60c5eb7d 494 PpmHirTree(s) => {
416331ca 495 let out = &mut out;
60c5eb7d 496 call_with_pp_support_hir(&s, tcx, move |_annotation, krate| {
ff7c6d11 497 debug!("pretty printing source code {:?}", s);
416331ca
XL
498 *out = format!("{:#?}", krate);
499 });
ff7c6d11
XL
500 }
501
c30ab7b3
SL
502 _ => unreachable!(),
503 }
a7813a04 504
416331ca 505 write_output(out.into_bytes(), ofile);
a7813a04
XL
506}
507
508// In an ideal world, this would be a public function called by the driver after
9fa01778 509// analysis is performed. However, we want to call `phase_3_run_analysis_passes`
a7813a04
XL
510// with a different callback than the standard driver, so that isn't easy.
511// Instead, we call that function ourselves.
416331ca
XL
512fn print_with_analysis(
513 tcx: TyCtxt<'_>,
532ac7d7 514 ppm: PpMode,
dc9dc135 515 ofile: Option<&Path>,
532ac7d7 516) -> Result<(), ErrorReported> {
a7813a04
XL
517 let mut out = Vec::new();
518
532ac7d7
XL
519 tcx.analysis(LOCAL_CRATE)?;
520
e74abb32 521 match ppm {
532ac7d7 522 PpmMir | PpmMirCFG => {
e74abb32 523 match ppm {
60c5eb7d
XL
524 PpmMir => write_mir_pretty(tcx, None, &mut out),
525 PpmMirCFG => write_mir_graphviz(tcx, None, &mut out),
e74abb32 526 _ => unreachable!(),
1a4d82fc
JJ
527 }
528 }
532ac7d7 529 _ => unreachable!(),
e74abb32 530 }.unwrap();
c34b1796 531
a7813a04 532 write_output(out, ofile);
532ac7d7
XL
533
534 Ok(())
1a4d82fc 535}