Skip to content

Commit a5ad4c3

Browse files
committed
Delay assignment of node ids until after expansion. Ensures that each AST node
has a unique id. Fixes numerous bugs in macro expansion and deriving. Add two representative tests. Fixes rust-lang#7971 Fixes rust-lang#6304 Fixes rust-lang#8367 Fixes rust-lang#8754 Fixes rust-lang#8852 Fixes rust-lang#2543 Fixes rust-lang#7654
1 parent ed695d4 commit a5ad4c3

28 files changed

+532
-384
lines changed

src/librustc/driver/driver.rs

+5
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ pub fn phase_2_configure_and_expand(sess: Session,
190190
crate = time(time_passes, ~"std injection", ||
191191
front::std_inject::maybe_inject_libstd_ref(sess, crate));
192192

193+
crate = time(time_passes, ~"assigning node ids", ||
194+
front::assign_node_ids::assign_node_ids(sess, crate));
195+
193196
return crate;
194197
}
195198

@@ -207,6 +210,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
207210
crate: @ast::Crate) -> CrateAnalysis {
208211

209212
let time_passes = sess.time_passes();
213+
210214
let ast_map = time(time_passes, ~"ast indexing", ||
211215
syntax::ast_map::map_crate(sess.diagnostic(), crate));
212216

@@ -812,6 +816,7 @@ pub fn build_session_(sopts: @session::options,
812816
building_library: @mut false,
813817
working_dir: os::getcwd(),
814818
lints: @mut HashMap::new(),
819+
node_id: @mut 1
815820
}
816821
}
817822

src/librustc/driver/session.rs

+56-46
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use syntax::abi;
2828
use syntax::parse::token;
2929
use syntax;
3030

31+
use std::int;
3132
use std::hashmap::HashMap;
3233

3334
#[deriving(Eq)]
@@ -216,57 +217,58 @@ pub struct Session_ {
216217
building_library: @mut bool,
217218
working_dir: Path,
218219
lints: @mut HashMap<ast::NodeId, ~[(lint::lint, codemap::Span, ~str)]>,
220+
node_id: @mut uint,
219221
}
220222

221223
pub type Session = @Session_;
222224

223225
impl Session_ {
224-
pub fn span_fatal(@self, sp: Span, msg: &str) -> ! {
226+
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
225227
self.span_diagnostic.span_fatal(sp, msg)
226228
}
227-
pub fn fatal(@self, msg: &str) -> ! {
229+
pub fn fatal(&self, msg: &str) -> ! {
228230
self.span_diagnostic.handler().fatal(msg)
229231
}
230-
pub fn span_err(@self, sp: Span, msg: &str) {
232+
pub fn span_err(&self, sp: Span, msg: &str) {
231233
self.span_diagnostic.span_err(sp, msg)
232234
}
233-
pub fn err(@self, msg: &str) {
235+
pub fn err(&self, msg: &str) {
234236
self.span_diagnostic.handler().err(msg)
235237
}
236-
pub fn err_count(@self) -> uint {
238+
pub fn err_count(&self) -> uint {
237239
self.span_diagnostic.handler().err_count()
238240
}
239-
pub fn has_errors(@self) -> bool {
241+
pub fn has_errors(&self) -> bool {
240242
self.span_diagnostic.handler().has_errors()
241243
}
242-
pub fn abort_if_errors(@self) {
244+
pub fn abort_if_errors(&self) {
243245
self.span_diagnostic.handler().abort_if_errors()
244246
}
245-
pub fn span_warn(@self, sp: Span, msg: &str) {
247+
pub fn span_warn(&self, sp: Span, msg: &str) {
246248
self.span_diagnostic.span_warn(sp, msg)
247249
}
248-
pub fn warn(@self, msg: &str) {
250+
pub fn warn(&self, msg: &str) {
249251
self.span_diagnostic.handler().warn(msg)
250252
}
251-
pub fn span_note(@self, sp: Span, msg: &str) {
253+
pub fn span_note(&self, sp: Span, msg: &str) {
252254
self.span_diagnostic.span_note(sp, msg)
253255
}
254-
pub fn note(@self, msg: &str) {
256+
pub fn note(&self, msg: &str) {
255257
self.span_diagnostic.handler().note(msg)
256258
}
257-
pub fn span_bug(@self, sp: Span, msg: &str) -> ! {
259+
pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
258260
self.span_diagnostic.span_bug(sp, msg)
259261
}
260-
pub fn bug(@self, msg: &str) -> ! {
262+
pub fn bug(&self, msg: &str) -> ! {
261263
self.span_diagnostic.handler().bug(msg)
262264
}
263-
pub fn span_unimpl(@self, sp: Span, msg: &str) -> ! {
265+
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
264266
self.span_diagnostic.span_unimpl(sp, msg)
265267
}
266-
pub fn unimpl(@self, msg: &str) -> ! {
268+
pub fn unimpl(&self, msg: &str) -> ! {
267269
self.span_diagnostic.handler().unimpl(msg)
268270
}
269-
pub fn add_lint(@self,
271+
pub fn add_lint(&self,
270272
lint: lint::lint,
271273
id: ast::NodeId,
272274
sp: Span,
@@ -277,77 +279,85 @@ impl Session_ {
277279
}
278280
self.lints.insert(id, ~[(lint, sp, msg)]);
279281
}
280-
pub fn next_node_id(@self) -> ast::NodeId {
281-
return syntax::parse::next_node_id(self.parse_sess);
282+
pub fn next_node_id(&self) -> ast::NodeId {
283+
self.reserve_node_ids(1)
282284
}
283-
pub fn diagnostic(@self) -> @mut diagnostic::span_handler {
285+
pub fn reserve_node_ids(&self, count: uint) -> ast::NodeId {
286+
let v = *self.node_id;
287+
*self.node_id += count;
288+
if v > (int::max_value as uint) {
289+
self.bug("Input too large, ran out of node ids!");
290+
}
291+
v as int
292+
}
293+
pub fn diagnostic(&self) -> @mut diagnostic::span_handler {
284294
self.span_diagnostic
285295
}
286-
pub fn debugging_opt(@self, opt: uint) -> bool {
296+
pub fn debugging_opt(&self, opt: uint) -> bool {
287297
(self.opts.debugging_opts & opt) != 0u
288298
}
289299
// This exists to help with refactoring to eliminate impossible
290300
// cases later on
291-
pub fn impossible_case(@self, sp: Span, msg: &str) -> ! {
301+
pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
292302
self.span_bug(sp, fmt!("Impossible case reached: %s", msg));
293303
}
294-
pub fn verbose(@self) -> bool { self.debugging_opt(verbose) }
295-
pub fn time_passes(@self) -> bool { self.debugging_opt(time_passes) }
296-
pub fn count_llvm_insns(@self) -> bool {
304+
pub fn verbose(&self) -> bool { self.debugging_opt(verbose) }
305+
pub fn time_passes(&self) -> bool { self.debugging_opt(time_passes) }
306+
pub fn count_llvm_insns(&self) -> bool {
297307
self.debugging_opt(count_llvm_insns)
298308
}
299-
pub fn count_type_sizes(@self) -> bool {
309+
pub fn count_type_sizes(&self) -> bool {
300310
self.debugging_opt(count_type_sizes)
301311
}
302-
pub fn time_llvm_passes(@self) -> bool {
312+
pub fn time_llvm_passes(&self) -> bool {
303313
self.debugging_opt(time_llvm_passes)
304314
}
305-
pub fn trans_stats(@self) -> bool { self.debugging_opt(trans_stats) }
306-
pub fn meta_stats(@self) -> bool { self.debugging_opt(meta_stats) }
307-
pub fn asm_comments(@self) -> bool { self.debugging_opt(asm_comments) }
308-
pub fn no_verify(@self) -> bool { self.debugging_opt(no_verify) }
309-
pub fn lint_llvm(@self) -> bool { self.debugging_opt(lint_llvm) }
310-
pub fn trace(@self) -> bool { self.debugging_opt(trace) }
311-
pub fn coherence(@self) -> bool { self.debugging_opt(coherence) }
312-
pub fn borrowck_stats(@self) -> bool { self.debugging_opt(borrowck_stats) }
313-
pub fn borrowck_note_pure(@self) -> bool {
315+
pub fn trans_stats(&self) -> bool { self.debugging_opt(trans_stats) }
316+
pub fn meta_stats(&self) -> bool { self.debugging_opt(meta_stats) }
317+
pub fn asm_comments(&self) -> bool { self.debugging_opt(asm_comments) }
318+
pub fn no_verify(&self) -> bool { self.debugging_opt(no_verify) }
319+
pub fn lint_llvm(&self) -> bool { self.debugging_opt(lint_llvm) }
320+
pub fn trace(&self) -> bool { self.debugging_opt(trace) }
321+
pub fn coherence(&self) -> bool { self.debugging_opt(coherence) }
322+
pub fn borrowck_stats(&self) -> bool { self.debugging_opt(borrowck_stats) }
323+
pub fn borrowck_note_pure(&self) -> bool {
314324
self.debugging_opt(borrowck_note_pure)
315325
}
316-
pub fn borrowck_note_loan(@self) -> bool {
326+
pub fn borrowck_note_loan(&self) -> bool {
317327
self.debugging_opt(borrowck_note_loan)
318328
}
319-
pub fn no_monomorphic_collapse(@self) -> bool {
329+
pub fn no_monomorphic_collapse(&self) -> bool {
320330
self.debugging_opt(no_monomorphic_collapse)
321331
}
322-
pub fn debug_borrows(@self) -> bool {
332+
pub fn debug_borrows(&self) -> bool {
323333
self.opts.optimize == No && !self.debugging_opt(no_debug_borrows)
324334
}
325-
pub fn once_fns(@self) -> bool { self.debugging_opt(once_fns) }
326-
pub fn print_llvm_passes(@self) -> bool {
335+
pub fn once_fns(&self) -> bool { self.debugging_opt(once_fns) }
336+
pub fn print_llvm_passes(&self) -> bool {
327337
self.debugging_opt(print_llvm_passes)
328338
}
329-
pub fn no_prepopulate_passes(@self) -> bool {
339+
pub fn no_prepopulate_passes(&self) -> bool {
330340
self.debugging_opt(no_prepopulate_passes)
331341
}
332-
pub fn no_vectorize_loops(@self) -> bool {
342+
pub fn no_vectorize_loops(&self) -> bool {
333343
self.debugging_opt(no_vectorize_loops)
334344
}
335-
pub fn no_vectorize_slp(@self) -> bool {
345+
pub fn no_vectorize_slp(&self) -> bool {
336346
self.debugging_opt(no_vectorize_slp)
337347
}
338348

339349
// pointless function, now...
340-
pub fn str_of(@self, id: ast::Ident) -> @str {
350+
pub fn str_of(&self, id: ast::Ident) -> @str {
341351
token::ident_to_str(&id)
342352
}
343353

344354
// pointless function, now...
345-
pub fn ident_of(@self, st: &str) -> ast::Ident {
355+
pub fn ident_of(&self, st: &str) -> ast::Ident {
346356
token::str_to_ident(st)
347357
}
348358

349359
// pointless function, now...
350-
pub fn intr(@self) -> @syntax::parse::token::ident_interner {
360+
pub fn intr(&self) -> @syntax::parse::token::ident_interner {
351361
token::get_ident_interner()
352362
}
353363
}

src/librustc/front/assign_node_ids.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2012 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+
use driver::session::Session;
12+
13+
use syntax::ast;
14+
use syntax::ast_util;
15+
16+
pub fn assign_node_ids(sess: Session, crate: @ast::Crate) -> @ast::Crate {
17+
let fold = ast_util::node_id_assigner(|| sess.next_node_id());
18+
@fold.fold_crate(crate)
19+
}

src/librustc/front/std_inject.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
4545

4646
let precursor = @fold::AstFoldFns {
4747
fold_crate: |crate, fld| {
48-
let n1 = sess.next_node_id();
48+
let n1 = ast::DUMMY_NODE_ID;
4949
let vi1 = ast::view_item {
5050
node: ast::view_item_extern_mod(
5151
sess.ident_of("std"), None, ~[], n1),
@@ -86,7 +86,7 @@ fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
8686
}
8787
},
8888
fold_mod: |module, fld| {
89-
let n2 = sess.next_node_id();
89+
let n2 = ast::DUMMY_NODE_ID;
9090

9191
let prelude_path = ast::Path {
9292
span: dummy_sp(),

src/librustc/front/test.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -280,10 +280,10 @@ fn mk_std(cx: &TestCtxt) -> ast::view_item {
280280
ast::view_item_use(
281281
~[@nospan(ast::view_path_simple(id_extra,
282282
path_node(~[id_extra]),
283-
cx.sess.next_node_id()))])
283+
ast::DUMMY_NODE_ID))])
284284
} else {
285285
let mi = attr::mk_name_value_item_str(@"vers", @"0.8-pre");
286-
ast::view_item_extern_mod(id_extra, None, ~[mi], cx.sess.next_node_id())
286+
ast::view_item_extern_mod(id_extra, None, ~[mi], ast::DUMMY_NODE_ID)
287287
};
288288
ast::view_item {
289289
node: vi,
@@ -325,7 +325,7 @@ fn mk_test_module(cx: &TestCtxt) -> @ast::item {
325325
let item = ast::item {
326326
ident: cx.sess.ident_of("__test"),
327327
attrs: ~[resolve_unexported_attr],
328-
id: cx.sess.next_node_id(),
328+
id: ast::DUMMY_NODE_ID,
329329
node: item_,
330330
vis: ast::public,
331331
span: dummy_sp(),
@@ -367,7 +367,7 @@ fn mk_test_module(cx: &TestCtxt) -> @ast::item {
367367
let item = ast::item {
368368
ident: cx.sess.ident_of("__test"),
369369
attrs: ~[resolve_unexported_attr],
370-
id: cx.sess.next_node_id(),
370+
id: ast::DUMMY_NODE_ID,
371371
node: item_,
372372
vis: ast::public,
373373
span: dummy_sp(),
@@ -448,15 +448,14 @@ fn mk_test_descs(cx: &TestCtxt) -> @ast::Expr {
448448
descs.push(mk_test_desc_and_fn_rec(cx, test));
449449
}
450450

451-
let sess = cx.sess;
452451
let inner_expr = @ast::Expr {
453-
id: sess.next_node_id(),
452+
id: ast::DUMMY_NODE_ID,
454453
node: ast::ExprVec(descs, ast::MutImmutable),
455454
span: dummy_sp(),
456455
};
457456

458457
@ast::Expr {
459-
id: sess.next_node_id(),
458+
id: ast::DUMMY_NODE_ID,
460459
node: ast::ExprVstore(inner_expr, ast::ExprVstoreSlice),
461460
span: dummy_sp(),
462461
}
@@ -475,15 +474,15 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::Expr {
475474
nospan(ast::lit_str(ast_util::path_name_i(path).to_managed()));
476475

477476
let name_expr = @ast::Expr {
478-
id: cx.sess.next_node_id(),
477+
id: ast::DUMMY_NODE_ID,
479478
node: ast::ExprLit(@name_lit),
480479
span: span
481480
};
482481

483482
let fn_path = path_node_global(path);
484483

485484
let fn_expr = @ast::Expr {
486-
id: cx.sess.next_node_id(),
485+
id: ast::DUMMY_NODE_ID,
487486
node: ast::ExprPath(fn_path),
488487
span: span,
489488
};
@@ -529,15 +528,15 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::Expr {
529528
nospan(ast::lit_str(ast_util::path_name_i(path).to_managed()));
530529

531530
let name_expr = @ast::Expr {
532-
id: cx.sess.next_node_id(),
531+
id: ast::DUMMY_NODE_ID,
533532
node: ast::ExprLit(@name_lit),
534533
span: span
535534
};
536535

537536
let fn_path = path_node_global(path);
538537

539538
let fn_expr = @ast::Expr {
540-
id: cx.sess.next_node_id(),
539+
id: ast::DUMMY_NODE_ID,
541540
node: ast::ExprPath(fn_path),
542541
span: span,
543542
};

src/librustc/middle/astencode.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,10 @@ fn reserve_id_range(sess: Session,
157157
// Handle the case of an empty range:
158158
if from_id_range.empty() { return from_id_range; }
159159
let cnt = from_id_range.max - from_id_range.min;
160-
let to_id_min = sess.parse_sess.next_id;
161-
let to_id_max = sess.parse_sess.next_id + cnt;
162-
sess.parse_sess.next_id = to_id_max;
163-
ast_util::id_range { min: to_id_min, max: to_id_min }
160+
assert!(cnt >= 0);
161+
let to_id_min = sess.reserve_node_ids(cnt as uint);
162+
let to_id_max = to_id_min + cnt;
163+
ast_util::id_range { min: to_id_min, max: to_id_max }
164164
}
165165

166166
impl ExtendedDecodeContext {

src/librustc/middle/resolve.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -5403,7 +5403,15 @@ impl Resolver {
54035403

54045404
pub fn record_def(@mut self, node_id: NodeId, def: Def) {
54055405
debug!("(recording def) recording %? for %?", def, node_id);
5406-
self.def_map.insert(node_id, def);
5406+
do self.def_map.insert_or_update_with(node_id, def) |_, old_value| {
5407+
// Resolve appears to "resolve" the same ID multiple
5408+
// times, so here is a sanity check it at least comes to
5409+
// the same conclusion! - nmatsakis
5410+
if def != *old_value {
5411+
self.session.bug(fmt!("node_id %? resolved first to %? \
5412+
and then %?", node_id, *old_value, def));
5413+
}
5414+
};
54075415
}
54085416

54095417
pub fn enforce_default_binding_mode(@mut self,

src/librustc/middle/typeck/coherence.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ use syntax::ast_util::{def_id_of_def, local_def};
4545
use syntax::codemap::Span;
4646
use syntax::opt_vec;
4747
use syntax::visit;
48-
use syntax::parse;
4948

5049
use std::hashmap::HashSet;
5150
use std::result::Ok;
@@ -334,7 +333,7 @@ impl CoherenceChecker {
334333
let provided = ty::provided_trait_methods(tcx, trait_ref.def_id);
335334
for trait_method in provided.iter() {
336335
// Synthesize an ID.
337-
let new_id = parse::next_node_id(tcx.sess.parse_sess);
336+
let new_id = tcx.sess.next_node_id();
338337
let new_did = local_def(new_id);
339338

340339
debug!("new_did=%? trait_method=%s", new_did, trait_method.repr(tcx));

0 commit comments

Comments
 (0)