]> git.proxmox.com Git - rustc.git/blob - src/librustc_resolve/build_reduced_graph.rs
New upstream version 1.31.0~beta.19+dfsg1
[rustc.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 macros::{InvocationData, ParentScope, LegacyScope};
17 use resolve_imports::ImportDirective;
18 use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
19 use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
20 use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
21 use Namespace::{self, TypeNS, ValueNS, MacroNS};
22 use {resolve_error, resolve_struct_error, ResolutionError};
23
24 use rustc::hir::def::*;
25 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
26 use rustc::ty;
27 use rustc::middle::cstore::CrateStore;
28 use rustc_metadata::cstore::LoadedMacro;
29
30 use std::cell::Cell;
31 use std::ptr;
32 use rustc_data_structures::sync::Lrc;
33
34 use syntax::ast::{Name, Ident};
35 use syntax::attr;
36
37 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
38 use syntax::ast::{MetaItemKind, Mutability, StmtKind, TraitItem, TraitItemKind, Variant};
39 use syntax::ext::base::{MacroKind, SyntaxExtension};
40 use syntax::ext::base::Determinacy::Undetermined;
41 use syntax::ext::hygiene::Mark;
42 use syntax::ext::tt::macro_rules;
43 use syntax::feature_gate::is_builtin_attr;
44 use syntax::parse::token::{self, Token};
45 use syntax::std_inject::injected_crate_name;
46 use syntax::symbol::keywords;
47 use syntax::visit::{self, Visitor};
48
49 use syntax_pos::{Span, DUMMY_SP};
50
51 impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) {
52 fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
53 arenas.alloc_name_binding(NameBinding {
54 kind: NameBindingKind::Module(self.0),
55 vis: self.1,
56 span: self.2,
57 expansion: self.3,
58 })
59 }
60 }
61
62 impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) {
63 fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
64 arenas.alloc_name_binding(NameBinding {
65 kind: NameBindingKind::Def(self.0, false),
66 vis: self.1,
67 span: self.2,
68 expansion: self.3,
69 })
70 }
71 }
72
73 pub(crate) struct IsMacroExport;
74
75 impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, IsMacroExport) {
76 fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
77 arenas.alloc_name_binding(NameBinding {
78 kind: NameBindingKind::Def(self.0, true),
79 vis: self.1,
80 span: self.2,
81 expansion: self.3,
82 })
83 }
84 }
85
86 impl<'a, 'cl> Resolver<'a, 'cl> {
87 /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
88 /// otherwise, reports an error.
89 pub fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T)
90 where T: ToNameBinding<'a>,
91 {
92 let binding = def.to_name_binding(self.arenas);
93 if let Err(old_binding) = self.try_define(parent, ident, ns, binding) {
94 self.report_conflict(parent, ident, ns, old_binding, &binding);
95 }
96 }
97
98 fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
99 // If any statements are items, we need to create an anonymous module
100 block.stmts.iter().any(|statement| match statement.node {
101 StmtKind::Item(_) | StmtKind::Mac(_) => true,
102 _ => false,
103 })
104 }
105
106 fn insert_field_names(&mut self, def_id: DefId, field_names: Vec<Name>) {
107 if !field_names.is_empty() {
108 self.field_names.insert(def_id, field_names);
109 }
110 }
111
112 fn build_reduced_graph_for_use_tree(
113 &mut self,
114 // This particular use tree
115 use_tree: &ast::UseTree,
116 id: NodeId,
117 parent_prefix: &[Segment],
118 nested: bool,
119 // The whole `use` item
120 parent_scope: ParentScope<'a>,
121 item: &Item,
122 vis: ty::Visibility,
123 root_span: Span,
124 ) {
125 debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, use_tree={:?}, nested={})",
126 parent_prefix, use_tree, nested);
127
128 let mut prefix_iter = parent_prefix.iter().cloned()
129 .chain(use_tree.prefix.segments.iter().map(|seg| seg.into())).peekable();
130
131 // On 2015 edition imports are resolved as crate-relative by default,
132 // so prefixes are prepended with crate root segment if necessary.
133 // The root is prepended lazily, when the first non-empty prefix or terminating glob
134 // appears, so imports in braced groups can have roots prepended independently.
135 // 2015 identifiers used on global 2018 edition enter special "virtual 2015 mode", don't
136 // get crate root prepended, but get special treatment during in-scope resolution instead.
137 let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false };
138 let crate_root = match prefix_iter.peek() {
139 Some(seg) if !seg.ident.is_path_segment_keyword() &&
140 seg.ident.span.rust_2015() && self.session.rust_2015() => {
141 Some(seg.ident.span.ctxt())
142 }
143 None if is_glob && use_tree.span.rust_2015() => {
144 Some(use_tree.span.ctxt())
145 }
146 _ => None,
147 }.map(|ctxt| Segment::from_ident(Ident::new(
148 keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt)
149 )));
150
151 let prefix = crate_root.into_iter().chain(prefix_iter).collect::<Vec<_>>();
152 debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix);
153
154 let empty_for_self = |prefix: &[Segment]| {
155 prefix.is_empty() ||
156 prefix.len() == 1 && prefix[0].ident.name == keywords::CrateRoot.name()
157 };
158 match use_tree.kind {
159 ast::UseTreeKind::Simple(rename, ..) => {
160 let mut ident = use_tree.ident();
161 let mut module_path = prefix;
162 let mut source = module_path.pop().unwrap();
163 let mut type_ns_only = false;
164
165 if nested {
166 // Correctly handle `self`
167 if source.ident.name == keywords::SelfValue.name() {
168 type_ns_only = true;
169
170 if empty_for_self(&module_path) {
171 resolve_error(
172 self,
173 use_tree.span,
174 ResolutionError::
175 SelfImportOnlyInImportListWithNonEmptyPrefix
176 );
177 return;
178 }
179
180 // Replace `use foo::self;` with `use foo;`
181 source = module_path.pop().unwrap();
182 if rename.is_none() {
183 ident = source.ident;
184 }
185 }
186 } else {
187 // Disallow `self`
188 if source.ident.name == keywords::SelfValue.name() {
189 resolve_error(self,
190 use_tree.span,
191 ResolutionError::SelfImportsOnlyAllowedWithin);
192 }
193
194 // Disallow `use $crate;`
195 if source.ident.name == keywords::DollarCrate.name() && module_path.is_empty() {
196 let crate_root = self.resolve_crate_root(source.ident);
197 let crate_name = match crate_root.kind {
198 ModuleKind::Def(_, name) => name,
199 ModuleKind::Block(..) => unreachable!(),
200 };
201 // HACK(eddyb) unclear how good this is, but keeping `$crate`
202 // in `source` breaks `src/test/compile-fail/import-crate-var.rs`,
203 // while the current crate doesn't have a valid `crate_name`.
204 if crate_name != keywords::Invalid.name() {
205 // `crate_name` should not be interpreted as relative.
206 module_path.push(Segment {
207 ident: Ident {
208 name: keywords::CrateRoot.name(),
209 span: source.ident.span,
210 },
211 id: Some(self.session.next_node_id()),
212 });
213 source.ident.name = crate_name;
214 }
215 if rename.is_none() {
216 ident.name = crate_name;
217 }
218
219 self.session.struct_span_warn(item.span, "`$crate` may not be imported")
220 .note("`use $crate;` was erroneously allowed and \
221 will become a hard error in a future release")
222 .emit();
223 }
224 }
225
226 if ident.name == keywords::Crate.name() {
227 self.session.span_err(ident.span,
228 "crate root imports need to be explicitly named: \
229 `use crate as name;`");
230 }
231
232 let subclass = SingleImport {
233 target: ident,
234 source: source.ident,
235 result: PerNS {
236 type_ns: Cell::new(Err(Undetermined)),
237 value_ns: Cell::new(Err(Undetermined)),
238 macro_ns: Cell::new(Err(Undetermined)),
239 },
240 type_ns_only,
241 };
242 self.add_import_directive(
243 module_path,
244 subclass,
245 use_tree.span,
246 id,
247 root_span,
248 item.id,
249 vis,
250 parent_scope,
251 );
252 }
253 ast::UseTreeKind::Glob => {
254 let subclass = GlobImport {
255 is_prelude: attr::contains_name(&item.attrs, "prelude_import"),
256 max_vis: Cell::new(ty::Visibility::Invisible),
257 };
258 self.add_import_directive(
259 prefix,
260 subclass,
261 use_tree.span,
262 id,
263 root_span,
264 item.id,
265 vis,
266 parent_scope,
267 );
268 }
269 ast::UseTreeKind::Nested(ref items) => {
270 // Ensure there is at most one `self` in the list
271 let self_spans = items.iter().filter_map(|&(ref use_tree, _)| {
272 if let ast::UseTreeKind::Simple(..) = use_tree.kind {
273 if use_tree.ident().name == keywords::SelfValue.name() {
274 return Some(use_tree.span);
275 }
276 }
277
278 None
279 }).collect::<Vec<_>>();
280 if self_spans.len() > 1 {
281 let mut e = resolve_struct_error(self,
282 self_spans[0],
283 ResolutionError::SelfImportCanOnlyAppearOnceInTheList);
284
285 for other_span in self_spans.iter().skip(1) {
286 e.span_label(*other_span, "another `self` import appears here");
287 }
288
289 e.emit();
290 }
291
292 for &(ref tree, id) in items {
293 self.build_reduced_graph_for_use_tree(
294 // This particular use tree
295 tree, id, &prefix, true,
296 // The whole `use` item
297 parent_scope.clone(), item, vis, root_span,
298 );
299 }
300
301 // Empty groups `a::b::{}` are turned into synthetic `self` imports
302 // `a::b::c::{self as _}`, so that their prefixes are correctly
303 // resolved and checked for privacy/stability/etc.
304 if items.is_empty() && !empty_for_self(&prefix) {
305 let new_span = prefix[prefix.len() - 1].ident.span;
306 let tree = ast::UseTree {
307 prefix: ast::Path::from_ident(
308 Ident::new(keywords::SelfValue.name(), new_span)
309 ),
310 kind: ast::UseTreeKind::Simple(
311 Some(Ident::new(keywords::Underscore.name().gensymed(), new_span)),
312 ast::DUMMY_NODE_ID,
313 ast::DUMMY_NODE_ID,
314 ),
315 span: use_tree.span,
316 };
317 self.build_reduced_graph_for_use_tree(
318 // This particular use tree
319 &tree, id, &prefix, true,
320 // The whole `use` item
321 parent_scope.clone(), item, ty::Visibility::Invisible, root_span,
322 );
323 }
324 }
325 }
326 }
327
328 /// Constructs the reduced graph for one item.
329 fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScope<'a>) {
330 let parent = parent_scope.module;
331 let expansion = parent_scope.expansion;
332 let ident = item.ident;
333 let sp = item.span;
334 let vis = self.resolve_visibility(&item.vis);
335
336 match item.node {
337 ItemKind::Use(ref use_tree) => {
338 self.build_reduced_graph_for_use_tree(
339 // This particular use tree
340 use_tree, item.id, &[], false,
341 // The whole `use` item
342 parent_scope, item, vis, use_tree.span,
343 );
344 }
345
346 ItemKind::ExternCrate(orig_name) => {
347 let crate_id = self.crate_loader.process_extern_crate(item, &self.definitions);
348 let module =
349 self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
350 self.populate_module_if_necessary(module);
351 if injected_crate_name().map_or(false, |name| ident.name == name) {
352 self.injected_crate = Some(module);
353 }
354
355 let used = self.process_legacy_macro_imports(item, module, &parent_scope);
356 let binding =
357 (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
358 let directive = self.arenas.alloc_import_directive(ImportDirective {
359 root_id: item.id,
360 id: item.id,
361 parent_scope,
362 imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
363 subclass: ImportDirectiveSubclass::ExternCrate {
364 source: orig_name,
365 target: ident,
366 },
367 root_span: item.span,
368 span: item.span,
369 module_path: Vec::new(),
370 vis: Cell::new(vis),
371 used: Cell::new(used),
372 });
373 self.potentially_unused_imports.push(directive);
374 let imported_binding = self.import(binding, directive);
375 if ptr::eq(self.current_module, self.graph_root) {
376 if let Some(entry) = self.extern_prelude.get(&ident.modern()) {
377 if expansion != Mark::root() && orig_name.is_some() &&
378 entry.extern_crate_item.is_none() {
379 self.session.span_err(item.span, "macro-expanded `extern crate` items \
380 cannot shadow names passed with \
381 `--extern`");
382 }
383 }
384 let entry = self.extern_prelude.entry(ident.modern())
385 .or_insert(ExternPreludeEntry {
386 extern_crate_item: None,
387 introduced_by_item: true,
388 });
389 entry.extern_crate_item = Some(imported_binding);
390 if orig_name.is_some() {
391 entry.introduced_by_item = true;
392 }
393 }
394 self.define(parent, ident, TypeNS, imported_binding);
395 }
396
397 ItemKind::GlobalAsm(..) => {}
398
399 ItemKind::Mod(..) if ident == keywords::Invalid.ident() => {} // Crate root
400
401 ItemKind::Mod(..) => {
402 let def_id = self.definitions.local_def_id(item.id);
403 let module_kind = ModuleKind::Def(Def::Mod(def_id), ident.name);
404 let module = self.arenas.alloc_module(ModuleData {
405 no_implicit_prelude: parent.no_implicit_prelude || {
406 attr::contains_name(&item.attrs, "no_implicit_prelude")
407 },
408 ..ModuleData::new(Some(parent), module_kind, def_id, expansion, item.span)
409 });
410 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
411 self.module_map.insert(def_id, module);
412
413 // Descend into the module.
414 self.current_module = module;
415 }
416
417 // Handled in `rustc_metadata::{native_libs,link_args}`
418 ItemKind::ForeignMod(..) => {}
419
420 // These items live in the value namespace.
421 ItemKind::Static(_, m, _) => {
422 let mutbl = m == Mutability::Mutable;
423 let def = Def::Static(self.definitions.local_def_id(item.id), mutbl);
424 self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
425 }
426 ItemKind::Const(..) => {
427 let def = Def::Const(self.definitions.local_def_id(item.id));
428 self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
429 }
430 ItemKind::Fn(..) => {
431 let def = Def::Fn(self.definitions.local_def_id(item.id));
432 self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
433
434 // Functions introducing procedural macros reserve a slot
435 // in the macro namespace as well (see #52225).
436 if attr::contains_name(&item.attrs, "proc_macro") ||
437 attr::contains_name(&item.attrs, "proc_macro_attribute") {
438 let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
439 self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
440 }
441 if let Some(attr) = attr::find_by_name(&item.attrs, "proc_macro_derive") {
442 if let Some(trait_attr) =
443 attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
444 if let Some(ident) = trait_attr.name().map(Ident::with_empty_ctxt) {
445 let sp = trait_attr.span;
446 let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
447 self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
448 }
449 }
450 }
451 }
452
453 // These items live in the type namespace.
454 ItemKind::Ty(..) => {
455 let def = Def::TyAlias(self.definitions.local_def_id(item.id));
456 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
457 }
458
459 ItemKind::Existential(_, _) => {
460 let def = Def::Existential(self.definitions.local_def_id(item.id));
461 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
462 }
463
464 ItemKind::Enum(ref enum_definition, _) => {
465 let def = Def::Enum(self.definitions.local_def_id(item.id));
466 let module_kind = ModuleKind::Def(def, ident.name);
467 let module = self.new_module(parent,
468 module_kind,
469 parent.normal_ancestor_id,
470 expansion,
471 item.span);
472 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
473
474 for variant in &(*enum_definition).variants {
475 self.build_reduced_graph_for_variant(variant, module, vis, expansion);
476 }
477 }
478
479 ItemKind::TraitAlias(..) => {
480 let def = Def::TraitAlias(self.definitions.local_def_id(item.id));
481 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
482 }
483
484 // These items live in both the type and value namespaces.
485 ItemKind::Struct(ref struct_def, _) => {
486 // Define a name in the type namespace.
487 let def_id = self.definitions.local_def_id(item.id);
488 let def = Def::Struct(def_id);
489 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
490
491 let mut ctor_vis = vis;
492
493 let has_non_exhaustive = attr::contains_name(&item.attrs, "non_exhaustive");
494
495 // If the structure is marked as non_exhaustive then lower the visibility
496 // to within the crate.
497 if has_non_exhaustive && vis == ty::Visibility::Public {
498 ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
499 }
500
501 // Record field names for error reporting.
502 let field_names = struct_def.fields().iter().filter_map(|field| {
503 let field_vis = self.resolve_visibility(&field.vis);
504 if ctor_vis.is_at_least(field_vis, &*self) {
505 ctor_vis = field_vis;
506 }
507 field.ident.map(|ident| ident.name)
508 }).collect();
509 let item_def_id = self.definitions.local_def_id(item.id);
510 self.insert_field_names(item_def_id, field_names);
511
512 // If this is a tuple or unit struct, define a name
513 // in the value namespace as well.
514 if !struct_def.is_struct() {
515 let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
516 CtorKind::from_ast(struct_def));
517 self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
518 self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis));
519 }
520 }
521
522 ItemKind::Union(ref vdata, _) => {
523 let def = Def::Union(self.definitions.local_def_id(item.id));
524 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
525
526 // Record field names for error reporting.
527 let field_names = vdata.fields().iter().filter_map(|field| {
528 self.resolve_visibility(&field.vis);
529 field.ident.map(|ident| ident.name)
530 }).collect();
531 let item_def_id = self.definitions.local_def_id(item.id);
532 self.insert_field_names(item_def_id, field_names);
533 }
534
535 ItemKind::Impl(..) => {}
536
537 ItemKind::Trait(..) => {
538 let def_id = self.definitions.local_def_id(item.id);
539
540 // Add all the items within to a new module.
541 let module_kind = ModuleKind::Def(Def::Trait(def_id), ident.name);
542 let module = self.new_module(parent,
543 module_kind,
544 parent.normal_ancestor_id,
545 expansion,
546 item.span);
547 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
548 self.current_module = module;
549 }
550
551 ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
552 }
553 }
554
555 // Constructs the reduced graph for one variant. Variants exist in the
556 // type and value namespaces.
557 fn build_reduced_graph_for_variant(&mut self,
558 variant: &Variant,
559 parent: Module<'a>,
560 vis: ty::Visibility,
561 expansion: Mark) {
562 let ident = variant.node.ident;
563 let def_id = self.definitions.local_def_id(variant.node.data.id());
564
565 // Define a name in the type namespace.
566 let def = Def::Variant(def_id);
567 self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion));
568
569 // Define a constructor name in the value namespace.
570 // Braced variants, unlike structs, generate unusable names in
571 // value namespace, they are reserved for possible future use.
572 let ctor_kind = CtorKind::from_ast(&variant.node.data);
573 let ctor_def = Def::VariantCtor(def_id, ctor_kind);
574
575 self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion));
576 }
577
578 /// Constructs the reduced graph for one foreign item.
579 fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) {
580 let (def, ns) = match item.node {
581 ForeignItemKind::Fn(..) => {
582 (Def::Fn(self.definitions.local_def_id(item.id)), ValueNS)
583 }
584 ForeignItemKind::Static(_, m) => {
585 (Def::Static(self.definitions.local_def_id(item.id), m), ValueNS)
586 }
587 ForeignItemKind::Ty => {
588 (Def::ForeignTy(self.definitions.local_def_id(item.id)), TypeNS)
589 }
590 ForeignItemKind::Macro(_) => unreachable!(),
591 };
592 let parent = self.current_module;
593 let vis = self.resolve_visibility(&item.vis);
594 self.define(parent, item.ident, ns, (def, vis, item.span, expansion));
595 }
596
597 fn build_reduced_graph_for_block(&mut self, block: &Block, expansion: Mark) {
598 let parent = self.current_module;
599 if self.block_needs_anonymous_module(block) {
600 let module = self.new_module(parent,
601 ModuleKind::Block(block.id),
602 parent.normal_ancestor_id,
603 expansion,
604 block.span);
605 self.block_map.insert(block.id, module);
606 self.current_module = module; // Descend into the block.
607 }
608 }
609
610 /// Builds the reduced graph for a single item in an external crate.
611 fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
612 let Export { ident, def, vis, span, .. } = child;
613 let def_id = def.def_id();
614 let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
615 match def {
616 Def::Mod(..) | Def::Enum(..) => {
617 let module = self.new_module(parent,
618 ModuleKind::Def(def, ident.name),
619 def_id,
620 expansion,
621 span);
622 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
623 }
624 Def::Variant(..) | Def::TyAlias(..) | Def::ForeignTy(..) => {
625 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
626 }
627 Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => {
628 self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
629 }
630 Def::StructCtor(..) => {
631 self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
632
633 if let Some(struct_def_id) =
634 self.cstore.def_key(def_id).parent
635 .map(|index| DefId { krate: def_id.krate, index: index }) {
636 self.struct_constructors.insert(struct_def_id, (def, vis));
637 }
638 }
639 Def::Trait(..) => {
640 let module_kind = ModuleKind::Def(def, ident.name);
641 let module = self.new_module(parent,
642 module_kind,
643 parent.normal_ancestor_id,
644 expansion,
645 span);
646 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
647
648 for child in self.cstore.item_children_untracked(def_id, self.session) {
649 let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS };
650 self.define(module, child.ident, ns,
651 (child.def, ty::Visibility::Public, DUMMY_SP, expansion));
652
653 if self.cstore.associated_item_cloned_untracked(child.def.def_id())
654 .method_has_self_argument {
655 self.has_self.insert(child.def.def_id());
656 }
657 }
658 module.populated.set(true);
659 }
660 Def::Struct(..) | Def::Union(..) => {
661 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
662
663 // Record field names for error reporting.
664 let field_names = self.cstore.struct_field_names_untracked(def_id);
665 self.insert_field_names(def_id, field_names);
666 }
667 Def::Macro(..) => {
668 self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, expansion));
669 }
670 _ => bug!("unexpected definition: {:?}", def)
671 }
672 }
673
674 pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
675 if def_id.krate == LOCAL_CRATE {
676 return self.module_map[&def_id]
677 }
678
679 let macros_only = self.cstore.dep_kind_untracked(def_id.krate).macros_only();
680 if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) {
681 return module;
682 }
683
684 let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
685 (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None)
686 } else {
687 let def_key = self.cstore.def_key(def_id);
688 (def_key.disambiguated_data.data.get_opt_name().unwrap(),
689 Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
690 };
691
692 let kind = ModuleKind::Def(Def::Mod(def_id), name.as_symbol());
693 let module =
694 self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP));
695 self.extern_module_map.insert((def_id, macros_only), module);
696 module
697 }
698
699 pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
700 let def_id = self.macro_defs[&expansion];
701 if let Some(id) = self.definitions.as_local_node_id(def_id) {
702 self.local_macro_def_scopes[&id]
703 } else if def_id.krate == CrateNum::BuiltinMacros {
704 self.injected_crate.unwrap_or(self.graph_root)
705 } else {
706 let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
707 self.get_module(module_def_id)
708 }
709 }
710
711 pub fn get_macro(&mut self, def: Def) -> Lrc<SyntaxExtension> {
712 let def_id = match def {
713 Def::Macro(def_id, ..) => def_id,
714 Def::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::NonMacroAttr {
715 mark_used: attr_kind == NonMacroAttrKind::Tool,
716 }),
717 _ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"),
718 };
719 if let Some(ext) = self.macro_map.get(&def_id) {
720 return ext.clone();
721 }
722
723 let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
724 LoadedMacro::MacroDef(macro_def) => macro_def,
725 LoadedMacro::ProcMacro(ext) => return ext,
726 };
727
728 let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
729 &self.session.features_untracked(),
730 &macro_def,
731 self.cstore.crate_edition_untracked(def_id.krate)));
732 self.macro_map.insert(def_id, ext.clone());
733 ext
734 }
735
736 /// Ensures that the reduced graph rooted at the given external module
737 /// is built, building it if it is not.
738 pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
739 if module.populated.get() { return }
740 let def_id = module.def_id().unwrap();
741 for child in self.cstore.item_children_untracked(def_id, self.session) {
742 self.build_reduced_graph_for_external_crate_def(module, child);
743 }
744 module.populated.set(true)
745 }
746
747 fn legacy_import_macro(&mut self,
748 name: Name,
749 binding: &'a NameBinding<'a>,
750 span: Span,
751 allow_shadowing: bool) {
752 if self.macro_use_prelude.insert(name, binding).is_some() && !allow_shadowing {
753 let msg = format!("`{}` is already in scope", name);
754 let note =
755 "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
756 self.session.struct_span_err(span, &msg).note(note).emit();
757 }
758 }
759
760 // This returns true if we should consider the underlying `extern crate` to be used.
761 fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>,
762 parent_scope: &ParentScope<'a>) -> bool {
763 let mut import_all = None;
764 let mut single_imports = Vec::new();
765 for attr in &item.attrs {
766 if attr.check_name("macro_use") {
767 if self.current_module.parent.is_some() {
768 span_err!(self.session, item.span, E0468,
769 "an `extern crate` loading macros must be at the crate root");
770 }
771 let ill_formed = |span| span_err!(self.session, span, E0466, "bad macro import");
772 match attr.meta() {
773 Some(meta) => match meta.node {
774 MetaItemKind::Word => {
775 import_all = Some(meta.span);
776 break;
777 }
778 MetaItemKind::List(nested_metas) => for nested_meta in nested_metas {
779 match nested_meta.word() {
780 Some(word) => single_imports.push((word.name(), word.span)),
781 None => ill_formed(nested_meta.span),
782 }
783 }
784 MetaItemKind::NameValue(..) => ill_formed(meta.span),
785 }
786 None => ill_formed(attr.span()),
787 }
788 }
789 }
790
791 let arenas = self.arenas;
792 let macro_use_directive = |span| arenas.alloc_import_directive(ImportDirective {
793 root_id: item.id,
794 id: item.id,
795 parent_scope: parent_scope.clone(),
796 imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
797 subclass: ImportDirectiveSubclass::MacroUse,
798 root_span: span,
799 span,
800 module_path: Vec::new(),
801 vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))),
802 used: Cell::new(false),
803 });
804
805 let allow_shadowing = parent_scope.expansion == Mark::root();
806 if let Some(span) = import_all {
807 let directive = macro_use_directive(span);
808 self.potentially_unused_imports.push(directive);
809 module.for_each_child(|ident, ns, binding| if ns == MacroNS {
810 let imported_binding = self.import(binding, directive);
811 self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
812 });
813 } else {
814 for (name, span) in single_imports.iter().cloned() {
815 let ident = Ident::with_empty_ctxt(name);
816 let result = self.resolve_ident_in_module(
817 ModuleOrUniformRoot::Module(module),
818 ident,
819 MacroNS,
820 None,
821 false,
822 span,
823 );
824 if let Ok(binding) = result {
825 let directive = macro_use_directive(span);
826 self.potentially_unused_imports.push(directive);
827 let imported_binding = self.import(binding, directive);
828 self.legacy_import_macro(name, imported_binding, span, allow_shadowing);
829 } else {
830 span_err!(self.session, span, E0469, "imported macro not found");
831 }
832 }
833 }
834 import_all.is_some() || !single_imports.is_empty()
835 }
836
837 // does this attribute list contain "macro_use"?
838 fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
839 for attr in attrs {
840 if attr.check_name("macro_escape") {
841 let msg = "macro_escape is a deprecated synonym for macro_use";
842 let mut err = self.session.struct_span_warn(attr.span, msg);
843 if let ast::AttrStyle::Inner = attr.style {
844 err.help("consider an outer attribute, #[macro_use] mod ...").emit();
845 } else {
846 err.emit();
847 }
848 } else if !attr.check_name("macro_use") {
849 continue;
850 }
851
852 if !attr.is_word() {
853 self.session.span_err(attr.span, "arguments to macro_use are not allowed here");
854 }
855 return true;
856 }
857
858 false
859 }
860 }
861
862 pub struct BuildReducedGraphVisitor<'a, 'b: 'a, 'c: 'b> {
863 pub resolver: &'a mut Resolver<'b, 'c>,
864 pub current_legacy_scope: LegacyScope<'b>,
865 pub expansion: Mark,
866 }
867
868 impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> {
869 fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
870 let mark = id.placeholder_to_mark();
871 self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark);
872 let invocation = self.resolver.invocations[&mark];
873 invocation.module.set(self.resolver.current_module);
874 invocation.parent_legacy_scope.set(self.current_legacy_scope);
875 invocation
876 }
877 }
878
879 macro_rules! method {
880 ($visit:ident: $ty:ty, $invoc:path, $walk:ident) => {
881 fn $visit(&mut self, node: &'a $ty) {
882 if let $invoc(..) = node.node {
883 self.visit_invoc(node.id);
884 } else {
885 visit::$walk(self, node);
886 }
887 }
888 }
889 }
890
891 impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
892 method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item);
893 method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr);
894 method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat);
895 method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty);
896
897 fn visit_item(&mut self, item: &'a Item) {
898 let macro_use = match item.node {
899 ItemKind::MacroDef(..) => {
900 self.resolver.define_macro(item, self.expansion, &mut self.current_legacy_scope);
901 return
902 }
903 ItemKind::Mac(..) => {
904 self.current_legacy_scope = LegacyScope::Invocation(self.visit_invoc(item.id));
905 return
906 }
907 ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs),
908 _ => false,
909 };
910
911 let orig_current_module = self.resolver.current_module;
912 let orig_current_legacy_scope = self.current_legacy_scope;
913 let parent_scope = ParentScope {
914 module: self.resolver.current_module,
915 expansion: self.expansion,
916 legacy: self.current_legacy_scope,
917 derives: Vec::new(),
918 };
919 self.resolver.build_reduced_graph_for_item(item, parent_scope);
920 visit::walk_item(self, item);
921 self.resolver.current_module = orig_current_module;
922 if !macro_use {
923 self.current_legacy_scope = orig_current_legacy_scope;
924 }
925 }
926
927 fn visit_stmt(&mut self, stmt: &'a ast::Stmt) {
928 if let ast::StmtKind::Mac(..) = stmt.node {
929 self.current_legacy_scope = LegacyScope::Invocation(self.visit_invoc(stmt.id));
930 } else {
931 visit::walk_stmt(self, stmt);
932 }
933 }
934
935 fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
936 if let ForeignItemKind::Macro(_) = foreign_item.node {
937 self.visit_invoc(foreign_item.id);
938 return;
939 }
940
941 self.resolver.build_reduced_graph_for_foreign_item(foreign_item, self.expansion);
942 visit::walk_foreign_item(self, foreign_item);
943 }
944
945 fn visit_block(&mut self, block: &'a Block) {
946 let orig_current_module = self.resolver.current_module;
947 let orig_current_legacy_scope = self.current_legacy_scope;
948 self.resolver.build_reduced_graph_for_block(block, self.expansion);
949 visit::walk_block(self, block);
950 self.resolver.current_module = orig_current_module;
951 self.current_legacy_scope = orig_current_legacy_scope;
952 }
953
954 fn visit_trait_item(&mut self, item: &'a TraitItem) {
955 let parent = self.resolver.current_module;
956
957 if let TraitItemKind::Macro(_) = item.node {
958 self.visit_invoc(item.id);
959 return
960 }
961
962 // Add the item to the trait info.
963 let item_def_id = self.resolver.definitions.local_def_id(item.id);
964 let (def, ns) = match item.node {
965 TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS),
966 TraitItemKind::Method(ref sig, _) => {
967 if sig.decl.has_self() {
968 self.resolver.has_self.insert(item_def_id);
969 }
970 (Def::Method(item_def_id), ValueNS)
971 }
972 TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS),
973 TraitItemKind::Macro(_) => bug!(), // handled above
974 };
975
976 let vis = ty::Visibility::Public;
977 self.resolver.define(parent, item.ident, ns, (def, vis, item.span, self.expansion));
978
979 self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor
980 visit::walk_trait_item(self, item);
981 self.resolver.current_module = parent;
982 }
983
984 fn visit_token(&mut self, t: Token) {
985 if let Token::Interpolated(nt) = t {
986 if let token::NtExpr(ref expr) = nt.0 {
987 if let ast::ExprKind::Mac(..) = expr.node {
988 self.visit_invoc(expr.id);
989 }
990 }
991 }
992 }
993
994 fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
995 if !attr.is_sugared_doc && is_builtin_attr(attr) {
996 let parent_scope = ParentScope {
997 module: self.resolver.current_module.nearest_item_scope(),
998 expansion: self.expansion,
999 legacy: self.current_legacy_scope,
1000 // Let's hope discerning built-in attributes from derive helpers is not necessary
1001 derives: Vec::new(),
1002 };
1003 parent_scope.module.builtin_attrs.borrow_mut().push((
1004 attr.path.segments[0].ident, parent_scope
1005 ));
1006 }
1007 visit::walk_attribute(self, attr);
1008 }
1009 }