]>
Commit | Line | Data |
---|---|---|
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 | ||
16 | use {DefModifiers, PUBLIC, IMPORTABLE}; | |
17 | use ImportDirective; | |
18 | use ImportDirectiveSubclass::{self, SingleImport, GlobImport}; | |
19 | use ImportResolution; | |
20 | use Module; | |
21 | use ModuleKind::*; | |
22 | use Namespace::{TypeNS, ValueNS}; | |
23 | use NameBindings; | |
24 | use ParentLink::{self, ModuleParentLink, BlockParentLink}; | |
25 | use Resolver; | |
26 | use RibKind::*; | |
27 | use Shadowable; | |
28 | use TypeNsDef; | |
29 | use TypeParameters::HasTypeParameters; | |
30 | ||
31 | use self::DuplicateCheckingMode::*; | |
32 | use self::NamespaceError::*; | |
33 | ||
34 | use rustc::metadata::csearch; | |
35 | use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl}; | |
36 | use rustc::middle::def::*; | |
37 | use rustc::middle::subst::FnSpace; | |
38 | ||
39 | use syntax::ast::{Block, Crate}; | |
40 | use syntax::ast::{DeclItem, DefId}; | |
41 | use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic}; | |
42 | use syntax::ast::{Item, ItemConst, ItemEnum, ItemFn}; | |
43 | use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic}; | |
44 | use syntax::ast::{ItemStruct, ItemTrait, ItemTy}; | |
45 | use syntax::ast::{MethodImplItem, Name, NamedField, NodeId}; | |
46 | use syntax::ast::{PathListIdent, PathListMod}; | |
47 | use syntax::ast::{Public, SelfStatic}; | |
48 | use syntax::ast::StmtDecl; | |
49 | use syntax::ast::StructVariantKind; | |
50 | use syntax::ast::TupleVariantKind; | |
51 | use syntax::ast::TyObjectSum; | |
52 | use syntax::ast::{TypeImplItem, UnnamedField}; | |
53 | use syntax::ast::{Variant, ViewItem, ViewItemExternCrate}; | |
54 | use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple}; | |
55 | use syntax::ast::{Visibility}; | |
56 | use syntax::ast::TyPath; | |
57 | use syntax::ast; | |
58 | use syntax::ast_util::{self, PostExpansionMethod, local_def}; | |
59 | use syntax::attr::AttrMetaMethods; | |
60 | use syntax::parse::token::{self, special_idents}; | |
61 | use syntax::codemap::{Span, DUMMY_SP}; | |
62 | use syntax::visit::{self, Visitor}; | |
63 | ||
64 | use std::mem::replace; | |
65 | use std::ops::{Deref, DerefMut}; | |
66 | use 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)] | |
71 | enum DuplicateCheckingMode { | |
72 | ForbidDuplicateModules, | |
73 | ForbidDuplicateTypesAndModules, | |
74 | ForbidDuplicateValues, | |
75 | ForbidDuplicateTypesAndValues, | |
76 | OverwriteDuplicates | |
77 | } | |
78 | ||
79 | #[derive(Copy, PartialEq)] | |
80 | enum NamespaceError { | |
81 | NoError, | |
82 | ModuleError, | |
83 | TypeError, | |
84 | ValueError | |
85 | } | |
86 | ||
87 | fn 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 | ||
95 | struct GraphBuilder<'a, 'b:'a, 'tcx:'b> { | |
96 | resolver: &'a mut Resolver<'b, 'tcx> | |
97 | } | |
98 | ||
99 | impl<'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 | ||
107 | impl<'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 | ||
113 | impl<'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 | ||
1238 | struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> { | |
1239 | builder: GraphBuilder<'a, 'b, 'tcx>, | |
1240 | parent: Rc<Module> | |
1241 | } | |
1242 | ||
1243 | impl<'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 | ||
1276 | pub fn build_reduced_graph(resolver: &mut Resolver, krate: &ast::Crate) { | |
1277 | GraphBuilder { | |
1278 | resolver: resolver | |
1279 | }.build_reduced_graph(krate); | |
1280 | } | |
1281 | ||
1282 | pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc<Module>) { | |
1283 | GraphBuilder { | |
1284 | resolver: resolver | |
1285 | }.populate_module_if_necessary(module); | |
1286 | } |