Skip to content

Commit 32e4371

Browse files
committed
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).
1 parent ddc8cc9 commit 32e4371

File tree

6 files changed

+116
-3
lines changed

6 files changed

+116
-3
lines changed

src/librustc/driver/pretty.rs

+50
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub enum PpSourceMode {
4242
PpmTyped,
4343
PpmIdentified,
4444
PpmExpandedIdentified,
45+
PpmExpandedHygiene,
4546
}
4647

4748
#[deriving(PartialEq, Show)]
@@ -59,6 +60,7 @@ pub fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option<UserIdentifie
5960
"expanded" => PpmSource(PpmExpanded),
6061
"typed" => PpmSource(PpmTyped),
6162
"expanded,identified" => PpmSource(PpmExpandedIdentified),
63+
"expanded,hygiene" => PpmSource(PpmExpandedHygiene),
6264
"identified" => PpmSource(PpmIdentified),
6365
"flowgraph" => PpmFlowGraph,
6466
_ => {
@@ -106,6 +108,10 @@ impl PpSourceMode {
106108
let annotation = IdentifiedAnnotation { sess: sess, ast_map: ast_map };
107109
f(&annotation, payload)
108110
}
111+
PpmExpandedHygiene => {
112+
let annotation = HygieneAnnotation { sess: sess, ast_map: ast_map };
113+
f(&annotation, payload)
114+
}
109115
PpmTyped => {
110116
let ast_map = ast_map.expect("--pretty=typed missing ast_map");
111117
let analysis = driver::phase_3_run_analysis_passes(sess, krate, ast_map, id);
@@ -191,6 +197,8 @@ impl pprust::PpAnn for IdentifiedAnnotation {
191197
s: &mut pprust::State,
192198
node: pprust::AnnNode) -> io::IoResult<()> {
193199
match node {
200+
pprust::NodeIdent(_) | pprust::NodeName(_) => Ok(()),
201+
194202
pprust::NodeItem(item) => {
195203
try!(pp::space(&mut s.s));
196204
s.synth_comment(item.id.to_string())
@@ -212,6 +220,46 @@ impl pprust::PpAnn for IdentifiedAnnotation {
212220
}
213221
}
214222

223+
struct HygieneAnnotation {
224+
sess: Session,
225+
ast_map: Option<ast_map::Map>,
226+
}
227+
228+
impl PrinterSupport for HygieneAnnotation {
229+
fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
230+
}
231+
232+
impl SessionCarrier for HygieneAnnotation {
233+
fn sess<'a>(&'a self) -> &'a Session { &self.sess }
234+
}
235+
236+
impl AstMapCarrier for HygieneAnnotation {
237+
fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
238+
self.ast_map.as_ref()
239+
}
240+
}
241+
242+
impl pprust::PpAnn for HygieneAnnotation {
243+
fn post(&self,
244+
s: &mut pprust::State,
245+
node: pprust::AnnNode) -> io::IoResult<()> {
246+
match node {
247+
pprust::NodeIdent(&ast::Ident { name: ast::Name(nm), ctxt }) => {
248+
try!(pp::space(&mut s.s));
249+
// FIXME #16420: this doesn't display the connections
250+
// between syntax contexts
251+
s.synth_comment(format!("{}#{}", nm, ctxt))
252+
}
253+
pprust::NodeName(&ast::Name(nm)) => {
254+
try!(pp::space(&mut s.s));
255+
s.synth_comment(nm.to_string())
256+
}
257+
_ => Ok(())
258+
}
259+
}
260+
}
261+
262+
215263
struct TypedAnnotation {
216264
analysis: CrateAnalysis,
217265
}
@@ -364,6 +412,7 @@ fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {
364412

365413
PpmSource(PpmExpanded) |
366414
PpmSource(PpmExpandedIdentified) |
415+
PpmSource(PpmExpandedHygiene) |
367416
PpmSource(PpmTyped) |
368417
PpmFlowGraph => true
369418
}
@@ -376,6 +425,7 @@ fn needs_expansion(ppm: &PpMode) -> bool {
376425

377426
PpmSource(PpmExpanded) |
378427
PpmSource(PpmExpandedIdentified) |
428+
PpmSource(PpmExpandedHygiene) |
379429
PpmSource(PpmTyped) |
380430
PpmFlowGraph => true
381431
}

src/librustc/middle/dataflow.rs

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ impl<'a, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, O> {
111111
ps: &mut pprust::State,
112112
node: pprust::AnnNode) -> io::IoResult<()> {
113113
let id = match node {
114+
pprust::NodeIdent(_) | pprust::NodeName(_) => 0,
114115
pprust::NodeExpr(expr) => expr.id,
115116
pprust::NodeBlock(blk) => blk.id,
116117
pprust::NodeItem(_) => 0,

src/libsyntax/print/pprust.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ use std::io;
3333
use std::mem;
3434

3535
pub enum AnnNode<'a> {
36+
NodeIdent(&'a ast::Ident),
37+
NodeName(&'a ast::Name),
3638
NodeBlock(&'a ast::Block),
3739
NodeItem(&'a ast::Item),
3840
NodeExpr(&'a ast::Expr),
@@ -1725,14 +1727,16 @@ impl<'a> State<'a> {
17251727
pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> {
17261728
if self.encode_idents_with_hygiene {
17271729
let encoded = ident.encode_with_hygiene();
1728-
word(&mut self.s, encoded.as_slice())
1730+
try!(word(&mut self.s, encoded.as_slice()))
17291731
} else {
1730-
word(&mut self.s, token::get_ident(ident).get())
1732+
try!(word(&mut self.s, token::get_ident(ident).get()))
17311733
}
1734+
self.ann.post(self, NodeIdent(&ident))
17321735
}
17331736

17341737
pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> {
1735-
word(&mut self.s, token::get_name(name).get())
1738+
try!(word(&mut self.s, token::get_name(name).get()));
1739+
self.ann.post(self, NodeName(&name))
17361740
}
17371741

17381742
pub fn print_for_decl(&mut self, loc: &ast::Local,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-include ../tools.mk
2+
3+
REPLACEMENT := s/[0-9][0-9]*\#[0-9][0-9]*/$(shell date)/g
4+
5+
all:
6+
$(RUSTC) -o $(TMPDIR)/input.out --pretty expanded,hygiene input.rs
7+
8+
# the name/ctxt numbers are very internals-dependent and thus
9+
# change relatively frequently, and testing for their exact values
10+
# them will fail annoyingly, so we just check their positions
11+
# (using a non-constant replacement like this will make it less
12+
# likely the compiler matches whatever other dummy value we
13+
# choose).
14+
#
15+
# (These need to be out-of-place because OSX/BSD & GNU sed
16+
# differ.)
17+
sed "$(REPLACEMENT)" input.pp.rs > $(TMPDIR)/input.pp.rs
18+
sed "$(REPLACEMENT)" $(TMPDIR)/input.out > $(TMPDIR)/input.out.replaced
19+
20+
diff -u $(TMPDIR)/input.out.replaced $(TMPDIR)/input.pp.rs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
11+
#![feature(macro_rules)]
12+
// minimal junk
13+
#![no_std]
14+
15+
16+
fn bar /* 62#0 */() { let x /* 59#2 */ = 1; y /* 61#4 */ + x /* 59#5 */ }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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+
11+
#![feature(macro_rules)]
12+
// minimal junk
13+
#![no_std]
14+
15+
macro_rules! foo {
16+
($x: ident) => { y + $x }
17+
}
18+
19+
fn bar() {
20+
let x = 1;
21+
foo!(x)
22+
}

0 commit comments

Comments
 (0)