Skip to content

Commit

Permalink
rustc: implement a pretty mode to print ident/name's ctxt & gensyms.
Browse files Browse the repository at this point in the history
`--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).
  • Loading branch information
huonw committed Aug 29, 2014
1 parent ddc8cc9 commit d79047e
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 3 deletions.
50 changes: 50 additions & 0 deletions src/librustc/driver/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub enum PpSourceMode {
PpmTyped,
PpmIdentified,
PpmExpandedIdentified,
PpmExpandedHygiene,
}

#[deriving(PartialEq, Show)]
Expand All @@ -59,6 +60,7 @@ pub fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option<UserIdentifie
"expanded" => PpmSource(PpmExpanded),
"typed" => PpmSource(PpmTyped),
"expanded,identified" => PpmSource(PpmExpandedIdentified),
"expanded,hygiene" => PpmSource(PpmExpandedHygiene),
"identified" => PpmSource(PpmIdentified),
"flowgraph" => PpmFlowGraph,
_ => {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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())
Expand All @@ -212,6 +220,46 @@ impl pprust::PpAnn for IdentifiedAnnotation {
}
}

struct HygieneAnnotation {
sess: Session,
ast_map: Option<ast_map::Map>,
}

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,
}
Expand Down Expand Up @@ -364,6 +412,7 @@ fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {

PpmSource(PpmExpanded) |
PpmSource(PpmExpandedIdentified) |
PpmSource(PpmExpandedHygiene) |
PpmSource(PpmTyped) |
PpmFlowGraph => true
}
Expand All @@ -376,6 +425,7 @@ fn needs_expansion(ppm: &PpMode) -> bool {

PpmSource(PpmExpanded) |
PpmSource(PpmExpandedIdentified) |
PpmSource(PpmExpandedHygiene) |
PpmSource(PpmTyped) |
PpmFlowGraph => true
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 7 additions & 3 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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,
Expand Down
15 changes: 15 additions & 0 deletions src/test/run-make/pretty-expanded-hygiene/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-include ../tools.mk

all:
$(RUSTC) -o $(TMPDIR)/input.out --pretty expanded,hygiene input.rs
cp input.pp.rs $(TMPDIR)/input.pp.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).
sed -i "s/[0-9]*#[0-9]*/$(shell date)/g" $(TMPDIR)/input.out $(TMPDIR)/input.pp.rs

diff -u $(TMPDIR)/input.out $(TMPDIR)/input.pp.rs
16 changes: 16 additions & 0 deletions src/test/run-make/pretty-expanded-hygiene/input.pp.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 */ }
22 changes: 22 additions & 0 deletions src/test/run-make/pretty-expanded-hygiene/input.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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)
}

4 comments on commit d79047e

@bors
Copy link
Contributor

@bors bors commented on d79047e Aug 30, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from pnkfelix
at huonw@d79047e

@bors
Copy link
Contributor

@bors bors commented on d79047e Aug 30, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging huonw/rust/pretty-expanded-hygiene = d79047e into auto

@bors
Copy link
Contributor

@bors bors commented on d79047e Aug 30, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huonw/rust/pretty-expanded-hygiene = d79047e merged ok, testing candidate = 80f0ed04

Please sign in to comment.