auto merge of #9088 : nikomatsakis/rust/issue-6304-AST-tree-not-DAG, r=catamorphism

Ensures that each AST node has a unique id. Fixes numerous bugs in macro expansion and deriving. Add two
representative tests.

Fixes #7971
Fixes #6304
Fixes #8367
Fixes #8754
Fixes #8852
Fixes #2543
Fixes #7654
This commit is contained in:
bors 2013-09-10 03:10:59 -07:00
commit 753d8c226c
28 changed files with 532 additions and 384 deletions

View File

@ -190,6 +190,9 @@ pub fn phase_2_configure_and_expand(sess: Session,
crate = time(time_passes, ~"std injection", ||
front::std_inject::maybe_inject_libstd_ref(sess, crate));
crate = time(time_passes, ~"assigning node ids", ||
front::assign_node_ids::assign_node_ids(sess, crate));
return crate;
}
@ -207,6 +210,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
crate: @ast::Crate) -> CrateAnalysis {
let time_passes = sess.time_passes();
let ast_map = time(time_passes, ~"ast indexing", ||
syntax::ast_map::map_crate(sess.diagnostic(), crate));
@ -812,6 +816,7 @@ pub fn build_session_(sopts: @session::options,
building_library: @mut false,
working_dir: os::getcwd(),
lints: @mut HashMap::new(),
node_id: @mut 1
}
}

View File

@ -28,6 +28,7 @@ use syntax::abi;
use syntax::parse::token;
use syntax;
use std::int;
use std::hashmap::HashMap;
#[deriving(Eq)]
@ -216,57 +217,58 @@ pub struct Session_ {
building_library: @mut bool,
working_dir: Path,
lints: @mut HashMap<ast::NodeId, ~[(lint::lint, codemap::Span, ~str)]>,
node_id: @mut uint,
}
pub type Session = @Session_;
impl Session_ {
pub fn span_fatal(@self, sp: Span, msg: &str) -> ! {
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
self.span_diagnostic.span_fatal(sp, msg)
}
pub fn fatal(@self, msg: &str) -> ! {
pub fn fatal(&self, msg: &str) -> ! {
self.span_diagnostic.handler().fatal(msg)
}
pub fn span_err(@self, sp: Span, msg: &str) {
pub fn span_err(&self, sp: Span, msg: &str) {
self.span_diagnostic.span_err(sp, msg)
}
pub fn err(@self, msg: &str) {
pub fn err(&self, msg: &str) {
self.span_diagnostic.handler().err(msg)
}
pub fn err_count(@self) -> uint {
pub fn err_count(&self) -> uint {
self.span_diagnostic.handler().err_count()
}
pub fn has_errors(@self) -> bool {
pub fn has_errors(&self) -> bool {
self.span_diagnostic.handler().has_errors()
}
pub fn abort_if_errors(@self) {
pub fn abort_if_errors(&self) {
self.span_diagnostic.handler().abort_if_errors()
}
pub fn span_warn(@self, sp: Span, msg: &str) {
pub fn span_warn(&self, sp: Span, msg: &str) {
self.span_diagnostic.span_warn(sp, msg)
}
pub fn warn(@self, msg: &str) {
pub fn warn(&self, msg: &str) {
self.span_diagnostic.handler().warn(msg)
}
pub fn span_note(@self, sp: Span, msg: &str) {
pub fn span_note(&self, sp: Span, msg: &str) {
self.span_diagnostic.span_note(sp, msg)
}
pub fn note(@self, msg: &str) {
pub fn note(&self, msg: &str) {
self.span_diagnostic.handler().note(msg)
}
pub fn span_bug(@self, sp: Span, msg: &str) -> ! {
pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
self.span_diagnostic.span_bug(sp, msg)
}
pub fn bug(@self, msg: &str) -> ! {
pub fn bug(&self, msg: &str) -> ! {
self.span_diagnostic.handler().bug(msg)
}
pub fn span_unimpl(@self, sp: Span, msg: &str) -> ! {
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
self.span_diagnostic.span_unimpl(sp, msg)
}
pub fn unimpl(@self, msg: &str) -> ! {
pub fn unimpl(&self, msg: &str) -> ! {
self.span_diagnostic.handler().unimpl(msg)
}
pub fn add_lint(@self,
pub fn add_lint(&self,
lint: lint::lint,
id: ast::NodeId,
sp: Span,
@ -277,77 +279,85 @@ impl Session_ {
}
self.lints.insert(id, ~[(lint, sp, msg)]);
}
pub fn next_node_id(@self) -> ast::NodeId {
return syntax::parse::next_node_id(self.parse_sess);
pub fn next_node_id(&self) -> ast::NodeId {
self.reserve_node_ids(1)
}
pub fn diagnostic(@self) -> @mut diagnostic::span_handler {
pub fn reserve_node_ids(&self, count: uint) -> ast::NodeId {
let v = *self.node_id;
*self.node_id += count;
if v > (int::max_value as uint) {
self.bug("Input too large, ran out of node ids!");
}
v as int
}
pub fn diagnostic(&self) -> @mut diagnostic::span_handler {
self.span_diagnostic
}
pub fn debugging_opt(@self, opt: uint) -> bool {
pub fn debugging_opt(&self, opt: uint) -> bool {
(self.opts.debugging_opts & opt) != 0u
}
// This exists to help with refactoring to eliminate impossible
// cases later on
pub fn impossible_case(@self, sp: Span, msg: &str) -> ! {
pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
self.span_bug(sp, fmt!("Impossible case reached: %s", msg));
}
pub fn verbose(@self) -> bool { self.debugging_opt(verbose) }
pub fn time_passes(@self) -> bool { self.debugging_opt(time_passes) }
pub fn count_llvm_insns(@self) -> bool {
pub fn verbose(&self) -> bool { self.debugging_opt(verbose) }
pub fn time_passes(&self) -> bool { self.debugging_opt(time_passes) }
pub fn count_llvm_insns(&self) -> bool {
self.debugging_opt(count_llvm_insns)
}
pub fn count_type_sizes(@self) -> bool {
pub fn count_type_sizes(&self) -> bool {
self.debugging_opt(count_type_sizes)
}
pub fn time_llvm_passes(@self) -> bool {
pub fn time_llvm_passes(&self) -> bool {
self.debugging_opt(time_llvm_passes)
}
pub fn trans_stats(@self) -> bool { self.debugging_opt(trans_stats) }
pub fn meta_stats(@self) -> bool { self.debugging_opt(meta_stats) }
pub fn asm_comments(@self) -> bool { self.debugging_opt(asm_comments) }
pub fn no_verify(@self) -> bool { self.debugging_opt(no_verify) }
pub fn lint_llvm(@self) -> bool { self.debugging_opt(lint_llvm) }
pub fn trace(@self) -> bool { self.debugging_opt(trace) }
pub fn coherence(@self) -> bool { self.debugging_opt(coherence) }
pub fn borrowck_stats(@self) -> bool { self.debugging_opt(borrowck_stats) }
pub fn borrowck_note_pure(@self) -> bool {
pub fn trans_stats(&self) -> bool { self.debugging_opt(trans_stats) }
pub fn meta_stats(&self) -> bool { self.debugging_opt(meta_stats) }
pub fn asm_comments(&self) -> bool { self.debugging_opt(asm_comments) }
pub fn no_verify(&self) -> bool { self.debugging_opt(no_verify) }
pub fn lint_llvm(&self) -> bool { self.debugging_opt(lint_llvm) }
pub fn trace(&self) -> bool { self.debugging_opt(trace) }
pub fn coherence(&self) -> bool { self.debugging_opt(coherence) }
pub fn borrowck_stats(&self) -> bool { self.debugging_opt(borrowck_stats) }
pub fn borrowck_note_pure(&self) -> bool {
self.debugging_opt(borrowck_note_pure)
}
pub fn borrowck_note_loan(@self) -> bool {
pub fn borrowck_note_loan(&self) -> bool {
self.debugging_opt(borrowck_note_loan)
}
pub fn no_monomorphic_collapse(@self) -> bool {
pub fn no_monomorphic_collapse(&self) -> bool {
self.debugging_opt(no_monomorphic_collapse)
}
pub fn debug_borrows(@self) -> bool {
pub fn debug_borrows(&self) -> bool {
self.opts.optimize == No && !self.debugging_opt(no_debug_borrows)
}
pub fn once_fns(@self) -> bool { self.debugging_opt(once_fns) }
pub fn print_llvm_passes(@self) -> bool {
pub fn once_fns(&self) -> bool { self.debugging_opt(once_fns) }
pub fn print_llvm_passes(&self) -> bool {
self.debugging_opt(print_llvm_passes)
}
pub fn no_prepopulate_passes(@self) -> bool {
pub fn no_prepopulate_passes(&self) -> bool {
self.debugging_opt(no_prepopulate_passes)
}
pub fn no_vectorize_loops(@self) -> bool {
pub fn no_vectorize_loops(&self) -> bool {
self.debugging_opt(no_vectorize_loops)
}
pub fn no_vectorize_slp(@self) -> bool {
pub fn no_vectorize_slp(&self) -> bool {
self.debugging_opt(no_vectorize_slp)
}
// pointless function, now...
pub fn str_of(@self, id: ast::Ident) -> @str {
pub fn str_of(&self, id: ast::Ident) -> @str {
token::ident_to_str(&id)
}
// pointless function, now...
pub fn ident_of(@self, st: &str) -> ast::Ident {
pub fn ident_of(&self, st: &str) -> ast::Ident {
token::str_to_ident(st)
}
// pointless function, now...
pub fn intr(@self) -> @syntax::parse::token::ident_interner {
pub fn intr(&self) -> @syntax::parse::token::ident_interner {
token::get_ident_interner()
}
}

View File

@ -0,0 +1,19 @@
// Copyright 2012 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.
use driver::session::Session;
use syntax::ast;
use syntax::ast_util;
pub fn assign_node_ids(sess: Session, crate: @ast::Crate) -> @ast::Crate {
let fold = ast_util::node_id_assigner(|| sess.next_node_id());
@fold.fold_crate(crate)
}

View File

@ -45,7 +45,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
let precursor = @fold::AstFoldFns {
fold_crate: |crate, fld| {
let n1 = sess.next_node_id();
let n1 = ast::DUMMY_NODE_ID;
let vi1 = ast::view_item {
node: ast::view_item_extern_mod(
sess.ident_of("std"), None, ~[], n1),
@ -86,7 +86,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
}
},
fold_mod: |module, fld| {
let n2 = sess.next_node_id();
let n2 = ast::DUMMY_NODE_ID;
let prelude_path = ast::Path {
span: dummy_sp(),

View File

@ -280,10 +280,10 @@ fn mk_std(cx: &TestCtxt) -> ast::view_item {
ast::view_item_use(
~[@nospan(ast::view_path_simple(id_extra,
path_node(~[id_extra]),
cx.sess.next_node_id()))])
ast::DUMMY_NODE_ID))])
} else {
let mi = attr::mk_name_value_item_str(@"vers", @"0.8-pre");
ast::view_item_extern_mod(id_extra, None, ~[mi], cx.sess.next_node_id())
ast::view_item_extern_mod(id_extra, None, ~[mi], ast::DUMMY_NODE_ID)
};
ast::view_item {
node: vi,
@ -325,7 +325,7 @@ fn mk_test_module(cx: &TestCtxt) -> @ast::item {
let item = ast::item {
ident: cx.sess.ident_of("__test"),
attrs: ~[resolve_unexported_attr],
id: cx.sess.next_node_id(),
id: ast::DUMMY_NODE_ID,
node: item_,
vis: ast::public,
span: dummy_sp(),
@ -367,7 +367,7 @@ fn mk_test_module(cx: &TestCtxt) -> @ast::item {
let item = ast::item {
ident: cx.sess.ident_of("__test"),
attrs: ~[resolve_unexported_attr],
id: cx.sess.next_node_id(),
id: ast::DUMMY_NODE_ID,
node: item_,
vis: ast::public,
span: dummy_sp(),
@ -448,15 +448,14 @@ fn mk_test_descs(cx: &TestCtxt) -> @ast::Expr {
descs.push(mk_test_desc_and_fn_rec(cx, test));
}
let sess = cx.sess;
let inner_expr = @ast::Expr {
id: sess.next_node_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprVec(descs, ast::MutImmutable),
span: dummy_sp(),
};
@ast::Expr {
id: sess.next_node_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprVstore(inner_expr, ast::ExprVstoreSlice),
span: dummy_sp(),
}
@ -475,7 +474,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::Expr {
nospan(ast::lit_str(ast_util::path_name_i(path).to_managed()));
let name_expr = @ast::Expr {
id: cx.sess.next_node_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprLit(@name_lit),
span: span
};
@ -483,7 +482,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::Expr {
let fn_path = path_node_global(path);
let fn_expr = @ast::Expr {
id: cx.sess.next_node_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(fn_path),
span: span,
};
@ -529,7 +528,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::Expr {
nospan(ast::lit_str(ast_util::path_name_i(path).to_managed()));
let name_expr = @ast::Expr {
id: cx.sess.next_node_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprLit(@name_lit),
span: span
};
@ -537,7 +536,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::Expr {
let fn_path = path_node_global(path);
let fn_expr = @ast::Expr {
id: cx.sess.next_node_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(fn_path),
span: span,
};

View File

@ -157,10 +157,10 @@ fn reserve_id_range(sess: Session,
// Handle the case of an empty range:
if from_id_range.empty() { return from_id_range; }
let cnt = from_id_range.max - from_id_range.min;
let to_id_min = sess.parse_sess.next_id;
let to_id_max = sess.parse_sess.next_id + cnt;
sess.parse_sess.next_id = to_id_max;
ast_util::id_range { min: to_id_min, max: to_id_min }
assert!(cnt >= 0);
let to_id_min = sess.reserve_node_ids(cnt as uint);
let to_id_max = to_id_min + cnt;
ast_util::id_range { min: to_id_min, max: to_id_max }
}
impl ExtendedDecodeContext {

View File

@ -5403,7 +5403,15 @@ impl Resolver {
pub fn record_def(@mut self, node_id: NodeId, def: Def) {
debug!("(recording def) recording %? for %?", def, node_id);
self.def_map.insert(node_id, def);
do self.def_map.insert_or_update_with(node_id, def) |_, old_value| {
// Resolve appears to "resolve" the same ID multiple
// times, so here is a sanity check it at least comes to
// the same conclusion! - nmatsakis
if def != *old_value {
self.session.bug(fmt!("node_id %? resolved first to %? \
and then %?", node_id, *old_value, def));
}
};
}
pub fn enforce_default_binding_mode(@mut self,

View File

@ -45,7 +45,6 @@ use syntax::ast_util::{def_id_of_def, local_def};
use syntax::codemap::Span;
use syntax::opt_vec;
use syntax::visit;
use syntax::parse;
use std::hashmap::HashSet;
use std::result::Ok;
@ -334,7 +333,7 @@ impl CoherenceChecker {
let provided = ty::provided_trait_methods(tcx, trait_ref.def_id);
for trait_method in provided.iter() {
// Synthesize an ID.
let new_id = parse::next_node_id(tcx.sess.parse_sess);
let new_id = tcx.sess.next_node_id();
let new_did = local_def(new_id);
debug!("new_did=%? trait_method=%s", new_did, trait_method.repr(tcx));

View File

@ -80,6 +80,7 @@ pub mod front {
pub mod config;
pub mod test;
pub mod std_inject;
pub mod assign_node_ids;
}
pub mod back {

View File

@ -29,6 +29,7 @@ use rustc::driver::session::{basic_options, options};
use rustc::front;
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util;
use syntax;
pub struct Ctxt {
@ -108,6 +109,16 @@ pub fn exec<T:Send>(
po.recv()
}
fn assign_node_ids(crate: @ast::Crate) -> @ast::Crate {
let next_id = @mut 0;
let fold = ast_util::node_id_assigner(|| {
let i = *next_id;
*next_id += 1;
i
});
@fold.fold_crate(crate)
}
fn build_ctxt(sess: Session,
ast: @ast::Crate) -> Ctxt {
@ -121,6 +132,7 @@ fn build_ctxt(sess: Session,
sess.opts.cfg.clone(),
ast);
let ast = front::test::modify_for_testing(sess, ast);
let ast = assign_node_ids(ast);
let ast_map = ast_map::map_crate(sess.diagnostic(), ast);
Ctxt {

View File

@ -281,6 +281,7 @@ mod test {
fn should_extract_enum_docs() {
let doc = mk_doc(~"#[doc = \"b\"]\
enum a { v }");
debug!("%?", doc);
assert!(doc.cratemod().enums()[0].desc() == Some(~"b"));
}

View File

@ -285,6 +285,7 @@ mod test {
fn mk_doc(source: @str) -> doc::Doc {
let ast = parse::from_str(source);
debug!("ast=%?", ast);
extract(ast, ~"")
}

View File

@ -176,6 +176,11 @@ pub struct DefId {
pub static LOCAL_CRATE: CrateNum = 0;
pub static CRATE_NODE_ID: NodeId = 0;
// When parsing and doing expansions, we initially give all AST nodes this AST
// node value. Then later, in the renumber pass, we renumber them to have
// small, positive ids.
pub static DUMMY_NODE_ID: NodeId = -1;
// The AST represents all type param bounds as types.
// typeck::collect::compute_bounds matches these against
// the "special" built-in traits (see middle::lang_items) and

View File

@ -12,6 +12,7 @@ use ast::*;
use ast;
use ast_util;
use codemap::{Span, dummy_sp};
use fold;
use opt_vec;
use parse::token;
use visit::{SimpleVisitor, Visitor};
@ -370,6 +371,21 @@ pub fn empty_generics() -> Generics {
ty_params: opt_vec::Empty}
}
///////////////////////////////////////////////////////////////////////////
// Assigning node ids
fn node_id_assigner(next_id: @fn() -> ast::NodeId) -> @fold::ast_fold {
let precursor = @fold::AstFoldFns {
new_id: |old_id| {
assert_eq!(old_id, ast::DUMMY_NODE_ID);
next_id()
},
..*fold::default_ast_fold()
};
fold::make_fold(precursor)
}
// ______________________________________________________________________
// Enumerating the IDs which appear in an AST

View File

@ -76,7 +76,7 @@ pub fn expand_asm(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
p.expect(&token::RPAREN);
let out = @ast::Expr {
id: cx.next_id(),
id: ast::DUMMY_NODE_ID,
span: out.span,
node: ast::ExprAddrOf(ast::MutMutable, out)
};
@ -172,7 +172,7 @@ pub fn expand_asm(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
}
MRExpr(@ast::Expr {
id: cx.next_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprInlineAsm(ast::inline_asm {
asm: asm,
clobbers: cons.to_managed(),

View File

@ -319,9 +319,6 @@ impl ExtCtxt {
self.print_backtrace();
self.parse_sess.span_diagnostic.handler().bug(msg);
}
pub fn next_id(&self) -> ast::NodeId {
parse::next_node_id(self.parse_sess)
}
pub fn trace_macros(&self) -> bool {
*self.trace_mac
}

View File

@ -13,7 +13,6 @@ use ast::Ident;
use ast;
use ast_util;
use codemap::{Span, respan, dummy_sp};
use fold;
use ext::base::ExtCtxt;
use ext::quote::rt::*;
use opt_vec;
@ -277,7 +276,7 @@ impl AstBuilder for @ExtCtxt {
fn ty(&self, span: Span, ty: ast::ty_) -> ast::Ty {
ast::Ty {
id: self.next_id(),
id: ast::DUMMY_NODE_ID,
span: span,
node: ty
}
@ -286,7 +285,7 @@ impl AstBuilder for @ExtCtxt {
fn ty_path(&self, path: ast::Path, bounds: Option<OptVec<ast::TyParamBound>>)
-> ast::Ty {
self.ty(path.span,
ast::ty_path(path, bounds, self.next_id()))
ast::ty_path(path, bounds, ast::DUMMY_NODE_ID))
}
// Might need to take bounds as an argument in the future, if you ever want
@ -340,14 +339,14 @@ impl AstBuilder for @ExtCtxt {
fn ty_nil(&self) -> ast::Ty {
ast::Ty {
id: self.next_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ty_nil,
span: dummy_sp(),
}
}
fn typaram(&self, id: ast::Ident, bounds: OptVec<ast::TyParamBound>) -> ast::TyParam {
ast::TyParam { ident: id, id: self.next_id(), bounds: bounds }
ast::TyParam { ident: id, id: ast::DUMMY_NODE_ID, bounds: bounds }
}
// these are strange, and probably shouldn't be used outside of
@ -377,7 +376,7 @@ impl AstBuilder for @ExtCtxt {
fn trait_ref(&self, path: ast::Path) -> ast::trait_ref {
ast::trait_ref {
path: path,
ref_id: self.next_id()
ref_id: ast::DUMMY_NODE_ID
}
}
@ -386,11 +385,11 @@ impl AstBuilder for @ExtCtxt {
}
fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime {
ast::Lifetime { id: self.next_id(), span: span, ident: ident }
ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, ident: ident }
}
fn stmt_expr(&self, expr: @ast::Expr) -> @ast::Stmt {
@respan(expr.span, ast::StmtSemi(expr, self.next_id()))
@respan(expr.span, ast::StmtSemi(expr, ast::DUMMY_NODE_ID))
}
fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: @ast::Expr) -> @ast::Stmt {
@ -400,11 +399,11 @@ impl AstBuilder for @ExtCtxt {
ty: self.ty_infer(sp),
pat: pat,
init: Some(ex),
id: self.next_id(),
id: ast::DUMMY_NODE_ID,
span: sp,
};
let decl = respan(sp, ast::DeclLocal(local));
@respan(sp, ast::StmtDecl(@decl, self.next_id()))
@respan(sp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID))
}
fn stmt_let_typed(&self,
@ -420,11 +419,11 @@ impl AstBuilder for @ExtCtxt {
ty: typ,
pat: pat,
init: Some(ex),
id: self.next_id(),
id: ast::DUMMY_NODE_ID,
span: sp,
};
let decl = respan(sp, ast::DeclLocal(local));
@respan(sp, ast::StmtDecl(@decl, self.next_id()))
@respan(sp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID))
}
fn block(&self, span: Span, stmts: ~[@ast::Stmt], expr: Option<@Expr>) -> ast::Block {
@ -443,7 +442,7 @@ impl AstBuilder for @ExtCtxt {
view_items: view_items,
stmts: stmts,
expr: expr,
id: self.next_id(),
id: ast::DUMMY_NODE_ID,
rules: ast::DefaultBlock,
span: span,
}
@ -451,7 +450,7 @@ impl AstBuilder for @ExtCtxt {
fn expr(&self, span: Span, node: ast::Expr_) -> @ast::Expr {
@ast::Expr {
id: self.next_id(),
id: ast::DUMMY_NODE_ID,
node: node,
span: span,
}
@ -470,7 +469,7 @@ impl AstBuilder for @ExtCtxt {
fn expr_binary(&self, sp: Span, op: ast::BinOp,
lhs: @ast::Expr, rhs: @ast::Expr) -> @ast::Expr {
self.expr(sp, ast::ExprBinary(self.next_id(), op, lhs, rhs))
self.expr(sp, ast::ExprBinary(ast::DUMMY_NODE_ID, op, lhs, rhs))
}
fn expr_deref(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
@ -478,7 +477,7 @@ impl AstBuilder for @ExtCtxt {
}
fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr)
-> @ast::Expr {
self.expr(sp, ast::ExprUnary(self.next_id(), op, e))
self.expr(sp, ast::ExprUnary(ast::DUMMY_NODE_ID, op, e))
}
fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
@ -512,7 +511,7 @@ impl AstBuilder for @ExtCtxt {
ident: ast::Ident,
args: ~[@ast::Expr]) -> @ast::Expr {
self.expr(span,
ast::ExprMethodCall(self.next_id(), expr, ident, ~[], args, ast::NoSugar))
ast::ExprMethodCall(ast::DUMMY_NODE_ID, expr, ident, ~[], args, ast::NoSugar))
}
fn expr_block(&self, b: ast::Block) -> @ast::Expr {
self.expr(b.span, ast::ExprBlock(b))
@ -583,7 +582,7 @@ impl AstBuilder for @ExtCtxt {
fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat {
@ast::Pat { id: self.next_id(), node: pat, span: span }
@ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }
}
fn pat_wild(&self, span: Span) -> @ast::Pat {
self.pat(span, ast::PatWild)
@ -695,7 +694,7 @@ impl AstBuilder for @ExtCtxt {
is_mutbl: false,
ty: ty,
pat: arg_pat,
id: self.next_id()
id: ast::DUMMY_NODE_ID
}
}
@ -714,7 +713,7 @@ impl AstBuilder for @ExtCtxt {
// Rust coding conventions
@ast::item { ident: name,
attrs: attrs,
id: self.next_id(),
id: ast::DUMMY_NODE_ID,
node: node,
vis: ast::public,
span: span }
@ -755,7 +754,7 @@ impl AstBuilder for @ExtCtxt {
fn variant(&self, span: Span, name: Ident, tys: ~[ast::Ty]) -> ast::variant {
let args = tys.move_iter().map(|ty| {
ast::variant_arg { ty: ty, id: self.next_id() }
ast::variant_arg { ty: ty, id: ast::DUMMY_NODE_ID }
}).collect();
respan(span,
@ -763,7 +762,7 @@ impl AstBuilder for @ExtCtxt {
name: name,
attrs: ~[],
kind: ast::tuple_variant_kind(args),
id: self.next_id(),
id: ast::DUMMY_NODE_ID,
disr_expr: None,
vis: ast::public
})
@ -860,43 +859,20 @@ impl AstBuilder for @ExtCtxt {
fn view_use_list(&self, sp: Span, vis: ast::visibility,
path: ~[ast::Ident], imports: &[ast::Ident]) -> ast::view_item {
let imports = do imports.map |id| {
respan(sp, ast::path_list_ident_ { name: *id, id: self.next_id() })
respan(sp, ast::path_list_ident_ { name: *id, id: ast::DUMMY_NODE_ID })
};
self.view_use(sp, vis,
~[@respan(sp,
ast::view_path_list(self.path(sp, path),
imports,
self.next_id()))])
ast::DUMMY_NODE_ID))])
}
fn view_use_glob(&self, sp: Span,
vis: ast::visibility, path: ~[ast::Ident]) -> ast::view_item {
self.view_use(sp, vis,
~[@respan(sp,
ast::view_path_glob(self.path(sp, path), self.next_id()))])
}
}
pub trait Duplicate {
//
// Duplication functions
//
// These functions just duplicate AST nodes.
//
fn duplicate(&self, cx: @ExtCtxt) -> Self;
}
impl Duplicate for @ast::Expr {
fn duplicate(&self, cx: @ExtCtxt) -> @ast::Expr {
let folder = fold::default_ast_fold();
let folder = @fold::AstFoldFns {
new_id: |_| cx.next_id(),
..*folder
};
let folder = fold::make_fold(folder);
folder.fold_expr(*self)
ast::view_path_glob(self.path(sp, path), ast::DUMMY_NODE_ID))])
}
}

View File

@ -35,7 +35,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
let res = str_to_ident(res_str);
let e = @ast::Expr {
id: cx.next_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(
ast::Path {
span: sp,

View File

@ -539,9 +539,9 @@ impl<'self> MethodDef<'self> {
purity: ast::impure_fn,
decl: fn_decl,
body: body_block,
id: cx.next_id(),
id: ast::DUMMY_NODE_ID,
span: span,
self_id: cx.next_id(),
self_id: ast::DUMMY_NODE_ID,
vis: ast::inherited,
}
}

View File

@ -12,7 +12,7 @@ use ast;
use ast::{MetaItem, item, Expr, Ident};
use codemap::Span;
use ext::base::ExtCtxt;
use ext::build::{AstBuilder, Duplicate};
use ext::build::{AstBuilder};
use ext::deriving::generic::*;
use std::vec;
@ -62,7 +62,7 @@ fn rand_substructure(cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
let rand_call = || {
cx.expr_call_global(span,
rand_ident.clone(),
~[ rng[0].duplicate(cx) ])
~[ rng[0] ])
};
return match *substr.fields {
@ -86,7 +86,7 @@ fn rand_substructure(cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
// ::std::rand::Rand::rand(rng)
let rv_call = cx.expr_call(span,
rand_name,
~[ rng[0].duplicate(cx) ]);
~[ rng[0] ]);
// need to specify the uint-ness of the random number
let uint_ty = cx.ty_ident(span, cx.ident_of("uint"));

View File

@ -406,8 +406,8 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
let marked_ctxt = new_mark(fm,ctxt);
let expanded = match expandfun(cx, mac.span, marked_tts, marked_ctxt) {
MRExpr(e) =>
@codemap::Spanned { node: StmtExpr(e, cx.next_id()),
span: e.span},
@codemap::Spanned { node: StmtExpr(e, ast::DUMMY_NODE_ID),
span: e.span},
MRAny(_,_,stmt_mkr) => stmt_mkr(),
_ => cx.span_fatal(
pth.span,
@ -1365,8 +1365,8 @@ pub fn fun_to_ctxt_folder<T : 'static + CtxtFn>(cf: @T) -> @AstFoldFns {
match *m {
mac_invoc_tt(ref path, ref tts, ctxt) =>
(mac_invoc_tt(fld.fold_path(path),
fold_tts(*tts,fld),
cf.f(ctxt)),
fold_tts(*tts,fld),
cf.f(ctxt)),
sp)
}

View File

@ -550,7 +550,7 @@ impl Context {
for &method in self.method_statics.iter() {
let decl = respan(self.fmtsp, ast::DeclItem(method));
lets.push(@respan(self.fmtsp,
ast::StmtDecl(@decl, self.ecx.next_id())));
ast::StmtDecl(@decl, ast::DUMMY_NODE_ID)));
}
// Next, build up the static array which will become our precompiled
@ -581,7 +581,7 @@ impl Context {
let unnamed = self.ecx.attribute(self.fmtsp, unnamed);
let item = self.ecx.item(self.fmtsp, static_name, ~[unnamed], st);
let decl = respan(self.fmtsp, ast::DeclItem(item));
lets.push(@respan(self.fmtsp, ast::StmtDecl(@decl, self.ecx.next_id())));
lets.push(@respan(self.fmtsp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID)));
// Right now there is a bug such that for the expression:
// foo(bar(&1))
@ -631,7 +631,7 @@ impl Context {
view_items: ~[],
stmts: ~[],
expr: Some(result),
id: self.ecx.next_id(),
id: ast::DUMMY_NODE_ID,
rules: ast::UnsafeBlock,
span: self.fmtsp,
});

View File

@ -30,7 +30,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt,
//trivial expression
MRExpr(@ast::Expr {
id: cx.next_id(),
id: ast::DUMMY_NODE_ID,
node: ast::ExprLit(@codemap::Spanned {
node: ast::lit_nil,
span: sp

View File

@ -29,6 +29,7 @@ pub trait ast_fold {
fn fold_item(@self, @item) -> Option<@item>;
fn fold_struct_field(@self, @struct_field) -> @struct_field;
fn fold_item_underscore(@self, &item_) -> item_;
fn fold_type_method(@self, m: &TypeMethod) -> TypeMethod;
fn fold_method(@self, @method) -> @method;
fn fold_block(@self, &Block) -> Block;
fn fold_stmt(@self, &Stmt) -> Option<@Stmt>;
@ -47,6 +48,149 @@ pub trait ast_fold {
fn map_exprs(@self, @fn(@Expr) -> @Expr, &[@Expr]) -> ~[@Expr];
fn new_id(@self, NodeId) -> NodeId;
fn new_span(@self, Span) -> Span;
// New style, using default methods:
fn fold_variant_arg(@self, va: &variant_arg) -> variant_arg {
variant_arg {
ty: self.fold_ty(&va.ty),
id: self.new_id(va.id)
}
}
fn fold_spanned<T>(@self, s: &Spanned<T>, f: &fn(&T) -> T) -> Spanned<T> {
Spanned {
node: f(&s.node),
span: self.new_span(s.span)
}
}
fn fold_view_path(@self, vp: &view_path) -> view_path {
self.fold_spanned(vp, |v| self.fold_view_path_(v))
}
fn fold_view_paths(@self, vps: &[@view_path]) -> ~[@view_path] {
vps.map(|vp| @self.fold_view_path(*vp))
}
fn fold_view_path_(@self, vp: &view_path_) -> view_path_ {
match *vp {
view_path_simple(ident, ref path, node_id) => {
view_path_simple(self.fold_ident(ident),
self.fold_path(path),
self.new_id(node_id))
}
view_path_glob(ref path, node_id) => {
view_path_glob(self.fold_path(path),
self.new_id(node_id))
}
view_path_list(ref path, ref idents, node_id) => {
view_path_list(self.fold_path(path),
self.fold_path_list_idents(*idents),
self.new_id(node_id))
}
}
}
fn fold_path_list_idents(@self, idents: &[path_list_ident]) -> ~[path_list_ident] {
idents.map(|i| self.fold_path_list_ident(i))
}
fn fold_path_list_ident(@self, ident: &path_list_ident) -> path_list_ident {
self.fold_spanned(ident, |i| self.fold_path_list_ident_(i))
}
fn fold_path_list_ident_(@self, ident: &path_list_ident_) -> path_list_ident_ {
path_list_ident_ {
name: self.fold_ident(ident.name),
id: self.new_id(ident.id)
}
}
fn fold_arg(@self, a: &arg) -> arg {
arg {
is_mutbl: a.is_mutbl,
ty: self.fold_ty(&a.ty),
pat: self.fold_pat(a.pat),
id: self.new_id(a.id),
}
}
fn fold_trait_ref(@self, p: &trait_ref) -> trait_ref {
trait_ref {
path: self.fold_path(&p.path),
ref_id: self.new_id(p.ref_id),
}
}
fn fold_ty_param_bound(@self, tpb: &TyParamBound) -> TyParamBound {
match *tpb {
TraitTyParamBound(ref ty) => {
TraitTyParamBound(self.fold_trait_ref(ty))
}
RegionTyParamBound => {
RegionTyParamBound
}
}
}
fn fold_ty_param(@self, tp: &TyParam) -> TyParam {
TyParam {
ident: self.fold_ident(tp.ident),
id: self.new_id(tp.id),
bounds: tp.bounds.map(|x| self.fold_ty_param_bound(x))
}
}
fn fold_ty_params(@self, tps: &OptVec<TyParam>) -> OptVec<TyParam> {
tps.map(|tp| self.fold_ty_param(tp))
}
fn fold_lifetime(@self, l: &Lifetime) -> Lifetime {
Lifetime {
id: self.new_id(l.id),
span: self.new_span(l.span),
ident: l.ident, // Folding this ident causes hygiene errors - ndm
}
}
fn fold_lifetimes(@self, lts: &OptVec<Lifetime>) -> OptVec<Lifetime> {
lts.map(|l| self.fold_lifetime(l))
}
fn fold_meta_item(@self, mi: &MetaItem) -> @MetaItem {
@self.fold_spanned(mi, |n| match *n {
MetaWord(id) => {
MetaWord(id)
}
MetaList(id, ref mis) => {
MetaList(id, self.fold_meta_items(*mis))
}
MetaNameValue(id, s) => {
MetaNameValue(id, s)
}
})
}
fn fold_meta_items(@self, mis: &[@MetaItem]) -> ~[@MetaItem] {
mis.map(|&mi| self.fold_meta_item(mi))
}
fn fold_attribute(@self, at: &Attribute) -> Attribute {
Spanned {
span: self.new_span(at.span),
node: Attribute_ {
style: at.node.style,
value: self.fold_meta_item(at.node.value),
is_sugared_doc: at.node.is_sugared_doc
}
}
}
fn fold_attributes(@self, attrs: &[Attribute]) -> ~[Attribute] {
attrs.map(|x| self.fold_attribute(x))
}
}
// We may eventually want to be able to fold over type parameters, too
@ -59,6 +203,7 @@ pub struct AstFoldFns {
fold_item: @fn(@item, @ast_fold) -> Option<@item>,
fold_struct_field: @fn(@struct_field, @ast_fold) -> @struct_field,
fold_item_underscore: @fn(&item_, @ast_fold) -> item_,
fold_type_method: @fn(&TypeMethod, @ast_fold) -> TypeMethod,
fold_method: @fn(@method, @ast_fold) -> @method,
fold_block: @fn(&Block, @ast_fold) -> Block,
fold_stmt: @fn(&Stmt_, Span, @ast_fold) -> (Option<Stmt_>, Span),
@ -83,61 +228,20 @@ pub type ast_fold_fns = @AstFoldFns;
/* some little folds that probably aren't useful to have in ast_fold itself*/
//used in noop_fold_item and noop_fold_crate and noop_fold_crate_directive
fn fold_meta_item_(mi: @MetaItem, fld: @ast_fold) -> @MetaItem {
@Spanned {
node:
match mi.node {
MetaWord(id) => MetaWord(id),
MetaList(id, ref mis) => {
let fold_meta_item = |x| fold_meta_item_(x, fld);
MetaList(
id,
mis.map(|e| fold_meta_item(*e))
)
}
MetaNameValue(id, s) => MetaNameValue(id, s)
},
span: fld.new_span(mi.span) }
}
//used in noop_fold_item and noop_fold_crate
fn fold_attribute_(at: Attribute, fld: @ast_fold) -> Attribute {
Spanned {
span: fld.new_span(at.span),
node: ast::Attribute_ {
style: at.node.style,
value: fold_meta_item_(at.node.value, fld),
is_sugared_doc: at.node.is_sugared_doc
}
}
}
//used in noop_fold_foreign_item and noop_fold_fn_decl
fn fold_arg_(a: arg, fld: @ast_fold) -> arg {
ast::arg {
is_mutbl: a.is_mutbl,
ty: fld.fold_ty(&a.ty),
pat: fld.fold_pat(a.pat),
id: fld.new_id(a.id),
}
}
// build a new vector of tts by appling the ast_fold's fold_ident to
// all of the identifiers in the token trees.
pub fn fold_tts(tts : &[token_tree], f : @ast_fold) -> ~[token_tree] {
pub fn fold_tts(tts : &[token_tree], fld: @ast_fold) -> ~[token_tree] {
do tts.map |tt| {
match *tt {
tt_tok(span, ref tok) =>
tt_tok(span,maybe_fold_ident(tok,f)),
tt_tok(span,maybe_fold_ident(tok,fld)),
tt_delim(ref tts) =>
tt_delim(@mut fold_tts(**tts, f)),
tt_delim(@mut fold_tts(**tts, fld)),
tt_seq(span, ref pattern, ref sep, is_optional) =>
tt_seq(span,
@mut fold_tts(**pattern, f),
sep.map(|tok|maybe_fold_ident(tok,f)),
@mut fold_tts(**pattern, fld),
sep.map(|tok|maybe_fold_ident(tok,fld)),
is_optional),
tt_nonterminal(sp,ref ident) =>
tt_nonterminal(sp,f.fold_ident(*ident))
tt_nonterminal(sp,fld.fold_ident(*ident))
}
}
}
@ -153,82 +257,51 @@ fn maybe_fold_ident(t : &token::Token, f: @ast_fold) -> token::Token {
pub fn fold_fn_decl(decl: &ast::fn_decl, fld: @ast_fold) -> ast::fn_decl {
ast::fn_decl {
inputs: decl.inputs.map(|x| fold_arg_(/*bad*/ (*x).clone(), fld)),
inputs: decl.inputs.map(|x| fld.fold_arg(x)),
output: fld.fold_ty(&decl.output),
cf: decl.cf,
}
}
fn fold_ty_param_bound(tpb: &TyParamBound, fld: @ast_fold) -> TyParamBound {
match *tpb {
TraitTyParamBound(ref ty) => TraitTyParamBound(fold_trait_ref(ty, fld)),
RegionTyParamBound => RegionTyParamBound
}
}
pub fn fold_ty_param(tp: TyParam,
fld: @ast_fold) -> TyParam {
TyParam {ident: tp.ident,
id: fld.new_id(tp.id),
bounds: tp.bounds.map(|x| fold_ty_param_bound(x, fld))}
}
pub fn fold_ty_params(tps: &OptVec<TyParam>,
fld: @ast_fold) -> OptVec<TyParam> {
let tps = /*bad*/ (*tps).clone();
tps.map_move(|tp| fold_ty_param(tp, fld))
}
pub fn fold_lifetime(l: &Lifetime,
fld: @ast_fold) -> Lifetime {
Lifetime {id: fld.new_id(l.id),
span: fld.new_span(l.span),
ident: l.ident}
}
pub fn fold_lifetimes(lts: &OptVec<Lifetime>,
fld: @ast_fold) -> OptVec<Lifetime> {
lts.map(|l| fold_lifetime(l, fld))
}
pub fn fold_generics(generics: &Generics, fld: @ast_fold) -> Generics {
Generics {ty_params: fold_ty_params(&generics.ty_params, fld),
lifetimes: fold_lifetimes(&generics.lifetimes, fld)}
Generics {ty_params: fld.fold_ty_params(&generics.ty_params),
lifetimes: fld.fold_lifetimes(&generics.lifetimes)}
}
pub fn noop_fold_crate(c: &Crate, fld: @ast_fold) -> Crate {
let fold_meta_item = |x| fold_meta_item_(x, fld);
let fold_attribute = |x| fold_attribute_(x, fld);
Crate {
module: fld.fold_mod(&c.module),
attrs: c.attrs.map(|x| fold_attribute(*x)),
config: c.config.map(|x| fold_meta_item(*x)),
attrs: fld.fold_attributes(c.attrs),
config: fld.fold_meta_items(c.config),
span: fld.new_span(c.span),
}
}
fn noop_fold_view_item(vi: &view_item_, _fld: @ast_fold) -> view_item_ {
// FIXME #7654: doesn't iterate over idents in a view_item_use
return /* FIXME (#2543) */ (*vi).clone();
fn noop_fold_view_item(vi: &view_item_, fld: @ast_fold) -> view_item_ {
match *vi {
view_item_extern_mod(ident, name, ref meta_items, node_id) => {
view_item_extern_mod(ident,
name,
fld.fold_meta_items(*meta_items),
fld.new_id(node_id))
}
view_item_use(ref view_paths) => {
view_item_use(fld.fold_view_paths(*view_paths))
}
}
}
fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold)
-> @foreign_item {
let fold_arg = |x| fold_arg_(x, fld);
let fold_attribute = |x| fold_attribute_(x, fld);
@ast::foreign_item {
ident: fld.fold_ident(ni.ident),
attrs: ni.attrs.map(|x| fold_attribute(*x)),
attrs: fld.fold_attributes(ni.attrs),
node:
match ni.node {
foreign_item_fn(ref fdec, ref generics) => {
foreign_item_fn(
ast::fn_decl {
inputs: fdec.inputs.map(|a|
fold_arg(/*bad*/(*a).clone())),
inputs: fdec.inputs.map(|a| fld.fold_arg(a)),
output: fld.fold_ty(&fdec.output),
cf: fdec.cf,
},
@ -245,10 +318,8 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold)
}
pub fn noop_fold_item(i: @item, fld: @ast_fold) -> Option<@item> {
let fold_attribute = |x| fold_attribute_(x, fld);
Some(@ast::item { ident: fld.fold_ident(i.ident),
attrs: i.attrs.map(|e| fold_attribute(*e)),
attrs: fld.fold_attributes(i.attrs),
id: fld.new_id(i.id),
node: fld.fold_item_underscore(&i.node),
vis: i.vis,
@ -257,22 +328,35 @@ pub fn noop_fold_item(i: @item, fld: @ast_fold) -> Option<@item> {
fn noop_fold_struct_field(sf: @struct_field, fld: @ast_fold)
-> @struct_field {
let fold_attribute = |x| fold_attribute_(x, fld);
@Spanned {
node: ast::struct_field_ {
kind: sf.node.kind,
id: sf.node.id,
id: fld.new_id(sf.node.id),
ty: fld.fold_ty(&sf.node.ty),
attrs: sf.node.attrs.map(|e| fold_attribute(*e))
attrs: fld.fold_attributes(sf.node.attrs),
},
span: sf.span
}
}
pub fn noop_fold_type_method(m: &TypeMethod, fld: @ast_fold) -> TypeMethod {
TypeMethod {
ident: fld.fold_ident(m.ident),
attrs: fld.fold_attributes(m.attrs),
purity: m.purity,
decl: fold_fn_decl(&m.decl, fld),
generics: fold_generics(&m.generics, fld),
explicit_self: m.explicit_self,
id: fld.new_id(m.id),
span: fld.new_span(m.span),
}
}
pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ {
match *i {
item_static(ref t, m, e) => item_static(fld.fold_ty(t), m, fld.fold_expr(e)),
item_static(ref t, m, e) => {
item_static(fld.fold_ty(t), m, fld.fold_expr(e))
}
item_fn(ref decl, purity, abi, ref generics, ref body) => {
item_fn(
fold_fn_decl(decl, fld),
@ -282,7 +366,9 @@ pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ {
fld.fold_block(body)
)
}
item_mod(ref m) => item_mod(fld.fold_mod(m)),
item_mod(ref m) => {
item_mod(fld.fold_mod(m))
}
item_foreign_mod(ref nm) => {
item_foreign_mod(fld.fold_foreign_mod(nm))
}
@ -300,12 +386,12 @@ pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ {
}
item_struct(ref struct_def, ref generics) => {
let struct_def = fold_struct_def(*struct_def, fld);
item_struct(struct_def, /* FIXME (#2543) */ (*generics).clone())
item_struct(struct_def, fold_generics(generics, fld))
}
item_impl(ref generics, ref ifce, ref ty, ref methods) => {
item_impl(
fold_generics(generics, fld),
ifce.map(|p| fold_trait_ref(p, fld)),
ifce.map(|p| fld.fold_trait_ref(p)),
fld.fold_ty(ty),
methods.map(|x| fld.fold_method(*x))
)
@ -313,13 +399,13 @@ pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ {
item_trait(ref generics, ref traits, ref methods) => {
let methods = do methods.map |method| {
match *method {
required(*) => (*method).clone(),
required(ref m) => required(fld.fold_type_method(m)),
provided(method) => provided(fld.fold_method(method))
}
};
item_trait(
fold_generics(generics, fld),
traits.map(|p| fold_trait_ref(p, fld)),
traits.map(|p| fld.fold_trait_ref(p)),
methods
)
}
@ -337,20 +423,13 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: @ast_fold)
}
}
fn fold_trait_ref(p: &trait_ref, fld: @ast_fold) -> trait_ref {
ast::trait_ref {
path: fld.fold_path(&p.path),
ref_id: fld.new_id(p.ref_id),
}
}
fn fold_struct_field(f: @struct_field, fld: @ast_fold) -> @struct_field {
@Spanned {
node: ast::struct_field_ {
kind: f.node.kind,
id: fld.new_id(f.node.id),
ty: fld.fold_ty(&f.node.ty),
attrs: /* FIXME (#2543) */ f.node.attrs.clone(),
attrs: fld.fold_attributes(f.node.attrs),
},
span: fld.new_span(f.span),
}
@ -359,7 +438,7 @@ fn fold_struct_field(f: @struct_field, fld: @ast_fold) -> @struct_field {
fn noop_fold_method(m: @method, fld: @ast_fold) -> @method {
@ast::method {
ident: fld.fold_ident(m.ident),
attrs: /* FIXME (#2543) */ m.attrs.clone(),
attrs: fld.fold_attributes(m.attrs),
generics: fold_generics(&m.generics, fld),
explicit_self: m.explicit_self,
purity: m.purity,
@ -654,7 +733,7 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
fn fold_opt_bounds(b: &Option<OptVec<TyParamBound>>, fld: @ast_fold)
-> Option<OptVec<TyParamBound>> {
do b.map |bounds| {
do bounds.map |bound| { fold_ty_param_bound(bound, fld) }
do bounds.map |bound| { fld.fold_ty_param_bound(bound) }
}
}
match *t {
@ -672,12 +751,12 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
onceness: f.onceness,
bounds: fold_opt_bounds(&f.bounds, fld),
decl: fold_fn_decl(&f.decl, fld),
lifetimes: f.lifetimes.clone(),
lifetimes: fld.fold_lifetimes(&f.lifetimes)
})
}
ty_bare_fn(ref f) => {
ty_bare_fn(@TyBareFn {
lifetimes: f.lifetimes.clone(),
lifetimes: fld.fold_lifetimes(&f.lifetimes),
purity: f.purity,
abis: f.abis,
decl: fold_fn_decl(&f.decl, fld)
@ -715,29 +794,20 @@ fn noop_fold_foreign_mod(nm: &foreign_mod, fld: @ast_fold) -> foreign_mod {
}
fn noop_fold_variant(v: &variant_, fld: @ast_fold) -> variant_ {
fn fold_variant_arg_(va: variant_arg, fld: @ast_fold) -> variant_arg {
ast::variant_arg { ty: fld.fold_ty(&va.ty), id: fld.new_id(va.id) }
}
let fold_variant_arg = |x| fold_variant_arg_(x, fld);
let kind;
match v.kind {
let kind = match v.kind {
tuple_variant_kind(ref variant_args) => {
kind = tuple_variant_kind(do variant_args.map |x| {
fold_variant_arg(/*bad*/ (*x).clone())
})
tuple_variant_kind(variant_args.map(|x| fld.fold_variant_arg(x)))
}
struct_variant_kind(ref struct_def) => {
kind = struct_variant_kind(@ast::struct_def {
struct_variant_kind(@ast::struct_def {
fields: struct_def.fields.iter()
.map(|f| fld.fold_struct_field(*f)).collect(),
ctor_id: struct_def.ctor_id.map(|c| fld.new_id(*c))
})
}
}
};
let fold_attribute = |x| fold_attribute_(x, fld);
let attrs = v.attrs.map(|x| fold_attribute(*x));
let attrs = fld.fold_attributes(v.attrs);
let de = match v.disr_expr {
Some(e) => Some(fld.fold_expr(e)),
@ -811,6 +881,7 @@ pub fn default_ast_fold() -> ast_fold_fns {
fold_item: noop_fold_item,
fold_struct_field: noop_fold_struct_field,
fold_item_underscore: noop_fold_item_underscore,
fold_type_method: noop_fold_type_method,
fold_method: noop_fold_method,
fold_block: noop_fold_block,
fold_stmt: |x, s, fld| (noop_fold_stmt(x, fld), s),
@ -840,7 +911,7 @@ impl ast_fold for AstFoldFns {
fn fold_view_item(@self, x: &view_item) -> view_item {
ast::view_item {
node: (self.fold_view_item)(&x.node, self as @ast_fold),
attrs: x.attrs.iter().map(|a| fold_attribute_(*a, self as @ast_fold)).collect(),
attrs: self.fold_attributes(x.attrs),
vis: x.vis,
span: (self.new_span)(x.span),
}
@ -855,9 +926,9 @@ impl ast_fold for AstFoldFns {
@Spanned {
node: ast::struct_field_ {
kind: sf.node.kind,
id: sf.node.id,
id: (self.new_id)(sf.node.id),
ty: self.fold_ty(&sf.node.ty),
attrs: sf.node.attrs.clone(),
attrs: self.fold_attributes(sf.node.attrs),
},
span: (self.new_span)(sf.span),
}
@ -865,6 +936,9 @@ impl ast_fold for AstFoldFns {
fn fold_item_underscore(@self, i: &item_) -> item_ {
(self.fold_item_underscore)(i, self as @ast_fold)
}
fn fold_type_method(@self, m: &TypeMethod) -> TypeMethod {
(self.fold_type_method)(m, self as @ast_fold)
}
fn fold_method(@self, x: @method) -> @method {
(self.fold_method)(x, self as @ast_fold)
}
@ -949,16 +1023,6 @@ impl ast_fold for AstFoldFns {
}
}
pub trait AstFoldExtensions {
fn fold_attributes(&self, attrs: ~[Attribute]) -> ~[Attribute];
}
impl AstFoldExtensions for @ast_fold {
fn fold_attributes(&self, attrs: ~[Attribute]) -> ~[Attribute] {
attrs.map(|x| fold_attribute_(*x, *self))
}
}
// brson agrees with me that this function's existence is probably
// not a good or useful thing.
pub fn make_fold(afp: ast_fold_fns) -> @ast_fold {

View File

@ -11,7 +11,6 @@
//! The main parser interface
use ast::NodeId;
use ast;
use codemap::{Span, CodeMap, FileMap, FileSubstr};
use codemap;
@ -29,7 +28,6 @@ pub mod token;
pub mod comments;
pub mod attr;
/// Common routines shared by parser mods
pub mod common;
@ -42,7 +40,6 @@ pub mod obsolete;
// info about a parsing session.
pub struct ParseSess {
cm: @codemap::CodeMap, // better be the same as the one in the reader!
next_id: NodeId,
span_diagnostic: @mut span_handler, // better be the same as the one in the reader!
/// Used to determine and report recursive mod inclusions
included_mod_stack: ~[Path],
@ -52,7 +49,6 @@ pub fn new_parse_sess(demitter: Option<Emitter>) -> @mut ParseSess {
let cm = @CodeMap::new();
@mut ParseSess {
cm: cm,
next_id: 1,
span_diagnostic: mk_span_handler(mk_handler(demitter), cm),
included_mod_stack: ~[],
}
@ -63,7 +59,6 @@ pub fn new_parse_sess_special_handler(sh: @mut span_handler,
-> @mut ParseSess {
@mut ParseSess {
cm: cm,
next_id: 1,
span_diagnostic: sh,
included_mod_stack: ~[],
}
@ -201,15 +196,6 @@ pub fn parse_from_source_str<T>(
maybe_aborted(r,p)
}
// return the next unused node id.
pub fn next_node_id(sess: @mut ParseSess) -> NodeId {
let rv = sess.next_id;
sess.next_id += 1;
// ID 0 is reserved for the crate and doesn't actually exist in the AST
assert!(rv != 0);
return rv;
}
// Create a new parser from a source string
pub fn new_parser_from_source_str(sess: @mut ParseSess,
cfg: ast::CrateConfig,
@ -364,7 +350,7 @@ mod test {
#[test] fn path_exprs_1() {
assert_eq!(string_to_expr(@"a"),
@ast::Expr{
id: 1,
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(ast::Path {
span: sp(0, 1),
global: false,
@ -383,7 +369,7 @@ mod test {
#[test] fn path_exprs_2 () {
assert_eq!(string_to_expr(@"::a::b"),
@ast::Expr {
id:1,
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(ast::Path {
span: sp(0, 6),
global: true,
@ -441,9 +427,9 @@ mod test {
#[test] fn ret_expr() {
assert_eq!(string_to_expr(@"return d"),
@ast::Expr{
id:2,
id: ast::DUMMY_NODE_ID,
node:ast::ExprRet(Some(@ast::Expr{
id:1,
id: ast::DUMMY_NODE_ID,
node:ast::ExprPath(ast::Path{
span: sp(7, 8),
global: false,
@ -465,7 +451,7 @@ mod test {
assert_eq!(string_to_stmt(@"b;"),
@Spanned{
node: ast::StmtExpr(@ast::Expr {
id: 1,
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(ast::Path {
span:sp(0,1),
global:false,
@ -478,7 +464,7 @@ mod test {
],
}),
span: sp(0,1)},
2), // fixme
ast::DUMMY_NODE_ID),
span: sp(0,1)})
}
@ -490,7 +476,7 @@ mod test {
#[test] fn parse_ident_pat () {
let parser = string_to_parser(@"b");
assert_eq!(parser.parse_pat(),
@ast::Pat{id:1, // fixme
@ast::Pat{id: ast::DUMMY_NODE_ID,
node: ast::PatIdent(
ast::BindInfer,
ast::Path {
@ -511,17 +497,16 @@ mod test {
// check the contents of the tt manually:
#[test] fn parse_fundecl () {
// this test depends on the intern order of "fn" and "int", and on the
// assignment order of the NodeIds.
// this test depends on the intern order of "fn" and "int"
assert_eq!(string_to_item(@"fn a (b : int) { b; }"),
Some(
@ast::item{ident:str_to_ident("a"),
attrs:~[],
id: 9, // fixme
id: ast::DUMMY_NODE_ID,
node: ast::item_fn(ast::fn_decl{
inputs: ~[ast::arg{
is_mutbl: false,
ty: ast::Ty{id:3, // fixme
ty: ast::Ty{id: ast::DUMMY_NODE_ID,
node: ast::ty_path(ast::Path{
span:sp(10,13),
global:false,
@ -533,11 +518,11 @@ mod test {
types: opt_vec::Empty,
}
],
}, None, 2),
}, None, ast::DUMMY_NODE_ID),
span:sp(10,13)
},
pat: @ast::Pat {
id:1, // fixme
id: ast::DUMMY_NODE_ID,
node: ast::PatIdent(
ast::BindInfer,
ast::Path {
@ -556,9 +541,9 @@ mod test {
),
span: sp(6,7)
},
id: 4 // fixme
id: ast::DUMMY_NODE_ID
}],
output: ast::Ty{id:5, // fixme
output: ast::Ty{id: ast::DUMMY_NODE_ID,
node: ast::ty_nil,
span:sp(15,15)}, // not sure
cf: ast::return_val
@ -573,7 +558,7 @@ mod test {
view_items: ~[],
stmts: ~[@Spanned{
node: ast::StmtSemi(@ast::Expr{
id: 6,
id: ast::DUMMY_NODE_ID,
node: ast::ExprPath(
ast::Path{
span:sp(17,18),
@ -591,10 +576,10 @@ mod test {
],
}),
span: sp(17,18)},
7), // fixme
ast::DUMMY_NODE_ID),
span: sp(17,18)}],
expr: None,
id: 8, // fixme
id: ast::DUMMY_NODE_ID,
rules: ast::DefaultBlock, // no idea
span: sp(15,21),
}),

View File

@ -41,7 +41,7 @@ use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int, lit_char};
use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, Local};
use ast::{MutImmutable, MutMutable, mac_, mac_invoc_tt, matcher, match_nonterminal};
use ast::{match_seq, match_tok, method, mt, BiMul, Mutability};
use ast::{named_field, UnNeg, NodeId, noreturn, UnNot, Pat, PatBox, PatEnum};
use ast::{named_field, UnNeg, noreturn, UnNot, Pat, PatBox, PatEnum};
use ast::{PatIdent, PatLit, PatRange, PatRegion, PatStruct};
use ast::{PatTup, PatUniq, PatWild, private};
use ast::{BiRem, required};
@ -76,7 +76,7 @@ use parse::token::{is_ident_or_path};
use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents};
use parse::token::{token_to_binop};
use parse::token;
use parse::{new_sub_parser_from_file, next_node_id, ParseSess};
use parse::{new_sub_parser_from_file, ParseSess};
use opt_vec;
use opt_vec::OptVec;
@ -507,7 +507,7 @@ impl Parser {
let ident = self.parse_ident();
let hi = self.last_span.hi;
spanned(lo, hi, ast::path_list_ident_ { name: ident,
id: self.get_id() })
id: ast::DUMMY_NODE_ID })
}
// consume token 'tok' if it exists. Returns true if the given
@ -758,7 +758,6 @@ impl Parser {
pub fn abort_if_errors(&self) {
self.sess.span_diagnostic.handler().abort_if_errors();
}
pub fn get_id(&self) -> NodeId { next_node_id(self.sess) }
pub fn id_to_str(&self, id: Ident) -> @str {
get_ident_interner().get(id.name)
@ -961,7 +960,7 @@ impl Parser {
decl: d,
generics: generics,
explicit_self: explicit_self,
id: p.get_id(),
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi)
})
}
@ -978,9 +977,9 @@ impl Parser {
purity: pur,
decl: d,
body: body,
id: p.get_id(),
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
self_id: p.get_id(),
self_id: ast::DUMMY_NODE_ID,
vis: vis,
})
}
@ -1028,7 +1027,7 @@ impl Parser {
(
noreturn,
Ty {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ty_bot,
span: mk_sp(lo, self.last_span.hi)
}
@ -1041,7 +1040,7 @@ impl Parser {
(
return_val,
Ty {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ty_nil,
span: mk_sp(pos, pos),
}
@ -1154,14 +1153,14 @@ impl Parser {
path,
bounds
} = self.parse_path(LifetimeAndTypesAndBounds);
ty_path(path, bounds, self.get_id())
ty_path(path, bounds, ast::DUMMY_NODE_ID)
} else {
self.fatal(fmt!("expected type, found token %?",
*self.token));
};
let sp = mk_sp(lo, self.last_span.hi);
Ty {id: self.get_id(), node: t, span: sp}
Ty {id: ast::DUMMY_NODE_ID, node: t, span: sp}
}
// parse the type following a @ or a ~
@ -1275,7 +1274,7 @@ impl Parser {
pat
} else {
debug!("parse_arg_general ident_to_pat");
ast_util::ident_to_pat(self.get_id(),
ast_util::ident_to_pat(ast::DUMMY_NODE_ID,
*self.last_span,
special_idents::invalid)
};
@ -1286,7 +1285,7 @@ impl Parser {
is_mutbl: is_mutbl,
ty: t,
pat: pat,
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
}
}
@ -1304,7 +1303,7 @@ impl Parser {
self.parse_ty(false)
} else {
Ty {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ty_infer,
span: mk_sp(self.span.lo, self.span.hi),
}
@ -1313,7 +1312,7 @@ impl Parser {
is_mutbl: is_mutbl,
ty: t,
pat: pat,
id: self.get_id()
id: ast::DUMMY_NODE_ID
})
}
@ -1562,7 +1561,7 @@ impl Parser {
let span = self.span;
self.bump();
return ast::Lifetime {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
span: *span,
ident: i
};
@ -1575,7 +1574,7 @@ impl Parser {
self.expect(&token::BINOP(token::SLASH));
self.obsolete(*self.last_span, ObsoleteLifetimeNotation);
return ast::Lifetime {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
span: *span,
ident: i
};
@ -1654,18 +1653,18 @@ impl Parser {
pub fn mk_expr(&self, lo: BytePos, hi: BytePos, node: Expr_) -> @Expr {
@Expr {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: node,
span: mk_sp(lo, hi),
}
}
pub fn mk_unary(&self, unop: ast::UnOp, expr: @Expr) -> ast::Expr_ {
ExprUnary(self.get_id(), unop, expr)
ExprUnary(ast::DUMMY_NODE_ID, unop, expr)
}
pub fn mk_binary(&self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
ExprBinary(self.get_id(), binop, lhs, rhs)
ExprBinary(ast::DUMMY_NODE_ID, binop, lhs, rhs)
}
pub fn mk_call(&self, f: @Expr, args: ~[@Expr], sugar: CallSugar) -> ast::Expr_ {
@ -1678,11 +1677,11 @@ impl Parser {
tps: ~[Ty],
args: ~[@Expr],
sugar: CallSugar) -> ast::Expr_ {
ExprMethodCall(self.get_id(), rcvr, ident, tps, args, sugar)
ExprMethodCall(ast::DUMMY_NODE_ID, rcvr, ident, tps, args, sugar)
}
pub fn mk_index(&self, expr: @Expr, idx: @Expr) -> ast::Expr_ {
ExprIndex(self.get_id(), expr, idx)
ExprIndex(ast::DUMMY_NODE_ID, expr, idx)
}
pub fn mk_field(&self, expr: @Expr, ident: Ident, tys: ~[Ty]) -> ast::Expr_ {
@ -1690,12 +1689,12 @@ impl Parser {
}
pub fn mk_assign_op(&self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
ExprAssignOp(self.get_id(), binop, lhs, rhs)
ExprAssignOp(ast::DUMMY_NODE_ID, binop, lhs, rhs)
}
pub fn mk_mac_expr(&self, lo: BytePos, hi: BytePos, m: mac_) -> @Expr {
@Expr {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ExprMac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}),
span: mk_sp(lo, hi),
}
@ -1709,7 +1708,7 @@ impl Parser {
};
@Expr {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ExprLit(lv_lit),
span: *span,
}
@ -2415,7 +2414,7 @@ impl Parser {
ast::fn_decl {
inputs: ~[],
output: Ty {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ty_infer,
span: *self.span
},
@ -2450,7 +2449,7 @@ impl Parser {
view_items: ~[],
stmts: ~[],
expr: Some(body),
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
rules: DefaultBlock,
span: body.span,
};
@ -2631,7 +2630,7 @@ impl Parser {
view_items: ~[],
stmts: ~[],
expr: Some(expr),
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
rules: DefaultBlock,
span: expr.span,
};
@ -2764,7 +2763,7 @@ impl Parser {
subpat = self.parse_pat();
} else {
subpat = @ast::Pat {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: PatIdent(BindInfer, fieldpath, None),
span: *self.last_span
};
@ -2788,7 +2787,7 @@ impl Parser {
pat = PatWild;
hi = self.last_span.hi;
return @ast::Pat {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: pat,
span: mk_sp(lo, hi)
}
@ -2806,7 +2805,7 @@ impl Parser {
span: _}), _
}) => {
let vst = @Expr {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ExprVstore(e, ExprVstoreBox),
span: mk_sp(lo, hi),
};
@ -2816,7 +2815,7 @@ impl Parser {
};
hi = self.last_span.hi;
return @ast::Pat {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: pat,
span: mk_sp(lo, hi)
}
@ -2834,7 +2833,7 @@ impl Parser {
span: _}), _
}) => {
let vst = @Expr {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ExprVstore(e, ExprVstoreUniq),
span: mk_sp(lo, hi),
};
@ -2844,7 +2843,7 @@ impl Parser {
};
hi = self.last_span.hi;
return @ast::Pat {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: pat,
span: mk_sp(lo, hi)
}
@ -2862,7 +2861,7 @@ impl Parser {
node: lit_str(_), span: _}), _
}) => {
let vst = @Expr {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ExprVstore(e, ExprVstoreSlice),
span: mk_sp(lo, hi)
};
@ -2872,7 +2871,7 @@ impl Parser {
};
hi = self.last_span.hi;
return @ast::Pat {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: pat,
span: mk_sp(lo, hi)
}
@ -2885,7 +2884,7 @@ impl Parser {
pat = PatWild;
hi = self.last_span.hi;
return @ast::Pat {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: pat,
span: mk_sp(lo, hi)
}
@ -2915,7 +2914,7 @@ impl Parser {
}
hi = self.last_span.hi;
return @ast::Pat {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: pat,
span: mk_sp(lo, hi)
}
@ -2930,7 +2929,7 @@ impl Parser {
pat = ast::PatVec(before, slice, after);
hi = self.last_span.hi;
return @ast::Pat {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: pat,
span: mk_sp(lo, hi)
}
@ -3046,7 +3045,7 @@ impl Parser {
}
hi = self.last_span.hi;
@ast::Pat {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: pat,
span: mk_sp(lo, hi),
}
@ -3095,7 +3094,7 @@ impl Parser {
}
let mut ty = Ty {
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: ty_infer,
span: mk_sp(lo, lo),
};
@ -3106,7 +3105,7 @@ impl Parser {
ty: ty,
pat: pat,
init: init,
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, self.last_span.hi),
}
}
@ -3136,7 +3135,7 @@ impl Parser {
let ty = self.parse_ty(false);
@spanned(lo, self.last_span.hi, ast::struct_field_ {
kind: named_field(name, pr),
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
ty: ty,
attrs: attrs,
})
@ -3159,7 +3158,7 @@ impl Parser {
check_expected_item(self, !item_attrs.is_empty());
self.expect_keyword(keywords::Let);
let decl = self.parse_let();
return @spanned(lo, decl.span.hi, StmtDecl(decl, self.get_id()));
return @spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID));
} else if is_ident(&*self.token)
&& !token::is_any_keyword(self.token)
&& self.look_ahead(1, |t| *t == token::NOT) {
@ -3208,7 +3207,7 @@ impl Parser {
lo, hi, id /*id is good here*/,
item_mac(spanned(lo, hi, mac_invoc_tt(pth, tts, EMPTY_CTXT))),
inherited, ~[/*no attrs*/]))),
self.get_id()));
ast::DUMMY_NODE_ID));
}
} else {
@ -3217,7 +3216,7 @@ impl Parser {
iovi_item(i) => {
let hi = i.span.hi;
let decl = @spanned(lo, hi, DeclItem(i));
return @spanned(lo, hi, StmtDecl(decl, self.get_id()));
return @spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID));
}
iovi_view_item(vi) => {
self.span_fatal(vi.span,
@ -3233,7 +3232,7 @@ impl Parser {
// Remainder are line-expr stmts.
let e = self.parse_expr_res(RESTRICT_STMT_EXPR);
return @spanned(lo, e.span.hi, StmtExpr(e, self.get_id()));
return @spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID));
}
}
@ -3298,7 +3297,7 @@ impl Parser {
for item in items.iter() {
let decl = @spanned(item.span.lo, item.span.hi, DeclItem(*item));
stmts.push(@spanned(item.span.lo, item.span.hi,
StmtDecl(decl, self.get_id())));
StmtDecl(decl, ast::DUMMY_NODE_ID)));
}
let mut attributes_box = attrs_remaining;
@ -3397,7 +3396,7 @@ impl Parser {
view_items: view_items,
stmts: stmts,
expr: expr,
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
rules: s,
span: mk_sp(lo, hi),
}
@ -3463,7 +3462,7 @@ impl Parser {
let opt_bounds = self.parse_optional_ty_param_bounds();
// For typarams we don't care about the difference b/w "<T>" and "<T:>".
let bounds = opt_bounds.unwrap_or_default(opt_vec::Empty);
ast::TyParam { ident: ident, id: self.get_id(), bounds: bounds }
ast::TyParam { ident: ident, id: ast::DUMMY_NODE_ID, bounds: bounds }
}
// parse a set of optional generic type parameter declarations
@ -3717,7 +3716,7 @@ impl Parser {
let output = if self.eat(&token::RARROW) {
self.parse_ty(false)
} else {
Ty { id: self.get_id(), node: ty_infer, span: *self.span }
Ty { id: ast::DUMMY_NODE_ID, node: ty_infer, span: *self.span }
};
ast::fn_decl {
@ -3739,7 +3738,7 @@ impl Parser {
attrs: ~[Attribute]) -> @item {
@ast::item { ident: ident,
attrs: attrs,
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
node: node,
vis: vis,
span: mk_sp(lo, hi) }
@ -3779,9 +3778,9 @@ impl Parser {
purity: pur,
decl: decl,
body: body,
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
self_id: self.get_id(),
self_id: ast::DUMMY_NODE_ID,
vis: visa,
}
}
@ -3873,7 +3872,7 @@ impl Parser {
fn parse_trait_ref(&self) -> trait_ref {
ast::trait_ref {
path: self.parse_path(LifetimeAndTypesWithoutColons).path,
ref_id: self.get_id(),
ref_id: ast::DUMMY_NODE_ID,
}
}
@ -3926,7 +3925,7 @@ impl Parser {
let lo = p.span.lo;
let struct_field_ = ast::struct_field_ {
kind: unnamed_field,
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
ty: p.parse_ty(false),
attrs: attrs,
};
@ -3947,8 +3946,8 @@ impl Parser {
);
}
let _ = self.get_id(); // XXX: Workaround for crazy bug.
let new_id = self.get_id();
let _ = ast::DUMMY_NODE_ID; // XXX: Workaround for crazy bug.
let new_id = ast::DUMMY_NODE_ID;
(class_name,
item_struct(@ast::struct_def {
fields: fields,
@ -4238,7 +4237,7 @@ impl Parser {
@ast::foreign_item { ident: ident,
attrs: attrs,
node: foreign_item_fn(decl, generics),
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
vis: vis }
}
@ -4264,7 +4263,7 @@ impl Parser {
@ast::foreign_item { ident: ident,
attrs: attrs,
node: foreign_item_static(ty, mutbl),
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
vis: vis }
}
@ -4386,7 +4385,7 @@ impl Parser {
let metadata = self.parse_optional_meta();
self.expect(&token::SEMI);
iovi_view_item(ast::view_item {
node: view_item_extern_mod(ident, maybe_path, metadata, self.get_id()),
node: view_item_extern_mod(ident, maybe_path, metadata, ast::DUMMY_NODE_ID),
attrs: attrs,
vis: visibility,
span: mk_sp(lo, self.last_span.hi)
@ -4461,7 +4460,7 @@ impl Parser {
for ty in arg_tys.move_iter() {
args.push(ast::variant_arg {
ty: ty,
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
});
}
kind = tuple_variant_kind(args);
@ -4477,7 +4476,7 @@ impl Parser {
name: ident,
attrs: variant_attrs,
kind: kind,
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
disr_expr: disr_expr,
vis: vis,
};
@ -4509,9 +4508,9 @@ impl Parser {
name: id,
attrs: ~[],
kind: tuple_variant_kind(
~[ast::variant_arg {ty: ty, id: self.get_id()}]
~[ast::variant_arg {ty: ty, id: ast::DUMMY_NODE_ID}]
),
id: self.get_id(),
id: ast::DUMMY_NODE_ID,
disr_expr: None,
vis: public,
});
@ -4886,7 +4885,7 @@ impl Parser {
return @spanned(lo, self.span.hi,
view_path_simple(first_ident,
path,
self.get_id()));
ast::DUMMY_NODE_ID));
}
token::MOD_SEP => {
@ -4920,7 +4919,7 @@ impl Parser {
}).collect()
};
return @spanned(lo, self.span.hi,
view_path_list(path, idents, self.get_id()));
view_path_list(path, idents, ast::DUMMY_NODE_ID));
}
// foo::bar::*
@ -4938,7 +4937,7 @@ impl Parser {
}).collect()
};
return @spanned(lo, self.span.hi,
view_path_glob(path, self.get_id()));
view_path_glob(path, ast::DUMMY_NODE_ID));
}
_ => break
@ -4961,7 +4960,7 @@ impl Parser {
};
return @spanned(lo,
self.last_span.hi,
view_path_simple(last, path, self.get_id()));
view_path_simple(last, path, ast::DUMMY_NODE_ID));
}
// matches view_paths = view_path | view_path , view_paths
@ -5008,7 +5007,7 @@ impl Parser {
}
else { None };
let metadata = self.parse_optional_meta();
view_item_extern_mod(ident, path, metadata, self.get_id())
view_item_extern_mod(ident, path, metadata, ast::DUMMY_NODE_ID)
} else {
self.bug("expected view item");
};

View File

@ -0,0 +1,29 @@
// Check that we do not ICE when compiling this
// macro, which reuses the expression `$id`
struct Foo {
a: int
}
pub enum Bar {
Bar1, Bar2(int, ~Bar),
}
impl Foo {
fn elaborate_stm(&mut self, s: ~Bar) -> ~Bar {
macro_rules! declare(
($id:expr, $rest:expr) => ({
self.check_id($id);
~Bar2($id, $rest)
})
);
match s {
~Bar2(id, rest) => declare!(id, self.elaborate_stm(rest)),
_ => fail!()
}
}
fn check_id(&mut self, s: int) { fail!() }
}
fn main() { }

View File

@ -0,0 +1,22 @@
enum T {
A(int),
B(float)
}
macro_rules! test(
($e:expr) => (
fn foo(a:T, b:T) -> T {
match (a, b) {
(A(x), A(y)) => A($e),
(B(x), B(y)) => B($e),
_ => fail!()
}
}
)
)
test!(x + y)
fn main() {
foo(A(1), A(2));
}