]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/build_reduced_graph.rs
Auto merge of #35856 - phimuemue:master, r=brson
[rust.git] / src / librustc_resolve / build_reduced_graph.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 //! Reduced graph building
12 //!
13 //! Here we build the "reduced graph": the graph of the module tree without
14 //! any imports resolved.
15
16 use resolve_imports::ImportDirectiveSubclass::{self, GlobImport};
17 use Module;
18 use Namespace::{self, TypeNS, ValueNS};
19 use {NameBinding, NameBindingKind, ToNameBinding};
20 use ParentLink::{ModuleParentLink, BlockParentLink};
21 use Resolver;
22 use {resolve_error, resolve_struct_error, ResolutionError};
23
24 use rustc::middle::cstore::{ChildItem, DlDef};
25 use rustc::hir::def::*;
26 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
27 use rustc::ty::{self, VariantKind};
28
29 use std::cell::Cell;
30
31 use syntax::ast::Name;
32 use syntax::attr;
33 use syntax::parse::token;
34
35 use syntax::ast::{Block, Crate};
36 use syntax::ast::{ForeignItem, ForeignItemKind, Item, ItemKind};
37 use syntax::ast::{Mutability, StmtKind, TraitItemKind};
38 use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
39 use syntax::parse::token::keywords;
40 use syntax::visit::{self, Visitor};
41
42 use syntax_pos::{Span, DUMMY_SP};
43
44 impl<'a> ToNameBinding<'a> for (Module<'a>, Span, ty::Visibility) {
45     fn to_name_binding(self) -> NameBinding<'a> {
46         NameBinding { kind: NameBindingKind::Module(self.0), span: self.1, vis: self.2 }
47     }
48 }
49
50 impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
51     fn to_name_binding(self) -> NameBinding<'a> {
52         NameBinding { kind: NameBindingKind::Def(self.0), span: self.1, vis: self.2 }
53     }
54 }
55
56 impl<'b> Resolver<'b> {
57     /// Constructs the reduced graph for the entire crate.
58     pub fn build_reduced_graph(&mut self, krate: &Crate) {
59         let no_implicit_prelude = attr::contains_name(&krate.attrs, "no_implicit_prelude");
60         self.graph_root.no_implicit_prelude.set(no_implicit_prelude);
61         visit::walk_crate(&mut BuildReducedGraphVisitor { resolver: self }, krate);
62     }
63
64     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
65     /// otherwise, reports an error.
66     fn define<T>(&mut self, parent: Module<'b>, name: Name, ns: Namespace, def: T)
67         where T: ToNameBinding<'b>,
68     {
69         let binding = def.to_name_binding();
70         if let Err(old_binding) = self.try_define(parent, name, ns, binding.clone()) {
71             self.report_conflict(parent, name, ns, old_binding, &binding);
72         }
73     }
74
75     fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
76         // If any statements are items, we need to create an anonymous module
77         block.stmts.iter().any(|statement| match statement.node {
78             StmtKind::Item(_) => true,
79             _ => false,
80         })
81     }
82
83     /// Constructs the reduced graph for one item.
84     fn build_reduced_graph_for_item(&mut self, item: &Item) {
85         let parent = self.current_module;
86         let name = item.ident.name;
87         let sp = item.span;
88         let vis = self.resolve_visibility(&item.vis);
89
90         match item.node {
91             ItemKind::Use(ref view_path) => {
92                 // Extract and intern the module part of the path. For
93                 // globs and lists, the path is found directly in the AST;
94                 // for simple paths we have to munge the path a little.
95                 let module_path: Vec<Name> = match view_path.node {
96                     ViewPathSimple(_, ref full_path) => {
97                         full_path.segments
98                                  .split_last()
99                                  .unwrap()
100                                  .1
101                                  .iter()
102                                  .map(|seg| seg.identifier.name)
103                                  .collect()
104                     }
105
106                     ViewPathGlob(ref module_ident_path) |
107                     ViewPathList(ref module_ident_path, _) => {
108                         module_ident_path.segments
109                                          .iter()
110                                          .map(|seg| seg.identifier.name)
111                                          .collect()
112                     }
113                 };
114
115                 // Build up the import directives.
116                 let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
117
118                 match view_path.node {
119                     ViewPathSimple(binding, ref full_path) => {
120                         let source_name = full_path.segments.last().unwrap().identifier.name;
121                         if source_name.as_str() == "mod" || source_name.as_str() == "self" {
122                             resolve_error(self,
123                                           view_path.span,
124                                           ResolutionError::SelfImportsOnlyAllowedWithin);
125                         }
126
127                         let subclass = ImportDirectiveSubclass::single(binding.name, source_name);
128                         let span = view_path.span;
129                         self.add_import_directive(module_path, subclass, span, item.id, vis);
130                     }
131                     ViewPathList(_, ref source_items) => {
132                         // Make sure there's at most one `mod` import in the list.
133                         let mod_spans = source_items.iter().filter_map(|item| {
134                             if item.node.name.name == keywords::SelfValue.name() {
135                                 Some(item.span)
136                             } else {
137                                 None
138                             }
139                         }).collect::<Vec<Span>>();
140
141                         if mod_spans.len() > 1 {
142                             let mut e = resolve_struct_error(self,
143                                           mod_spans[0],
144                                           ResolutionError::SelfImportCanOnlyAppearOnceInTheList);
145                             for other_span in mod_spans.iter().skip(1) {
146                                 e.span_note(*other_span, "another `self` import appears here");
147                             }
148                             e.emit();
149                         }
150
151                         for source_item in source_items {
152                             let node = source_item.node;
153                             let (module_path, name, rename) = {
154                                 if node.name.name != keywords::SelfValue.name() {
155                                     let rename = node.rename.unwrap_or(node.name).name;
156                                     (module_path.clone(), node.name.name, rename)
157                                 } else {
158                                     let name = match module_path.last() {
159                                         Some(name) => *name,
160                                         None => {
161                                             resolve_error(
162                                                 self,
163                                                 source_item.span,
164                                                 ResolutionError::
165                                                 SelfImportOnlyInImportListWithNonEmptyPrefix
166                                             );
167                                             continue;
168                                         }
169                                     };
170                                     let module_path = module_path.split_last().unwrap().1;
171                                     let rename = node.rename.map(|i| i.name).unwrap_or(name);
172                                     (module_path.to_vec(), name, rename)
173                                 }
174                             };
175                             let subclass = ImportDirectiveSubclass::single(rename, name);
176                             let (span, id) = (source_item.span, source_item.node.id);
177                             self.add_import_directive(module_path, subclass, span, id, vis);
178                         }
179                     }
180                     ViewPathGlob(_) => {
181                         let subclass = GlobImport {
182                             is_prelude: is_prelude,
183                             max_vis: Cell::new(ty::Visibility::PrivateExternal),
184                         };
185                         let span = view_path.span;
186                         self.add_import_directive(module_path, subclass, span, item.id, vis);
187                     }
188                 }
189             }
190
191             ItemKind::ExternCrate(_) => {
192                 // n.b. we don't need to look at the path option here, because cstore already
193                 // did
194                 if let Some(crate_id) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
195                     let def_id = DefId {
196                         krate: crate_id,
197                         index: CRATE_DEF_INDEX,
198                     };
199                     let parent_link = ModuleParentLink(parent, name);
200                     let def = Def::Mod(def_id);
201                     let module = self.new_extern_crate_module(parent_link, def, item.id);
202                     self.define(parent, name, TypeNS, (module, sp, vis));
203
204                     self.build_reduced_graph_for_external_crate(module);
205                 }
206             }
207
208             ItemKind::Mod(..) => {
209                 let parent_link = ModuleParentLink(parent, name);
210                 let def = Def::Mod(self.definitions.local_def_id(item.id));
211                 let module = self.new_module(parent_link, Some(def), Some(item.id));
212                 module.no_implicit_prelude.set({
213                     parent.no_implicit_prelude.get() ||
214                         attr::contains_name(&item.attrs, "no_implicit_prelude")
215                 });
216                 self.define(parent, name, TypeNS, (module, sp, vis));
217                 self.module_map.insert(item.id, module);
218
219                 // Descend into the module.
220                 self.current_module = module;
221             }
222
223             ItemKind::ForeignMod(..) => {}
224
225             // These items live in the value namespace.
226             ItemKind::Static(_, m, _) => {
227                 let mutbl = m == Mutability::Mutable;
228                 let def = Def::Static(self.definitions.local_def_id(item.id), mutbl);
229                 self.define(parent, name, ValueNS, (def, sp, vis));
230             }
231             ItemKind::Const(_, _) => {
232                 let def = Def::Const(self.definitions.local_def_id(item.id));
233                 self.define(parent, name, ValueNS, (def, sp, vis));
234             }
235             ItemKind::Fn(_, _, _, _, _, _) => {
236                 let def = Def::Fn(self.definitions.local_def_id(item.id));
237                 self.define(parent, name, ValueNS, (def, sp, vis));
238             }
239
240             // These items live in the type namespace.
241             ItemKind::Ty(..) => {
242                 let def = Def::TyAlias(self.definitions.local_def_id(item.id));
243                 self.define(parent, name, TypeNS, (def, sp, vis));
244             }
245
246             ItemKind::Enum(ref enum_definition, _) => {
247                 let parent_link = ModuleParentLink(parent, name);
248                 let def = Def::Enum(self.definitions.local_def_id(item.id));
249                 let module = self.new_module(parent_link, Some(def), parent.normal_ancestor_id);
250                 self.define(parent, name, TypeNS, (module, sp, vis));
251
252                 for variant in &(*enum_definition).variants {
253                     let item_def_id = self.definitions.local_def_id(item.id);
254                     self.build_reduced_graph_for_variant(variant, item_def_id, module, vis);
255                 }
256             }
257
258             // These items live in both the type and value namespaces.
259             ItemKind::Struct(ref struct_def, _) => {
260                 // Define a name in the type namespace.
261                 let def = Def::Struct(self.definitions.local_def_id(item.id));
262                 self.define(parent, name, TypeNS, (def, sp, vis));
263
264                 // If this is a newtype or unit-like struct, define a name
265                 // in the value namespace as well
266                 if !struct_def.is_struct() {
267                     let def = Def::Struct(self.definitions.local_def_id(struct_def.id()));
268                     self.define(parent, name, ValueNS, (def, sp, vis));
269                 }
270
271                 // Record the def ID and fields of this struct.
272                 let field_names = struct_def.fields().iter().enumerate().map(|(index, field)| {
273                     self.resolve_visibility(&field.vis);
274                     field.ident.map(|ident| ident.name)
275                                .unwrap_or_else(|| token::intern(&index.to_string()))
276                 }).collect();
277                 let item_def_id = self.definitions.local_def_id(item.id);
278                 self.structs.insert(item_def_id, field_names);
279             }
280
281             ItemKind::Union(..) => panic!("`union` is not yet implemented"),
282
283             ItemKind::DefaultImpl(_, _) | ItemKind::Impl(..) => {}
284
285             ItemKind::Trait(_, _, _, ref items) => {
286                 let def_id = self.definitions.local_def_id(item.id);
287
288                 // Add all the items within to a new module.
289                 let parent_link = ModuleParentLink(parent, name);
290                 let def = Def::Trait(def_id);
291                 let module_parent =
292                     self.new_module(parent_link, Some(def), parent.normal_ancestor_id);
293                 self.define(parent, name, TypeNS, (module_parent, sp, vis));
294
295                 // Add the names of all the items to the trait info.
296                 for item in items {
297                     let item_def_id = self.definitions.local_def_id(item.id);
298                     let mut is_static_method = false;
299                     let (def, ns) = match item.node {
300                         TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS),
301                         TraitItemKind::Method(ref sig, _) => {
302                             is_static_method = !sig.decl.has_self();
303                             (Def::Method(item_def_id), ValueNS)
304                         }
305                         TraitItemKind::Type(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
306                         TraitItemKind::Macro(_) => panic!("unexpanded macro in resolve!"),
307                     };
308
309                     self.define(module_parent, item.ident.name, ns, (def, item.span, vis));
310
311                     self.trait_item_map.insert((item.ident.name, def_id), is_static_method);
312                 }
313             }
314             ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
315         }
316
317         visit::walk_item(&mut BuildReducedGraphVisitor { resolver: self }, item);
318         self.current_module = parent;
319     }
320
321     // Constructs the reduced graph for one variant. Variants exist in the
322     // type and value namespaces.
323     fn build_reduced_graph_for_variant(&mut self,
324                                        variant: &Variant,
325                                        item_id: DefId,
326                                        parent: Module<'b>,
327                                        vis: ty::Visibility) {
328         let name = variant.node.name.name;
329         if variant.node.data.is_struct() {
330             // Not adding fields for variants as they are not accessed with a self receiver
331             let variant_def_id = self.definitions.local_def_id(variant.node.data.id());
332             self.structs.insert(variant_def_id, Vec::new());
333         }
334
335         // Variants are always treated as importable to allow them to be glob used.
336         // All variants are defined in both type and value namespaces as future-proofing.
337         let def = Def::Variant(item_id, self.definitions.local_def_id(variant.node.data.id()));
338         self.define(parent, name, ValueNS, (def, variant.span, vis));
339         self.define(parent, name, TypeNS, (def, variant.span, vis));
340     }
341
342     /// Constructs the reduced graph for one foreign item.
343     fn build_reduced_graph_for_foreign_item(&mut self, foreign_item: &ForeignItem) {
344         let parent = self.current_module;
345         let name = foreign_item.ident.name;
346
347         let def = match foreign_item.node {
348             ForeignItemKind::Fn(..) => {
349                 Def::Fn(self.definitions.local_def_id(foreign_item.id))
350             }
351             ForeignItemKind::Static(_, m) => {
352                 Def::Static(self.definitions.local_def_id(foreign_item.id), m)
353             }
354         };
355         let vis = self.resolve_visibility(&foreign_item.vis);
356         self.define(parent, name, ValueNS, (def, foreign_item.span, vis));
357     }
358
359     fn build_reduced_graph_for_block(&mut self, block: &Block) {
360         let parent = self.current_module;
361         if self.block_needs_anonymous_module(block) {
362             let block_id = block.id;
363
364             debug!("(building reduced graph for block) creating a new anonymous module for block \
365                     {}",
366                    block_id);
367
368             let parent_link = BlockParentLink(parent, block_id);
369             let new_module = self.new_module(parent_link, None, parent.normal_ancestor_id);
370             self.module_map.insert(block_id, new_module);
371             self.current_module = new_module; // Descend into the block.
372         }
373
374         visit::walk_block(&mut BuildReducedGraphVisitor { resolver: self }, block);
375         self.current_module = parent;
376     }
377
378     /// Builds the reduced graph for a single item in an external crate.
379     fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcdef: ChildItem) {
380         let def = match xcdef.def {
381             DlDef(def) => def,
382             _ => return,
383         };
384
385         if let Def::ForeignMod(def_id) = def {
386             // Foreign modules have no names. Recur and populate eagerly.
387             for child in self.session.cstore.item_children(def_id) {
388                 self.build_reduced_graph_for_external_crate_def(parent, child);
389             }
390             return;
391         }
392
393         let name = xcdef.name;
394         let vis = if parent.is_trait() { ty::Visibility::Public } else { xcdef.vis };
395
396         match def {
397             Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) => {
398                 debug!("(building reduced graph for external crate) building module {} {:?}",
399                        name, vis);
400                 let parent_link = ModuleParentLink(parent, name);
401                 let module = self.new_module(parent_link, Some(def), None);
402                 let _ = self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis));
403             }
404             Def::Variant(_, variant_id) => {
405                 debug!("(building reduced graph for external crate) building variant {}", name);
406                 // Variants are always treated as importable to allow them to be glob used.
407                 // All variants are defined in both type and value namespaces as future-proofing.
408                 let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis));
409                 let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis));
410                 if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) {
411                     // Not adding fields for variants as they are not accessed with a self receiver
412                     self.structs.insert(variant_id, Vec::new());
413                 }
414             }
415             Def::Fn(..) |
416             Def::Static(..) |
417             Def::Const(..) |
418             Def::AssociatedConst(..) |
419             Def::Method(..) => {
420                 debug!("(building reduced graph for external crate) building value (fn/static) {}",
421                        name);
422                 let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis));
423             }
424             Def::Trait(def_id) => {
425                 debug!("(building reduced graph for external crate) building type {}", name);
426
427                 // If this is a trait, add all the trait item names to the trait
428                 // info.
429
430                 let trait_item_def_ids = self.session.cstore.trait_item_def_ids(def_id);
431                 for trait_item_def in &trait_item_def_ids {
432                     let trait_item_name =
433                         self.session.cstore.item_name(trait_item_def.def_id());
434
435                     debug!("(building reduced graph for external crate) ... adding trait item \
436                             '{}'",
437                            trait_item_name);
438
439                     self.trait_item_map.insert((trait_item_name, def_id), false);
440                 }
441
442                 let parent_link = ModuleParentLink(parent, name);
443                 let module = self.new_module(parent_link, Some(def), None);
444                 let _ = self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis));
445             }
446             Def::TyAlias(..) | Def::AssociatedTy(..) => {
447                 debug!("(building reduced graph for external crate) building type {}", name);
448                 let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis));
449             }
450             Def::Struct(def_id)
451                 if self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_none() => {
452                 debug!("(building reduced graph for external crate) building type and value for {}",
453                        name);
454                 let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis));
455                 if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) {
456                     let def = Def::Struct(ctor_def_id);
457                     let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis));
458                 }
459
460                 // Record the def ID and fields of this struct.
461                 let fields = self.session.cstore.struct_field_names(def_id);
462                 self.structs.insert(def_id, fields);
463             }
464             Def::Struct(..) => {}
465             Def::Local(..) |
466             Def::PrimTy(..) |
467             Def::TyParam(..) |
468             Def::Upvar(..) |
469             Def::Label(..) |
470             Def::SelfTy(..) |
471             Def::Err => {
472                 bug!("didn't expect `{:?}`", def);
473             }
474         }
475     }
476
477     /// Builds the reduced graph rooted at the 'use' directive for an external
478     /// crate.
479     fn build_reduced_graph_for_external_crate(&mut self, root: Module<'b>) {
480         let root_cnum = root.def_id().unwrap().krate;
481         for child in self.session.cstore.crate_top_level_items(root_cnum) {
482             self.build_reduced_graph_for_external_crate_def(root, child);
483         }
484     }
485
486     /// Ensures that the reduced graph rooted at the given external module
487     /// is built, building it if it is not.
488     pub fn populate_module_if_necessary(&mut self, module: Module<'b>) {
489         if module.populated.get() { return }
490         for child in self.session.cstore.item_children(module.def_id().unwrap()) {
491             self.build_reduced_graph_for_external_crate_def(module, child);
492         }
493         module.populated.set(true)
494     }
495 }
496
497 struct BuildReducedGraphVisitor<'a, 'b: 'a> {
498     resolver: &'a mut Resolver<'b>,
499 }
500
501 impl<'a, 'b> Visitor for BuildReducedGraphVisitor<'a, 'b> {
502     fn visit_item(&mut self, item: &Item) {
503         self.resolver.build_reduced_graph_for_item(item);
504     }
505
506     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
507         self.resolver.build_reduced_graph_for_foreign_item(foreign_item);
508     }
509
510     fn visit_block(&mut self, block: &Block) {
511         self.resolver.build_reduced_graph_for_block(block);
512     }
513 }