mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
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).
This commit is contained in:
parent
ddc8cc92c9
commit
32e437161d
@ -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<UserIdentifie
|
||||
"expanded" => 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<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,
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -376,6 +425,7 @@ fn needs_expansion(ppm: &PpMode) -> bool {
|
||||
|
||||
PpmSource(PpmExpanded) |
|
||||
PpmSource(PpmExpandedIdentified) |
|
||||
PpmSource(PpmExpandedHygiene) |
|
||||
PpmSource(PpmTyped) |
|
||||
PpmFlowGraph => true
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
20
src/test/run-make/pretty-expanded-hygiene/Makefile
Normal file
20
src/test/run-make/pretty-expanded-hygiene/Makefile
Normal file
@ -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
|
16
src/test/run-make/pretty-expanded-hygiene/input.pp.rs
Executable file
16
src/test/run-make/pretty-expanded-hygiene/input.pp.rs
Executable file
@ -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
src/test/run-make/pretty-expanded-hygiene/input.rs
Executable file
22
src/test/run-make/pretty-expanded-hygiene/input.rs
Executable file
@ -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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user