From 32e437161da5e60c660b86da9003b7f73ebb5676 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Mon, 11 Aug 2014 22:01:37 +1000 Subject: [PATCH] rustc: implement a pretty mode to print ident/name's ctxt & gensyms. `--pretty expanded,hygiene` is helpful with debugging macro issues, since two identifiers/names can be textually the same, but different internally (resulting in weird "undefined variable" errors). --- src/librustc/driver/pretty.rs | 50 +++++++++++++++++++ src/librustc/middle/dataflow.rs | 1 + src/libsyntax/print/pprust.rs | 10 ++-- .../run-make/pretty-expanded-hygiene/Makefile | 20 ++++++++ .../pretty-expanded-hygiene/input.pp.rs | 16 ++++++ .../run-make/pretty-expanded-hygiene/input.rs | 22 ++++++++ 6 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 src/test/run-make/pretty-expanded-hygiene/Makefile create mode 100755 src/test/run-make/pretty-expanded-hygiene/input.pp.rs create mode 100755 src/test/run-make/pretty-expanded-hygiene/input.rs diff --git a/src/librustc/driver/pretty.rs b/src/librustc/driver/pretty.rs index d7118c7e54c..67dbc6f6a30 100644 --- a/src/librustc/driver/pretty.rs +++ b/src/librustc/driver/pretty.rs @@ -42,6 +42,7 @@ pub enum PpSourceMode { PpmTyped, PpmIdentified, PpmExpandedIdentified, + PpmExpandedHygiene, } #[deriving(PartialEq, Show)] @@ -59,6 +60,7 @@ pub fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option PpmSource(PpmExpanded), "typed" => PpmSource(PpmTyped), "expanded,identified" => PpmSource(PpmExpandedIdentified), + "expanded,hygiene" => PpmSource(PpmExpandedHygiene), "identified" => PpmSource(PpmIdentified), "flowgraph" => PpmFlowGraph, _ => { @@ -106,6 +108,10 @@ impl PpSourceMode { let annotation = IdentifiedAnnotation { sess: sess, ast_map: ast_map }; f(&annotation, payload) } + PpmExpandedHygiene => { + let annotation = HygieneAnnotation { sess: sess, ast_map: ast_map }; + f(&annotation, payload) + } PpmTyped => { let ast_map = ast_map.expect("--pretty=typed missing ast_map"); let analysis = driver::phase_3_run_analysis_passes(sess, krate, ast_map, id); @@ -191,6 +197,8 @@ impl pprust::PpAnn for IdentifiedAnnotation { s: &mut pprust::State, node: pprust::AnnNode) -> io::IoResult<()> { match node { + pprust::NodeIdent(_) | pprust::NodeName(_) => Ok(()), + pprust::NodeItem(item) => { try!(pp::space(&mut s.s)); s.synth_comment(item.id.to_string()) @@ -212,6 +220,46 @@ impl pprust::PpAnn for IdentifiedAnnotation { } } +struct HygieneAnnotation { + sess: Session, + ast_map: Option, +} + +impl PrinterSupport for HygieneAnnotation { + fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn } +} + +impl SessionCarrier for HygieneAnnotation { + fn sess<'a>(&'a self) -> &'a Session { &self.sess } +} + +impl AstMapCarrier for HygieneAnnotation { + fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> { + self.ast_map.as_ref() + } +} + +impl pprust::PpAnn for HygieneAnnotation { + fn post(&self, + s: &mut pprust::State, + node: pprust::AnnNode) -> io::IoResult<()> { + match node { + pprust::NodeIdent(&ast::Ident { name: ast::Name(nm), ctxt }) => { + try!(pp::space(&mut s.s)); + // FIXME #16420: this doesn't display the connections + // between syntax contexts + s.synth_comment(format!("{}#{}", nm, ctxt)) + } + pprust::NodeName(&ast::Name(nm)) => { + try!(pp::space(&mut s.s)); + s.synth_comment(nm.to_string()) + } + _ => Ok(()) + } + } +} + + struct TypedAnnotation { analysis: CrateAnalysis, } @@ -364,6 +412,7 @@ fn needs_ast_map(ppm: &PpMode, opt_uii: &Option) -> bool { PpmSource(PpmExpanded) | PpmSource(PpmExpandedIdentified) | + PpmSource(PpmExpandedHygiene) | PpmSource(PpmTyped) | PpmFlowGraph => true } @@ -376,6 +425,7 @@ fn needs_expansion(ppm: &PpMode) -> bool { PpmSource(PpmExpanded) | PpmSource(PpmExpandedIdentified) | + PpmSource(PpmExpandedHygiene) | PpmSource(PpmTyped) | PpmFlowGraph => true } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 91c227cd5bc..876789f99bc 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -111,6 +111,7 @@ impl<'a, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, O> { ps: &mut pprust::State, node: pprust::AnnNode) -> io::IoResult<()> { let id = match node { + pprust::NodeIdent(_) | pprust::NodeName(_) => 0, pprust::NodeExpr(expr) => expr.id, pprust::NodeBlock(blk) => blk.id, pprust::NodeItem(_) => 0, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index da265d81250..14ba4d73a4e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -33,6 +33,8 @@ use std::io; use std::mem; pub enum AnnNode<'a> { + NodeIdent(&'a ast::Ident), + NodeName(&'a ast::Name), NodeBlock(&'a ast::Block), NodeItem(&'a ast::Item), NodeExpr(&'a ast::Expr), @@ -1725,14 +1727,16 @@ impl<'a> State<'a> { pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> { if self.encode_idents_with_hygiene { let encoded = ident.encode_with_hygiene(); - word(&mut self.s, encoded.as_slice()) + try!(word(&mut self.s, encoded.as_slice())) } else { - word(&mut self.s, token::get_ident(ident).get()) + try!(word(&mut self.s, token::get_ident(ident).get())) } + self.ann.post(self, NodeIdent(&ident)) } pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> { - word(&mut self.s, token::get_name(name).get()) + try!(word(&mut self.s, token::get_name(name).get())); + self.ann.post(self, NodeName(&name)) } pub fn print_for_decl(&mut self, loc: &ast::Local, diff --git a/src/test/run-make/pretty-expanded-hygiene/Makefile b/src/test/run-make/pretty-expanded-hygiene/Makefile new file mode 100644 index 00000000000..11763446437 --- /dev/null +++ b/src/test/run-make/pretty-expanded-hygiene/Makefile @@ -0,0 +1,20 @@ +-include ../tools.mk + +REPLACEMENT := s/[0-9][0-9]*\#[0-9][0-9]*/$(shell date)/g + +all: + $(RUSTC) -o $(TMPDIR)/input.out --pretty expanded,hygiene input.rs + + # the name/ctxt numbers are very internals-dependent and thus + # change relatively frequently, and testing for their exact values + # them will fail annoyingly, so we just check their positions + # (using a non-constant replacement like this will make it less + # likely the compiler matches whatever other dummy value we + # choose). + # + # (These need to be out-of-place because OSX/BSD & GNU sed + # differ.) + sed "$(REPLACEMENT)" input.pp.rs > $(TMPDIR)/input.pp.rs + sed "$(REPLACEMENT)" $(TMPDIR)/input.out > $(TMPDIR)/input.out.replaced + + diff -u $(TMPDIR)/input.out.replaced $(TMPDIR)/input.pp.rs diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs new file mode 100755 index 00000000000..bf60784ab58 --- /dev/null +++ b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs @@ -0,0 +1,16 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(macro_rules)] +// minimal junk +#![no_std] + + +fn bar /* 62#0 */() { let x /* 59#2 */ = 1; y /* 61#4 */ + x /* 59#5 */ } diff --git a/src/test/run-make/pretty-expanded-hygiene/input.rs b/src/test/run-make/pretty-expanded-hygiene/input.rs new file mode 100755 index 00000000000..c9d603c2e1c --- /dev/null +++ b/src/test/run-make/pretty-expanded-hygiene/input.rs @@ -0,0 +1,22 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(macro_rules)] +// minimal junk +#![no_std] + +macro_rules! foo { + ($x: ident) => { y + $x } +} + +fn bar() { + let x = 1; + foo!(x) +}