]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/record_exports.rs
Auto merge of #28355 - DiamondLovesYou:pnacl-librustc-trans, r=alexcrichton
[rust.git] / src / librustc_resolve / record_exports.rs
1 // Copyright 2012-2014 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
12 // Export recording
13 //
14 // This pass simply determines what all "export" keywords refer to and
15 // writes the results into the export map.
16 //
17 // FIXME #4953 This pass will be removed once exports change to per-item.
18 // Then this operation can simply be performed as part of item (or import)
19 // processing.
20
21 use {Module, NameBindings, Resolver};
22 use Namespace::{self, TypeNS, ValueNS};
23
24 use build_reduced_graph;
25 use module_to_string;
26
27 use rustc::middle::def::Export;
28 use syntax::ast;
29
30 use std::ops::{Deref, DerefMut};
31 use std::rc::Rc;
32
33 struct ExportRecorder<'a, 'b:'a, 'tcx:'b> {
34     resolver: &'a mut Resolver<'b, 'tcx>
35 }
36
37 // Deref and DerefMut impls allow treating ExportRecorder as Resolver.
38 impl<'a, 'b, 'tcx:'b> Deref for ExportRecorder<'a, 'b, 'tcx> {
39     type Target = Resolver<'b, 'tcx>;
40
41     fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
42         &*self.resolver
43     }
44 }
45
46 impl<'a, 'b, 'tcx:'b> DerefMut for ExportRecorder<'a, 'b, 'tcx> {
47     fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
48         &mut *self.resolver
49     }
50 }
51
52 impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
53     fn record_exports_for_module_subtree(&mut self,
54                                          module_: Rc<Module>) {
55         // If this isn't a local krate, then bail out. We don't need to record
56         // exports for nonlocal crates.
57
58         match module_.def_id.get() {
59             Some(def_id) if def_id.is_local() => {
60                 // OK. Continue.
61                 debug!("(recording exports for module subtree) recording \
62                         exports for local module `{}`",
63                        module_to_string(&*module_));
64             }
65             None => {
66                 // Record exports for the root module.
67                 debug!("(recording exports for module subtree) recording \
68                         exports for root module `{}`",
69                        module_to_string(&*module_));
70             }
71             Some(_) => {
72                 // Bail out.
73                 debug!("(recording exports for module subtree) not recording \
74                         exports for `{}`",
75                        module_to_string(&*module_));
76                 return;
77             }
78         }
79
80         self.record_exports_for_module(&*module_);
81         build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
82
83         for (_, child_name_bindings) in module_.children.borrow().iter() {
84             match child_name_bindings.get_module_if_available() {
85                 None => {
86                     // Nothing to do.
87                 }
88                 Some(child_module) => {
89                     self.record_exports_for_module_subtree(child_module);
90                 }
91             }
92         }
93
94         for (_, child_module) in module_.anonymous_children.borrow().iter() {
95             self.record_exports_for_module_subtree(child_module.clone());
96         }
97     }
98
99     fn record_exports_for_module(&mut self, module_: &Module) {
100         let mut exports = Vec::new();
101
102         self.add_exports_for_module(&mut exports, module_);
103         match module_.def_id.get() {
104             Some(def_id) => {
105                 let node_id = self.ast_map.as_local_node_id(def_id).unwrap();
106                 self.export_map.insert(node_id, exports);
107                 debug!("(computing exports) writing exports for {} (some)", node_id);
108             }
109             None => {}
110         }
111     }
112
113     fn add_exports_of_namebindings(&mut self,
114                                    exports: &mut Vec<Export>,
115                                    name: ast::Name,
116                                    namebindings: &NameBindings,
117                                    ns: Namespace) {
118         match namebindings.def_for_namespace(ns) {
119             Some(d) => {
120                 debug!("(computing exports) YES: export '{}' => {:?}",
121                        name, d.def_id());
122                 exports.push(Export {
123                     name: name,
124                     def_id: d.def_id()
125                 });
126             }
127             d_opt => {
128                 debug!("(computing exports) NO: {:?}", d_opt);
129             }
130         }
131     }
132
133     fn add_exports_for_module(&mut self,
134                               exports: &mut Vec<Export>,
135                               module_: &Module) {
136         for (name, import_resolution) in module_.import_resolutions.borrow().iter() {
137             if !import_resolution.is_public {
138                 continue
139             }
140             let xs = [TypeNS, ValueNS];
141             for &ns in &xs {
142                 match import_resolution.target_for_namespace(ns) {
143                     Some(target) => {
144                         debug!("(computing exports) maybe export '{}'",
145                                name);
146                         self.add_exports_of_namebindings(exports,
147                                                          *name,
148                                                          &*target.bindings,
149                                                          ns)
150                     }
151                     _ => ()
152                 }
153             }
154         }
155     }
156 }
157
158 pub fn record(resolver: &mut Resolver) {
159     let mut recorder = ExportRecorder { resolver: resolver };
160     let root_module = recorder.graph_root.get_module();
161     recorder.record_exports_for_module_subtree(root_module);
162 }