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