]> git.proxmox.com Git - rustc.git/blame - src/librustc_resolve/build_reduced_graph.rs
* Introduce some changes by Angus Lees
[rustc.git] / src / librustc_resolve / build_reduced_graph.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//! Reduced graph building
12//!
13//! Here we build the "reduced graph": the graph of the module tree without
14//! any imports resolved.
15
16use {DefModifiers, PUBLIC, IMPORTABLE};
17use ImportDirective;
18use ImportDirectiveSubclass::{self, SingleImport, GlobImport};
19use ImportResolution;
20use Module;
21use ModuleKind::*;
22use Namespace::{TypeNS, ValueNS};
23use NameBindings;
24use ParentLink::{self, ModuleParentLink, BlockParentLink};
25use Resolver;
26use RibKind::*;
27use Shadowable;
28use TypeNsDef;
29use TypeParameters::HasTypeParameters;
30
31use self::DuplicateCheckingMode::*;
32use self::NamespaceError::*;
33
34use rustc::metadata::csearch;
35use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
36use rustc::middle::def::*;
37use rustc::middle::subst::FnSpace;
38
39use syntax::ast::{Block, Crate};
40use syntax::ast::{DeclItem, DefId};
41use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
42use syntax::ast::{Item, ItemConst, ItemEnum, ItemFn};
43use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
44use syntax::ast::{ItemStruct, ItemTrait, ItemTy};
45use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
46use syntax::ast::{PathListIdent, PathListMod};
47use syntax::ast::{Public, SelfStatic};
48use syntax::ast::StmtDecl;
49use syntax::ast::StructVariantKind;
50use syntax::ast::TupleVariantKind;
51use syntax::ast::TyObjectSum;
52use syntax::ast::{TypeImplItem, UnnamedField};
53use syntax::ast::{Variant, ViewItem, ViewItemExternCrate};
54use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple};
55use syntax::ast::{Visibility};
56use syntax::ast::TyPath;
57use syntax::ast;
58use syntax::ast_util::{self, PostExpansionMethod, local_def};
59use syntax::attr::AttrMetaMethods;
60use syntax::parse::token::{self, special_idents};
61use syntax::codemap::{Span, DUMMY_SP};
62use syntax::visit::{self, Visitor};
63
64use std::mem::replace;
65use std::ops::{Deref, DerefMut};
66use std::rc::Rc;
67
68// Specifies how duplicates should be handled when adding a child item if
69// another item exists with the same name in some namespace.
70#[derive(Copy, PartialEq)]
71enum DuplicateCheckingMode {
72 ForbidDuplicateModules,
73 ForbidDuplicateTypesAndModules,
74 ForbidDuplicateValues,
75 ForbidDuplicateTypesAndValues,
76 OverwriteDuplicates
77}
78
79#[derive(Copy, PartialEq)]
80enum NamespaceError {
81 NoError,
82 ModuleError,
83 TypeError,
84 ValueError
85}
86
87fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
88 match ns {
89 NoError => "",
90 ModuleError | TypeError => "type or module",
91 ValueError => "value",
92 }
93}
94
95struct GraphBuilder<'a, 'b:'a, 'tcx:'b> {
96 resolver: &'a mut Resolver<'b, 'tcx>
97}
98
99impl<'a, 'b:'a, 'tcx:'b> Deref for GraphBuilder<'a, 'b, 'tcx> {
100 type Target = Resolver<'b, 'tcx>;
101
102 fn deref(&self) -> &Resolver<'b, 'tcx> {
103 &*self.resolver
104 }
105}
106
107impl<'a, 'b:'a, 'tcx:'b> DerefMut for GraphBuilder<'a, 'b, 'tcx> {
108 fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> {
109 &mut *self.resolver
110 }
111}
112
113impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
114 /// Constructs the reduced graph for the entire crate.
115 fn build_reduced_graph(self, krate: &ast::Crate) {
116 let parent = self.graph_root.get_module();
117 let mut visitor = BuildReducedGraphVisitor {
118 builder: self,
119 parent: parent
120 };
121 visit::walk_crate(&mut visitor, krate);
122 }
123
124 /// Adds a new child item to the module definition of the parent node and
125 /// returns its corresponding name bindings as well as the current parent.
126 /// Or, if we're inside a block, creates (or reuses) an anonymous module
127 /// corresponding to the innermost block ID and returns the name bindings
128 /// as well as the newly-created parent.
129 ///
130 /// # Panics
131 ///
132 /// Panics if this node does not have a module definition and we are not inside
133 /// a block.
134 fn add_child(&self,
135 name: Name,
136 parent: &Rc<Module>,
137 duplicate_checking_mode: DuplicateCheckingMode,
138 // For printing errors
139 sp: Span)
140 -> Rc<NameBindings> {
141 // If this is the immediate descendant of a module, then we add the
142 // child name directly. Otherwise, we create or reuse an anonymous
143 // module and add the child to that.
144
145 self.check_for_conflicts_between_external_crates_and_items(&**parent,
146 name,
147 sp);
148
149 // Add or reuse the child.
150 let child = parent.children.borrow().get(&name).cloned();
151 match child {
152 None => {
153 let child = Rc::new(NameBindings::new());
154 parent.children.borrow_mut().insert(name, child.clone());
155 child
156 }
157 Some(child) => {
158 // Enforce the duplicate checking mode:
159 //
160 // * If we're requesting duplicate module checking, check that
161 // there isn't a module in the module with the same name.
162 //
163 // * If we're requesting duplicate type checking, check that
164 // there isn't a type in the module with the same name.
165 //
166 // * If we're requesting duplicate value checking, check that
167 // there isn't a value in the module with the same name.
168 //
169 // * If we're requesting duplicate type checking and duplicate
170 // value checking, check that there isn't a duplicate type
171 // and a duplicate value with the same name.
172 //
173 // * If no duplicate checking was requested at all, do
174 // nothing.
175
176 let mut duplicate_type = NoError;
177 let ns = match duplicate_checking_mode {
178 ForbidDuplicateModules => {
179 if child.get_module_if_available().is_some() {
180 duplicate_type = ModuleError;
181 }
182 Some(TypeNS)
183 }
184 ForbidDuplicateTypesAndModules => {
185 match child.def_for_namespace(TypeNS) {
186 None => {}
187 Some(_) if child.get_module_if_available()
188 .map(|m| m.kind.get()) ==
189 Some(ImplModuleKind) => {}
190 Some(_) => duplicate_type = TypeError
191 }
192 Some(TypeNS)
193 }
194 ForbidDuplicateValues => {
195 if child.defined_in_namespace(ValueNS) {
196 duplicate_type = ValueError;
197 }
198 Some(ValueNS)
199 }
200 ForbidDuplicateTypesAndValues => {
201 let mut n = None;
202 match child.def_for_namespace(TypeNS) {
203 Some(DefMod(_)) | None => {}
204 Some(_) => {
205 n = Some(TypeNS);
206 duplicate_type = TypeError;
207 }
208 };
209 if child.defined_in_namespace(ValueNS) {
210 duplicate_type = ValueError;
211 n = Some(ValueNS);
212 }
213 n
214 }
215 OverwriteDuplicates => None
216 };
217 if duplicate_type != NoError {
218 // Return an error here by looking up the namespace that
219 // had the duplicate.
220 let ns = ns.unwrap();
221 self.resolve_error(sp,
222 &format!("duplicate definition of {} `{}`",
223 namespace_error_to_string(duplicate_type),
224 token::get_name(name))[]);
225 {
226 let r = child.span_for_namespace(ns);
227 for sp in r.iter() {
228 self.session.span_note(*sp,
229 &format!("first definition of {} `{}` here",
230 namespace_error_to_string(duplicate_type),
231 token::get_name(name))[]);
232 }
233 }
234 }
235 child
236 }
237 }
238 }
239
240 fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
241 // If the block has view items, we need an anonymous module.
242 if block.view_items.len() > 0 {
243 return true;
244 }
245
246 // Check each statement.
247 for statement in block.stmts.iter() {
248 match statement.node {
249 StmtDecl(ref declaration, _) => {
250 match declaration.node {
251 DeclItem(_) => {
252 return true;
253 }
254 _ => {
255 // Keep searching.
256 }
257 }
258 }
259 _ => {
260 // Keep searching.
261 }
262 }
263 }
264
265 // If we found neither view items nor items, we don't need to create
266 // an anonymous module.
267
268 return false;
269 }
270
271 fn get_parent_link(&mut self, parent: &Rc<Module>, name: Name) -> ParentLink {
272 ModuleParentLink(parent.downgrade(), name)
273 }
274
275 /// Constructs the reduced graph for one item.
276 fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) -> Rc<Module> {
277 let name = item.ident.name;
278 let sp = item.span;
279 let is_public = item.vis == ast::Public;
280 let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
281
282 match item.node {
283 ItemMod(..) => {
284 let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp);
285
286 let parent_link = self.get_parent_link(parent, name);
287 let def_id = DefId { krate: 0, node: item.id };
288 name_bindings.define_module(parent_link,
289 Some(def_id),
290 NormalModuleKind,
291 false,
292 item.vis == ast::Public,
293 sp);
294
295 name_bindings.get_module()
296 }
297
298 ItemForeignMod(..) => parent.clone(),
299
300 // These items live in the value namespace.
301 ItemStatic(_, m, _) => {
302 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
303 let mutbl = m == ast::MutMutable;
304
305 name_bindings.define_value(DefStatic(local_def(item.id), mutbl), sp, modifiers);
306 parent.clone()
307 }
308 ItemConst(_, _) => {
309 self.add_child(name, parent, ForbidDuplicateValues, sp)
310 .define_value(DefConst(local_def(item.id)), sp, modifiers);
311 parent.clone()
312 }
313 ItemFn(_, _, _, _, _) => {
314 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
315
316 let def = DefFn(local_def(item.id), false);
317 name_bindings.define_value(def, sp, modifiers);
318 parent.clone()
319 }
320
321 // These items live in the type namespace.
322 ItemTy(..) => {
323 let name_bindings =
324 self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
325
326 name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
327 parent.clone()
328 }
329
330 ItemEnum(ref enum_definition, _) => {
331 let name_bindings =
332 self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
333
334 name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
335
336 let parent_link = self.get_parent_link(parent, name);
337 // We want to make sure the module type is EnumModuleKind
338 // even if there's already an ImplModuleKind module defined,
339 // since that's how we prevent duplicate enum definitions
340 name_bindings.set_module_kind(parent_link,
341 Some(local_def(item.id)),
342 EnumModuleKind,
343 false,
344 is_public,
345 sp);
346
347 let module = name_bindings.get_module();
348
349 for variant in (*enum_definition).variants.iter() {
350 self.build_reduced_graph_for_variant(
351 &**variant,
352 local_def(item.id),
353 &module);
354 }
355 parent.clone()
356 }
357
358 // These items live in both the type and value namespaces.
359 ItemStruct(ref struct_def, _) => {
360 // Adding to both Type and Value namespaces or just Type?
361 let (forbid, ctor_id) = match struct_def.ctor_id {
362 Some(ctor_id) => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
363 None => (ForbidDuplicateTypesAndModules, None)
364 };
365
366 let name_bindings = self.add_child(name, parent, forbid, sp);
367
368 // Define a name in the type namespace.
369 name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
370
371 // If this is a newtype or unit-like struct, define a name
372 // in the value namespace as well
373 if let Some(cid) = ctor_id {
374 name_bindings.define_value(DefStruct(local_def(cid)), sp, modifiers);
375 }
376
377 // Record the def ID and fields of this struct.
378 let named_fields = struct_def.fields.iter().filter_map(|f| {
379 match f.node.kind {
380 NamedField(ident, _) => Some(ident.name),
381 UnnamedField(_) => None
382 }
383 }).collect();
384 self.structs.insert(local_def(item.id), named_fields);
385
386 parent.clone()
387 }
388
389 ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
390 // If this implements an anonymous trait, then add all the
391 // methods within to a new module, if the type was defined
392 // within this module.
393
394 let mod_name = match ty.node {
395 TyPath(ref path, _) if path.segments.len() == 1 => {
396 // FIXME(18446) we should distinguish between the name of
397 // a trait and the name of an impl of that trait.
398 Some(path.segments.last().unwrap().identifier.name)
399 }
400 TyObjectSum(ref lhs_ty, _) => {
401 match lhs_ty.node {
402 TyPath(ref path, _) if path.segments.len() == 1 => {
403 Some(path.segments.last().unwrap().identifier.name)
404 }
405 _ => {
406 None
407 }
408 }
409 }
410 _ => {
411 None
412 }
413 };
414
415 match mod_name {
416 None => {
417 self.resolve_error(ty.span,
418 "inherent implementations may \
419 only be implemented in the same \
420 module as the type they are \
421 implemented for")
422 }
423 Some(mod_name) => {
424 // Create the module and add all methods.
425 let parent_opt = parent.children.borrow().get(&mod_name).cloned();
426 let new_parent = match parent_opt {
427 // It already exists
428 Some(ref child) if child.get_module_if_available()
429 .is_some() &&
430 (child.get_module().kind.get() == ImplModuleKind ||
431 child.get_module().kind.get() == TraitModuleKind) => {
432 child.get_module()
433 }
434 Some(ref child) if child.get_module_if_available()
435 .is_some() &&
436 child.get_module().kind.get() ==
437 EnumModuleKind => child.get_module(),
438 // Create the module
439 _ => {
440 let name_bindings =
441 self.add_child(mod_name, parent, ForbidDuplicateModules, sp);
442
443 let parent_link = self.get_parent_link(parent, name);
444 let def_id = local_def(item.id);
445 let ns = TypeNS;
446 let is_public =
447 !name_bindings.defined_in_namespace(ns) ||
448 name_bindings.defined_in_public_namespace(ns);
449
450 name_bindings.define_module(parent_link,
451 Some(def_id),
452 ImplModuleKind,
453 false,
454 is_public,
455 sp);
456
457 name_bindings.get_module()
458 }
459 };
460
461 // For each implementation item...
462 for impl_item in impl_items.iter() {
463 match *impl_item {
464 MethodImplItem(ref method) => {
465 // Add the method to the module.
466 let name = method.pe_ident().name;
467 let method_name_bindings =
468 self.add_child(name,
469 &new_parent,
470 ForbidDuplicateValues,
471 method.span);
472 let def = match method.pe_explicit_self()
473 .node {
474 SelfStatic => {
475 // Static methods become
476 // `DefStaticMethod`s.
477 DefStaticMethod(local_def(method.id),
478 FromImpl(local_def(item.id)))
479 }
480 _ => {
481 // Non-static methods become
482 // `DefMethod`s.
483 DefMethod(local_def(method.id),
484 None,
485 FromImpl(local_def(item.id)))
486 }
487 };
488
489 // NB: not IMPORTABLE
490 let modifiers = if method.pe_vis() == ast::Public {
491 PUBLIC
492 } else {
493 DefModifiers::empty()
494 };
495 method_name_bindings.define_value(
496 def,
497 method.span,
498 modifiers);
499 }
500 TypeImplItem(ref typedef) => {
501 // Add the typedef to the module.
502 let name = typedef.ident.name;
503 let typedef_name_bindings =
504 self.add_child(
505 name,
506 &new_parent,
507 ForbidDuplicateTypesAndModules,
508 typedef.span);
509 let def = DefAssociatedTy(local_def(
510 typedef.id));
511 // NB: not IMPORTABLE
512 let modifiers = if typedef.vis == ast::Public {
513 PUBLIC
514 } else {
515 DefModifiers::empty()
516 };
517 typedef_name_bindings.define_type(
518 def,
519 typedef.span,
520 modifiers);
521 }
522 }
523 }
524 }
525 }
526
527 parent.clone()
528 }
529
530 ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
531
532 ItemTrait(_, _, _, ref items) => {
533 let name_bindings =
534 self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
535
536 // Add all the items within to a new module.
537 let parent_link = self.get_parent_link(parent, name);
538 name_bindings.define_module(parent_link,
539 Some(local_def(item.id)),
540 TraitModuleKind,
541 false,
542 item.vis == ast::Public,
543 sp);
544 let module_parent = name_bindings.get_module();
545
546 let def_id = local_def(item.id);
547
548 // Add the names of all the items to the trait info.
549 for trait_item in items.iter() {
550 let (name, kind) = match *trait_item {
551 ast::RequiredMethod(_) |
552 ast::ProvidedMethod(_) => {
553 let ty_m = ast_util::trait_item_to_ty_method(trait_item);
554
555 let name = ty_m.ident.name;
556
557 // Add it as a name in the trait module.
558 let (def, static_flag) = match ty_m.explicit_self
559 .node {
560 SelfStatic => {
561 // Static methods become `DefStaticMethod`s.
562 (DefStaticMethod(
563 local_def(ty_m.id),
564 FromTrait(local_def(item.id))),
565 StaticMethodTraitItemKind)
566 }
567 _ => {
568 // Non-static methods become `DefMethod`s.
569 (DefMethod(local_def(ty_m.id),
570 Some(local_def(item.id)),
571 FromTrait(local_def(item.id))),
572 NonstaticMethodTraitItemKind)
573 }
574 };
575
576 let method_name_bindings =
577 self.add_child(name,
578 &module_parent,
579 ForbidDuplicateTypesAndValues,
580 ty_m.span);
581 // NB: not IMPORTABLE
582 method_name_bindings.define_value(def,
583 ty_m.span,
584 PUBLIC);
585
586 (name, static_flag)
587 }
588 ast::TypeTraitItem(ref associated_type) => {
589 let def = DefAssociatedTy(local_def(
590 associated_type.ty_param.id));
591
592 let name_bindings =
593 self.add_child(associated_type.ty_param.ident.name,
594 &module_parent,
595 ForbidDuplicateTypesAndValues,
596 associated_type.ty_param.span);
597 // NB: not IMPORTABLE
598 name_bindings.define_type(def,
599 associated_type.ty_param.span,
600 PUBLIC);
601
602 (associated_type.ty_param.ident.name, TypeTraitItemKind)
603 }
604 };
605
606 self.trait_item_map.insert((name, def_id), kind);
607 }
608
609 name_bindings.define_type(DefTrait(def_id), sp, modifiers);
610 parent.clone()
611 }
612 ItemMac(..) => parent.clone()
613 }
614 }
615
616 // Constructs the reduced graph for one variant. Variants exist in the
617 // type and value namespaces.
618 fn build_reduced_graph_for_variant(&mut self,
619 variant: &Variant,
620 item_id: DefId,
621 parent: &Rc<Module>) {
622 let name = variant.node.name.name;
623 let is_exported = match variant.node.kind {
624 TupleVariantKind(_) => false,
625 StructVariantKind(_) => {
626 // Not adding fields for variants as they are not accessed with a self receiver
627 self.structs.insert(local_def(variant.node.id), Vec::new());
628 true
629 }
630 };
631
632 let child = self.add_child(name, parent,
633 ForbidDuplicateTypesAndValues,
634 variant.span);
635 // variants are always treated as importable to allow them to be glob
636 // used
637 child.define_value(DefVariant(item_id,
638 local_def(variant.node.id), is_exported),
639 variant.span, PUBLIC | IMPORTABLE);
640 child.define_type(DefVariant(item_id,
641 local_def(variant.node.id), is_exported),
642 variant.span, PUBLIC | IMPORTABLE);
643 }
644
645 /// Constructs the reduced graph for one 'view item'. View items consist
646 /// of imports and use directives.
647 fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem, parent: &Rc<Module>) {
648 match view_item.node {
649 ViewItemUse(ref view_path) => {
650 // Extract and intern the module part of the path. For
651 // globs and lists, the path is found directly in the AST;
652 // for simple paths we have to munge the path a little.
653 let module_path = match view_path.node {
654 ViewPathSimple(_, ref full_path, _) => {
655 full_path.segments
656 .init()
657 .iter().map(|ident| ident.identifier.name)
658 .collect()
659 }
660
661 ViewPathGlob(ref module_ident_path, _) |
662 ViewPathList(ref module_ident_path, _, _) => {
663 module_ident_path.segments
664 .iter().map(|ident| ident.identifier.name).collect()
665 }
666 };
667
668 // Build up the import directives.
669 let is_public = view_item.vis == ast::Public;
670 let shadowable =
671 view_item.attrs
672 .iter()
673 .any(|attr| {
674 attr.name() == token::get_name(
675 special_idents::prelude_import.name)
676 });
677 let shadowable = if shadowable {
678 Shadowable::Always
679 } else {
680 Shadowable::Never
681 };
682
683 match view_path.node {
684 ViewPathSimple(binding, ref full_path, id) => {
685 let source_name =
686 full_path.segments.last().unwrap().identifier.name;
687 if token::get_name(source_name).get() == "mod" ||
688 token::get_name(source_name).get() == "self" {
689 self.resolve_error(view_path.span,
690 "`self` imports are only allowed within a { } list");
691 }
692
693 let subclass = SingleImport(binding.name,
694 source_name);
695 self.build_import_directive(&**parent,
696 module_path,
697 subclass,
698 view_path.span,
699 id,
700 is_public,
701 shadowable);
702 }
703 ViewPathList(_, ref source_items, _) => {
704 // Make sure there's at most one `mod` import in the list.
705 let mod_spans = source_items.iter().filter_map(|item| match item.node {
706 PathListMod { .. } => Some(item.span),
707 _ => None
708 }).collect::<Vec<Span>>();
709 if mod_spans.len() > 1 {
710 self.resolve_error(mod_spans[0],
711 "`self` import can only appear once in the list");
712 for other_span in mod_spans.iter().skip(1) {
713 self.session.span_note(*other_span,
714 "another `self` import appears here");
715 }
716 }
717
718 for source_item in source_items.iter() {
719 let (module_path, name) = match source_item.node {
720 PathListIdent { name, .. } =>
721 (module_path.clone(), name.name),
722 PathListMod { .. } => {
723 let name = match module_path.last() {
724 Some(name) => *name,
725 None => {
726 self.resolve_error(source_item.span,
727 "`self` import can only appear in an import list \
728 with a non-empty prefix");
729 continue;
730 }
731 };
732 let module_path = module_path.init();
733 (module_path.to_vec(), name)
734 }
735 };
736 self.build_import_directive(
737 &**parent,
738 module_path,
739 SingleImport(name, name),
740 source_item.span,
741 source_item.node.id(),
742 is_public,
743 shadowable);
744 }
745 }
746 ViewPathGlob(_, id) => {
747 self.build_import_directive(&**parent,
748 module_path,
749 GlobImport,
750 view_path.span,
751 id,
752 is_public,
753 shadowable);
754 }
755 }
756 }
757
758 ViewItemExternCrate(name, _, node_id) => {
759 // n.b. we don't need to look at the path option here, because cstore already did
760 for &crate_id in self.session.cstore
761 .find_extern_mod_stmt_cnum(node_id).iter() {
762 let def_id = DefId { krate: crate_id, node: 0 };
763 self.external_exports.insert(def_id);
764 let parent_link = ModuleParentLink(parent.downgrade(), name.name);
765 let external_module = Rc::new(Module::new(parent_link,
766 Some(def_id),
767 NormalModuleKind,
768 false,
769 true));
770 debug!("(build reduced graph for item) found extern `{}`",
771 self.module_to_string(&*external_module));
772 self.check_for_conflicts_between_external_crates(
773 &**parent,
774 name.name,
775 view_item.span);
776 parent.external_module_children.borrow_mut()
777 .insert(name.name, external_module.clone());
778 self.build_reduced_graph_for_external_crate(&external_module);
779 }
780 }
781 }
782 }
783
784 /// Constructs the reduced graph for one foreign item.
785 fn build_reduced_graph_for_foreign_item<F>(&mut self,
786 foreign_item: &ForeignItem,
787 parent: &Rc<Module>,
788 f: F) where
789 F: FnOnce(&mut Resolver),
790 {
791 let name = foreign_item.ident.name;
792 let is_public = foreign_item.vis == ast::Public;
793 let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
794 let name_bindings =
795 self.add_child(name, parent, ForbidDuplicateValues,
796 foreign_item.span);
797
798 match foreign_item.node {
799 ForeignItemFn(_, ref generics) => {
800 let def = DefFn(local_def(foreign_item.id), false);
801 name_bindings.define_value(def, foreign_item.span, modifiers);
802
803 self.with_type_parameter_rib(
804 HasTypeParameters(generics,
805 FnSpace,
806 foreign_item.id,
807 NormalRibKind),
808 f);
809 }
810 ForeignItemStatic(_, m) => {
811 let def = DefStatic(local_def(foreign_item.id), m);
812 name_bindings.define_value(def, foreign_item.span, modifiers);
813
814 f(self.resolver)
815 }
816 }
817 }
818
819 fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>) -> Rc<Module> {
820 if self.block_needs_anonymous_module(block) {
821 let block_id = block.id;
822
823 debug!("(building reduced graph for block) creating a new \
824 anonymous module for block {}",
825 block_id);
826
827 let new_module = Rc::new(Module::new(
828 BlockParentLink(parent.downgrade(), block_id),
829 None,
830 AnonymousModuleKind,
831 false,
832 false));
833 parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone());
834 new_module
835 } else {
836 parent.clone()
837 }
838 }
839
840 fn handle_external_def(&mut self,
841 def: Def,
842 vis: Visibility,
843 child_name_bindings: &NameBindings,
844 final_ident: &str,
845 name: Name,
846 new_parent: &Rc<Module>) {
847 debug!("(building reduced graph for \
848 external crate) building external def, priv {:?}",
849 vis);
850 let is_public = vis == ast::Public;
851 let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
852 let is_exported = is_public && match new_parent.def_id.get() {
853 None => true,
854 Some(did) => self.external_exports.contains(&did)
855 };
856 if is_exported {
857 self.external_exports.insert(def.def_id());
858 }
859
860 let kind = match def {
861 DefTy(_, true) => EnumModuleKind,
862 DefStruct(..) | DefTy(..) => ImplModuleKind,
863 _ => NormalModuleKind
864 };
865
866 match def {
867 DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) |
868 DefTy(def_id, _) => {
869 let type_def = child_name_bindings.type_def.borrow().clone();
870 match type_def {
871 Some(TypeNsDef { module_def: Some(module_def), .. }) => {
872 debug!("(building reduced graph for external crate) \
873 already created module");
874 module_def.def_id.set(Some(def_id));
875 }
876 Some(_) | None => {
877 debug!("(building reduced graph for \
878 external crate) building module \
879 {}", final_ident);
880 let parent_link = self.get_parent_link(new_parent, name);
881
882 child_name_bindings.define_module(parent_link,
883 Some(def_id),
884 kind,
885 true,
886 is_public,
887 DUMMY_SP);
888 }
889 }
890 }
891 _ => {}
892 }
893
894 match def {
895 DefMod(_) | DefForeignMod(_) => {}
896 DefVariant(_, variant_id, is_struct) => {
897 debug!("(building reduced graph for external crate) building \
898 variant {}",
899 final_ident);
900 // variants are always treated as importable to allow them to be
901 // glob used
902 let modifiers = PUBLIC | IMPORTABLE;
903 if is_struct {
904 child_name_bindings.define_type(def, DUMMY_SP, modifiers);
905 // Not adding fields for variants as they are not accessed with a self receiver
906 self.structs.insert(variant_id, Vec::new());
907 } else {
908 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
909 }
910 }
911 DefFn(ctor_id, true) => {
912 child_name_bindings.define_value(
913 csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
914 .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
915 }
916 DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
917 debug!("(building reduced graph for external \
918 crate) building value (fn/static) {}", final_ident);
919 // impl methods have already been defined with the correct importability modifier
920 let mut modifiers = match *child_name_bindings.value_def.borrow() {
921 Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE),
922 None => modifiers
923 };
924 if new_parent.kind.get() != NormalModuleKind {
925 modifiers = modifiers & !IMPORTABLE;
926 }
927 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
928 }
929 DefTrait(def_id) => {
930 debug!("(building reduced graph for external \
931 crate) building type {}", final_ident);
932
933 // If this is a trait, add all the trait item names to the trait
934 // info.
935
936 let trait_item_def_ids =
937 csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
938 for trait_item_def_id in trait_item_def_ids.iter() {
939 let (trait_item_name, trait_item_kind) =
940 csearch::get_trait_item_name_and_kind(
941 &self.session.cstore,
942 trait_item_def_id.def_id());
943
944 debug!("(building reduced graph for external crate) ... \
945 adding trait item '{}'",
946 token::get_name(trait_item_name));
947
948 self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
949
950 if is_exported {
951 self.external_exports
952 .insert(trait_item_def_id.def_id());
953 }
954 }
955
956 child_name_bindings.define_type(def, DUMMY_SP, modifiers);
957
958 // Define a module if necessary.
959 let parent_link = self.get_parent_link(new_parent, name);
960 child_name_bindings.set_module_kind(parent_link,
961 Some(def_id),
962 TraitModuleKind,
963 true,
964 is_public,
965 DUMMY_SP)
966 }
967 DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
968 debug!("(building reduced graph for external \
969 crate) building type {}", final_ident);
970
971 child_name_bindings.define_type(def, DUMMY_SP, modifiers);
972 }
973 DefStruct(def_id) => {
974 debug!("(building reduced graph for external \
975 crate) building type and value for {}",
976 final_ident);
977 child_name_bindings.define_type(def, DUMMY_SP, modifiers);
978 let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| {
979 f.name
980 }).collect::<Vec<_>>();
981
982 if fields.len() == 0 {
983 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
984 }
985
986 // Record the def ID and fields of this struct.
987 self.structs.insert(def_id, fields);
988 }
989 DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
990 DefUse(..) | DefUpvar(..) | DefRegion(..) |
991 DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
992 panic!("didn't expect `{:?}`", def);
993 }
994 }
995 }
996
997 /// Builds the reduced graph for a single item in an external crate.
998 fn build_reduced_graph_for_external_crate_def(&mut self,
999 root: &Rc<Module>,
1000 def_like: DefLike,
1001 name: Name,
1002 visibility: Visibility) {
1003 match def_like {
1004 DlDef(def) => {
1005 // Add the new child item, if necessary.
1006 match def {
1007 DefForeignMod(def_id) => {
1008 // Foreign modules have no names. Recur and populate
1009 // eagerly.
1010 csearch::each_child_of_item(&self.session.cstore,
1011 def_id,
1012 |def_like,
1013 child_name,
1014 vis| {
1015 self.build_reduced_graph_for_external_crate_def(
1016 root,
1017 def_like,
1018 child_name,
1019 vis)
1020 });
1021 }
1022 _ => {
1023 let child_name_bindings =
1024 self.add_child(name,
1025 root,
1026 OverwriteDuplicates,
1027 DUMMY_SP);
1028
1029 self.handle_external_def(def,
1030 visibility,
1031 &*child_name_bindings,
1032 token::get_name(name).get(),
1033 name,
1034 root);
1035 }
1036 }
1037 }
1038 DlImpl(def) => {
1039 match csearch::get_type_name_if_impl(&self.session.cstore, def) {
1040 None => {}
1041 Some(final_name) => {
1042 let methods_opt =
1043 csearch::get_methods_if_impl(&self.session.cstore, def);
1044 match methods_opt {
1045 Some(ref methods) if
1046 methods.len() >= 1 => {
1047 debug!("(building reduced graph for \
1048 external crate) processing \
1049 static methods for type name {}",
1050 token::get_name(final_name));
1051
1052 let child_name_bindings =
1053 self.add_child(
1054 final_name,
1055 root,
1056 OverwriteDuplicates,
1057 DUMMY_SP);
1058
1059 // Process the static methods. First,
1060 // create the module.
1061 let type_module;
1062 let type_def = child_name_bindings.type_def.borrow().clone();
1063 match type_def {
1064 Some(TypeNsDef {
1065 module_def: Some(module_def),
1066 ..
1067 }) => {
1068 // We already have a module. This
1069 // is OK.
1070 type_module = module_def;
1071
1072 // Mark it as an impl module if
1073 // necessary.
1074 type_module.kind.set(ImplModuleKind);
1075 }
1076 Some(_) | None => {
1077 let parent_link =
1078 self.get_parent_link(root, final_name);
1079 child_name_bindings.define_module(
1080 parent_link,
1081 Some(def),
1082 ImplModuleKind,
1083 true,
1084 true,
1085 DUMMY_SP);
1086 type_module =
1087 child_name_bindings.
1088 get_module();
1089 }
1090 }
1091
1092 // Add each static method to the module.
1093 let new_parent = type_module;
1094 for method_info in methods.iter() {
1095 let name = method_info.name;
1096 debug!("(building reduced graph for \
1097 external crate) creating \
1098 static method '{}'",
1099 token::get_name(name));
1100
1101 let method_name_bindings =
1102 self.add_child(name,
1103 &new_parent,
1104 OverwriteDuplicates,
1105 DUMMY_SP);
1106 let def = DefFn(method_info.def_id, false);
1107
1108 // NB: not IMPORTABLE
1109 let modifiers = if visibility == ast::Public {
1110 PUBLIC
1111 } else {
1112 DefModifiers::empty()
1113 };
1114 method_name_bindings.define_value(
1115 def, DUMMY_SP, modifiers);
1116 }
1117 }
1118
1119 // Otherwise, do nothing.
1120 Some(_) | None => {}
1121 }
1122 }
1123 }
1124 }
1125 DlField => {
1126 debug!("(building reduced graph for external crate) \
1127 ignoring field");
1128 }
1129 }
1130 }
1131
1132 /// Builds the reduced graph rooted at the given external module.
1133 fn populate_external_module(&mut self, module: &Rc<Module>) {
1134 debug!("(populating external module) attempting to populate {}",
1135 self.module_to_string(&**module));
1136
1137 let def_id = match module.def_id.get() {
1138 None => {
1139 debug!("(populating external module) ... no def ID!");
1140 return
1141 }
1142 Some(def_id) => def_id,
1143 };
1144
1145 csearch::each_child_of_item(&self.session.cstore,
1146 def_id,
1147 |def_like, child_name, visibility| {
1148 debug!("(populating external module) ... found ident: {}",
1149 token::get_name(child_name));
1150 self.build_reduced_graph_for_external_crate_def(module,
1151 def_like,
1152 child_name,
1153 visibility)
1154 });
1155 module.populated.set(true)
1156 }
1157
1158 /// Ensures that the reduced graph rooted at the given external module
1159 /// is built, building it if it is not.
1160 fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
1161 if !module.populated.get() {
1162 self.populate_external_module(module)
1163 }
1164 assert!(module.populated.get())
1165 }
1166
1167 /// Builds the reduced graph rooted at the 'use' directive for an external
1168 /// crate.
1169 fn build_reduced_graph_for_external_crate(&mut self, root: &Rc<Module>) {
1170 csearch::each_top_level_item_of_crate(&self.session.cstore,
1171 root.def_id
1172 .get()
1173 .unwrap()
1174 .krate,
1175 |def_like, name, visibility| {
1176 self.build_reduced_graph_for_external_crate_def(root, def_like, name, visibility)
1177 });
1178 }
1179
1180 /// Creates and adds an import directive to the given module.
1181 fn build_import_directive(&mut self,
1182 module_: &Module,
1183 module_path: Vec<Name>,
1184 subclass: ImportDirectiveSubclass,
1185 span: Span,
1186 id: NodeId,
1187 is_public: bool,
1188 shadowable: Shadowable) {
1189 module_.imports.borrow_mut().push(ImportDirective::new(module_path,
1190 subclass,
1191 span,
1192 id,
1193 is_public,
1194 shadowable));
1195 self.unresolved_imports += 1;
1196 // Bump the reference count on the name. Or, if this is a glob, set
1197 // the appropriate flag.
1198
1199 match subclass {
1200 SingleImport(target, _) => {
1201 debug!("(building import directive) building import \
1202 directive: {}::{}",
1203 self.names_to_string(&module_.imports.borrow().last().unwrap().
1204 module_path[]),
1205 token::get_name(target));
1206
1207 let mut import_resolutions = module_.import_resolutions
1208 .borrow_mut();
1209 match import_resolutions.get_mut(&target) {
1210 Some(resolution) => {
1211 debug!("(building import directive) bumping \
1212 reference");
1213 resolution.outstanding_references += 1;
1214
1215 // the source of this name is different now
1216 resolution.type_id = id;
1217 resolution.value_id = id;
1218 resolution.is_public = is_public;
1219 return;
1220 }
1221 None => {}
1222 }
1223 debug!("(building import directive) creating new");
1224 let mut resolution = ImportResolution::new(id, is_public);
1225 resolution.outstanding_references = 1;
1226 import_resolutions.insert(target, resolution);
1227 }
1228 GlobImport => {
1229 // Set the glob flag. This tells us that we don't know the
1230 // module's exports ahead of time.
1231
1232 module_.glob_count.set(module_.glob_count.get() + 1);
1233 }
1234 }
1235 }
1236}
1237
1238struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> {
1239 builder: GraphBuilder<'a, 'b, 'tcx>,
1240 parent: Rc<Module>
1241}
1242
1243impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
1244 fn visit_item(&mut self, item: &Item) {
1245 let p = self.builder.build_reduced_graph_for_item(item, &self.parent);
1246 let old_parent = replace(&mut self.parent, p);
1247 visit::walk_item(self, item);
1248 self.parent = old_parent;
1249 }
1250
1251 fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
1252 let parent = &self.parent;
1253 self.builder.build_reduced_graph_for_foreign_item(foreign_item,
1254 parent,
1255 |r| {
1256 let mut v = BuildReducedGraphVisitor {
1257 builder: GraphBuilder { resolver: r },
1258 parent: parent.clone()
1259 };
1260 visit::walk_foreign_item(&mut v, foreign_item);
1261 })
1262 }
1263
1264 fn visit_view_item(&mut self, view_item: &ViewItem) {
1265 self.builder.build_reduced_graph_for_view_item(view_item, &self.parent);
1266 }
1267
1268 fn visit_block(&mut self, block: &Block) {
1269 let np = self.builder.build_reduced_graph_for_block(block, &self.parent);
1270 let old_parent = replace(&mut self.parent, np);
1271 visit::walk_block(self, block);
1272 self.parent = old_parent;
1273 }
1274}
1275
1276pub fn build_reduced_graph(resolver: &mut Resolver, krate: &ast::Crate) {
1277 GraphBuilder {
1278 resolver: resolver
1279 }.build_reduced_graph(krate);
1280}
1281
1282pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc<Module>) {
1283 GraphBuilder {
1284 resolver: resolver
1285 }.populate_module_if_necessary(module);
1286}