]> git.proxmox.com Git - rustc.git/blame - src/librustc_resolve/record_exports.rs
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / librustc_resolve / record_exports.rs
CommitLineData
1a4d82fc
JJ
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
92a42be0
SL
21use {Module, NameBinding, Resolver};
22use Namespace::{TypeNS, ValueNS};
1a4d82fc
JJ
23
24use build_reduced_graph;
c34b1796 25use module_to_string;
1a4d82fc
JJ
26
27use rustc::middle::def::Export;
28use syntax::ast;
1a4d82fc
JJ
29
30use std::ops::{Deref, DerefMut};
31use std::rc::Rc;
32
92a42be0
SL
33struct ExportRecorder<'a, 'b: 'a, 'tcx: 'b> {
34 resolver: &'a mut Resolver<'b, 'tcx>,
1a4d82fc
JJ
35}
36
37// Deref and DerefMut impls allow treating ExportRecorder as Resolver.
38impl<'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
46impl<'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
52impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
92a42be0 53 fn record_exports_for_module_subtree(&mut self, module_: Rc<Module>) {
1a4d82fc
JJ
54 // If this isn't a local krate, then bail out. We don't need to record
55 // exports for nonlocal crates.
56
92a42be0 57 match module_.def_id() {
e9174d1e 58 Some(def_id) if def_id.is_local() => {
1a4d82fc 59 // OK. Continue.
92a42be0
SL
60 debug!("(recording exports for module subtree) recording exports for local \
61 module `{}`",
c34b1796 62 module_to_string(&*module_));
1a4d82fc
JJ
63 }
64 None => {
65 // Record exports for the root module.
92a42be0
SL
66 debug!("(recording exports for module subtree) recording exports for root module \
67 `{}`",
c34b1796 68 module_to_string(&*module_));
1a4d82fc
JJ
69 }
70 Some(_) => {
71 // Bail out.
92a42be0 72 debug!("(recording exports for module subtree) not recording exports for `{}`",
c34b1796 73 module_to_string(&*module_));
1a4d82fc
JJ
74 return;
75 }
76 }
77
78 self.record_exports_for_module(&*module_);
79 build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
80
62682a34 81 for (_, child_name_bindings) in module_.children.borrow().iter() {
92a42be0 82 match child_name_bindings.type_ns.module() {
1a4d82fc
JJ
83 None => {
84 // Nothing to do.
85 }
86 Some(child_module) => {
87 self.record_exports_for_module_subtree(child_module);
88 }
89 }
90 }
91
62682a34 92 for (_, child_module) in module_.anonymous_children.borrow().iter() {
1a4d82fc
JJ
93 self.record_exports_for_module_subtree(child_module.clone());
94 }
95 }
96
97 fn record_exports_for_module(&mut self, module_: &Module) {
98 let mut exports = Vec::new();
99
100 self.add_exports_for_module(&mut exports, module_);
92a42be0 101 match module_.def_id() {
1a4d82fc 102 Some(def_id) => {
b039eaaf
SL
103 let node_id = self.ast_map.as_local_node_id(def_id).unwrap();
104 self.export_map.insert(node_id, exports);
105 debug!("(computing exports) writing exports for {} (some)", node_id);
1a4d82fc
JJ
106 }
107 None => {}
108 }
109 }
110
92a42be0
SL
111 fn add_export_of_namebinding(&mut self,
112 exports: &mut Vec<Export>,
113 name: ast::Name,
114 namebinding: &NameBinding) {
115 match namebinding.def() {
1a4d82fc
JJ
116 Some(d) => {
117 debug!("(computing exports) YES: export '{}' => {:?}",
92a42be0
SL
118 name,
119 d.def_id());
1a4d82fc
JJ
120 exports.push(Export {
121 name: name,
92a42be0 122 def_id: d.def_id(),
1a4d82fc
JJ
123 });
124 }
125 d_opt => {
126 debug!("(computing exports) NO: {:?}", d_opt);
127 }
128 }
129 }
130
92a42be0 131 fn add_exports_for_module(&mut self, exports: &mut Vec<Export>, module_: &Module) {
62682a34 132 for (name, import_resolution) in module_.import_resolutions.borrow().iter() {
c34b1796 133 if !import_resolution.is_public {
92a42be0 134 continue;
1a4d82fc
JJ
135 }
136 let xs = [TypeNS, ValueNS];
85aaf69f 137 for &ns in &xs {
c34b1796 138 match import_resolution.target_for_namespace(ns) {
1a4d82fc 139 Some(target) => {
92a42be0
SL
140 debug!("(computing exports) maybe export '{}'", name);
141 self.add_export_of_namebinding(exports, *name, &target.binding)
1a4d82fc 142 }
92a42be0 143 _ => (),
1a4d82fc
JJ
144 }
145 }
146 }
147 }
148}
149
150pub fn record(resolver: &mut Resolver) {
151 let mut recorder = ExportRecorder { resolver: resolver };
92a42be0 152 let root_module = recorder.graph_root.clone();
1a4d82fc
JJ
153 recorder.record_exports_for_module_subtree(root_module);
154}