]> git.proxmox.com Git - rustc.git/blob - src/librustc_resolve/assign_ids.rs
New upstream version 1.12.0+dfsg1
[rustc.git] / src / librustc_resolve / assign_ids.rs
1 // Copyright 2016 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 Resolver;
12 use rustc::session::Session;
13 use syntax::ast;
14 use syntax::ext::hygiene::Mark;
15 use syntax::fold::{self, Folder};
16 use syntax::ptr::P;
17 use syntax::util::move_map::MoveMap;
18 use syntax::util::small_vector::SmallVector;
19
20 use std::collections::HashMap;
21 use std::mem;
22
23 impl<'a> Resolver<'a> {
24 pub fn assign_node_ids(&mut self, krate: ast::Crate) -> ast::Crate {
25 NodeIdAssigner {
26 sess: self.session,
27 macros_at_scope: &mut self.macros_at_scope,
28 }.fold_crate(krate)
29 }
30 }
31
32 struct NodeIdAssigner<'a> {
33 sess: &'a Session,
34 macros_at_scope: &'a mut HashMap<ast::NodeId, Vec<Mark>>,
35 }
36
37 impl<'a> Folder for NodeIdAssigner<'a> {
38 fn new_id(&mut self, old_id: ast::NodeId) -> ast::NodeId {
39 assert_eq!(old_id, ast::DUMMY_NODE_ID);
40 self.sess.next_node_id()
41 }
42
43 fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
44 block.map(|mut block| {
45 block.id = self.new_id(block.id);
46
47 let stmt = block.stmts.pop();
48 let mut macros = Vec::new();
49 block.stmts = block.stmts.move_flat_map(|stmt| {
50 if let ast::StmtKind::Item(ref item) = stmt.node {
51 if let ast::ItemKind::Mac(..) = item.node {
52 macros.push(item.ident.ctxt.data().outer_mark);
53 return None;
54 }
55 }
56
57 let stmt = self.fold_stmt(stmt).pop().unwrap();
58 if !macros.is_empty() {
59 self.macros_at_scope.insert(stmt.id, mem::replace(&mut macros, Vec::new()));
60 }
61 Some(stmt)
62 });
63
64 stmt.and_then(|mut stmt| {
65 // Avoid wasting a node id on a trailing expression statement,
66 // which shares a HIR node with the expression itself.
67 if let ast::StmtKind::Expr(expr) = stmt.node {
68 let expr = self.fold_expr(expr);
69 stmt.id = expr.id;
70 stmt.node = ast::StmtKind::Expr(expr);
71 Some(stmt)
72 } else {
73 self.fold_stmt(stmt).pop()
74 }
75 }).map(|stmt| {
76 if !macros.is_empty() {
77 self.macros_at_scope.insert(stmt.id, mem::replace(&mut macros, Vec::new()));
78 }
79 block.stmts.push(stmt);
80 });
81
82 block
83 })
84 }
85
86 fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
87 match item.node {
88 ast::ItemKind::Mac(..) => SmallVector::zero(),
89 _ => fold::noop_fold_item(item, self),
90 }
91 }
92 }