]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/assign_ids.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.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 rustc::util::nodemap::FnvHashMap;
14 use syntax::ast;
15 use syntax::ext::hygiene::Mark;
16 use syntax::fold::{self, Folder};
17 use syntax::ptr::P;
18 use syntax::util::move_map::MoveMap;
19 use syntax::util::small_vector::SmallVector;
20
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 FnvHashMap<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 }