]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/record_exports.rs
rollup merge of #20350: fhahn/issue-20340-rustdoc-version
[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::{mod, TypeNS, ValueNS};
23
24 use build_reduced_graph;
25
26 use rustc::middle::def::Export;
27 use syntax::ast;
28 use syntax::parse::token;
29
30 use std::rc::Rc;
31
32 struct ExportRecorder<'a, 'b:'a, 'tcx:'b> {
33     resolver: &'a mut Resolver<'b, 'tcx>
34 }
35
36 // Deref and DerefMut impls allow treating ExportRecorder as Resolver.
37 impl<'a, 'b, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> {
38     fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
39         &*self.resolver
40     }
41 }
42
43 impl<'a, 'b, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for ExportRecorder<'a, 'b, 'tcx> {
44     fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
45         &mut *self.resolver
46     }
47 }
48
49 impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
50     fn record_exports_for_module_subtree(&mut self,
51                                          module_: Rc<Module>) {
52         // If this isn't a local krate, then bail out. We don't need to record
53         // exports for nonlocal crates.
54
55         match module_.def_id.get() {
56             Some(def_id) if def_id.krate == ast::LOCAL_CRATE => {
57                 // OK. Continue.
58                 debug!("(recording exports for module subtree) recording \
59                         exports for local module `{}`",
60                        self.module_to_string(&*module_));
61             }
62             None => {
63                 // Record exports for the root module.
64                 debug!("(recording exports for module subtree) recording \
65                         exports for root module `{}`",
66                        self.module_to_string(&*module_));
67             }
68             Some(_) => {
69                 // Bail out.
70                 debug!("(recording exports for module subtree) not recording \
71                         exports for `{}`",
72                        self.module_to_string(&*module_));
73                 return;
74             }
75         }
76
77         self.record_exports_for_module(&*module_);
78         build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
79
80         for (_, child_name_bindings) in module_.children.borrow().iter() {
81             match child_name_bindings.get_module_if_available() {
82                 None => {
83                     // Nothing to do.
84                 }
85                 Some(child_module) => {
86                     self.record_exports_for_module_subtree(child_module);
87                 }
88             }
89         }
90
91         for (_, child_module) in module_.anonymous_children.borrow().iter() {
92             self.record_exports_for_module_subtree(child_module.clone());
93         }
94     }
95
96     fn record_exports_for_module(&mut self, module_: &Module) {
97         let mut exports = Vec::new();
98
99         self.add_exports_for_module(&mut exports, module_);
100         match module_.def_id.get() {
101             Some(def_id) => {
102                 self.export_map.insert(def_id.node, exports);
103                 debug!("(computing exports) writing exports for {} (some)",
104                        def_id.node);
105             }
106             None => {}
107         }
108     }
109
110     fn add_exports_of_namebindings(&mut self,
111                                    exports: &mut Vec<Export>,
112                                    name: ast::Name,
113                                    namebindings: &NameBindings,
114                                    ns: Namespace) {
115         match namebindings.def_for_namespace(ns) {
116             Some(d) => {
117                 debug!("(computing exports) YES: export '{}' => {}",
118                        name, d.def_id());
119                 exports.push(Export {
120                     name: name,
121                     def_id: d.def_id()
122                 });
123             }
124             d_opt => {
125                 debug!("(computing exports) NO: {}", d_opt);
126             }
127         }
128     }
129
130     fn add_exports_for_module(&mut self,
131                               exports: &mut Vec<Export>,
132                               module_: &Module) {
133         for (name, importresolution) in module_.import_resolutions.borrow().iter() {
134             if !importresolution.is_public {
135                 continue
136             }
137             let xs = [TypeNS, ValueNS];
138             for &ns in xs.iter() {
139                 match importresolution.target_for_namespace(ns) {
140                     Some(target) => {
141                         debug!("(computing exports) maybe export '{}'",
142                                token::get_name(*name));
143                         self.add_exports_of_namebindings(exports,
144                                                          *name,
145                                                          &*target.bindings,
146                                                          ns)
147                     }
148                     _ => ()
149                 }
150             }
151         }
152     }
153 }
154
155 pub fn record(resolver: &mut Resolver) {
156     let mut recorder = ExportRecorder { resolver: resolver };
157     let root_module = recorder.graph_root.get_module();
158     recorder.record_exports_for_module_subtree(root_module);
159 }