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.
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.
11 //! Reduced graph building
13 //! Here we build the "reduced graph": the graph of the module tree without
14 //! any imports resolved.
16 use macros
::{InvocationData, LegacyScope}
;
17 use resolve_imports
::ImportDirective
;
18 use resolve_imports
::ImportDirectiveSubclass
::{self, GlobImport, SingleImport}
;
19 use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}
;
20 use {Resolver, ResolverArenas}
;
21 use Namespace
::{self, TypeNS, ValueNS, MacroNS}
;
22 use {resolve_error, resolve_struct_error, ResolutionError}
;
24 use rustc
::middle
::cstore
::LoadedMacro
;
25 use rustc
::hir
::def
::*;
26 use rustc
::hir
::def_id
::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}
;
32 use syntax
::ast
::{Name, Ident}
;
35 use syntax
::ast
::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}
;
36 use syntax
::ast
::{Mutability, StmtKind, TraitItem, TraitItemKind}
;
37 use syntax
::ast
::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}
;
38 use syntax
::ext
::base
::SyntaxExtension
;
39 use syntax
::ext
::base
::Determinacy
::Undetermined
;
40 use syntax
::ext
::hygiene
::Mark
;
41 use syntax
::ext
::tt
::macro_rules
;
42 use syntax
::parse
::token
;
43 use syntax
::symbol
::keywords
;
44 use syntax
::visit
::{self, Visitor}
;
46 use syntax_pos
::{Span, DUMMY_SP}
;
48 impl<'a
> ToNameBinding
<'a
> for (Module
<'a
>, ty
::Visibility
, Span
, Mark
) {
49 fn to_name_binding(self, arenas
: &'a ResolverArenas
<'a
>) -> &'a NameBinding
<'a
> {
50 arenas
.alloc_name_binding(NameBinding
{
51 kind
: NameBindingKind
::Module(self.0),
59 impl<'a
> ToNameBinding
<'a
> for (Def
, ty
::Visibility
, Span
, Mark
) {
60 fn to_name_binding(self, arenas
: &'a ResolverArenas
<'a
>) -> &'a NameBinding
<'a
> {
61 arenas
.alloc_name_binding(NameBinding
{
62 kind
: NameBindingKind
::Def(self.0),
70 #[derive(Default, PartialEq, Eq)]
71 struct LegacyMacroImports
{
72 import_all
: Option
<Span
>,
73 imports
: Vec
<(Name
, Span
)>,
74 reexports
: Vec
<(Name
, Span
)>,
77 impl<'a
> Resolver
<'a
> {
78 /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
79 /// otherwise, reports an error.
80 pub fn define
<T
>(&mut self, parent
: Module
<'a
>, ident
: Ident
, ns
: Namespace
, def
: T
)
81 where T
: ToNameBinding
<'a
>,
83 let binding
= def
.to_name_binding(self.arenas
);
84 if let Err(old_binding
) = self.try_define(parent
, ident
, ns
, binding
) {
85 self.report_conflict(parent
, ident
, ns
, old_binding
, &binding
);
89 fn block_needs_anonymous_module(&mut self, block
: &Block
) -> bool
{
90 // If any statements are items, we need to create an anonymous module
91 block
.stmts
.iter().any(|statement
| match statement
.node
{
92 StmtKind
::Item(_
) | StmtKind
::Mac(_
) => true,
97 fn insert_field_names(&mut self, def_id
: DefId
, field_names
: Vec
<Name
>) {
98 if !field_names
.is_empty() {
99 self.field_names
.insert(def_id
, field_names
);
103 /// Constructs the reduced graph for one item.
104 fn build_reduced_graph_for_item(&mut self, item
: &Item
, expansion
: Mark
) {
105 let parent
= self.current_module
;
106 let ident
= item
.ident
;
108 let vis
= self.resolve_visibility(&item
.vis
);
111 ItemKind
::Use(ref view_path
) => {
112 // Extract and intern the module part of the path. For
113 // globs and lists, the path is found directly in the AST;
114 // for simple paths we have to munge the path a little.
115 let mut module_path
: Vec
<_
> = match view_path
.node
{
116 ViewPathSimple(_
, ref full_path
) => {
122 .map(|seg
| seg
.identifier
)
126 ViewPathGlob(ref module_ident_path
) |
127 ViewPathList(ref module_ident_path
, _
) => {
128 module_ident_path
.segments
130 .map(|seg
| seg
.identifier
)
135 // This can be removed once warning cycle #36888 is complete.
136 if module_path
.len() >= 2 && module_path
[0].name
== keywords
::CrateRoot
.name() &&
137 token
::Ident(module_path
[1]).is_path_segment_keyword() {
138 module_path
.remove(0);
141 // Build up the import directives.
142 let is_prelude
= attr
::contains_name(&item
.attrs
, "prelude_import");
144 match view_path
.node
{
145 ViewPathSimple(mut binding
, ref full_path
) => {
146 let mut source
= full_path
.segments
.last().unwrap().identifier
;
147 let source_name
= source
.name
;
148 if source_name
== "mod" || source_name
== "self" {
151 ResolutionError
::SelfImportsOnlyAllowedWithin
);
152 } else if source_name
== keywords
::DollarCrate
.name() &&
153 full_path
.segments
.len() == 1 {
154 let crate_root
= self.resolve_crate_root(source
.ctxt
);
155 let crate_name
= match crate_root
.kind
{
156 ModuleKind
::Def(_
, name
) => name
,
157 ModuleKind
::Block(..) => unreachable
!(),
159 source
.name
= crate_name
;
160 if binding
.name
== keywords
::DollarCrate
.name() {
161 binding
.name
= crate_name
;
164 self.session
.struct_span_warn(item
.span
, "`$crate` may not be imported")
165 .note("`use $crate;` was erroneously allowed and \
166 will become a hard error in a future release")
170 let subclass
= SingleImport
{
173 result
: self.per_ns(|_
, _
| Cell
::new(Err(Undetermined
))),
176 self.add_import_directive(
177 module_path
, subclass
, view_path
.span
, item
.id
, vis
, expansion
,
180 ViewPathList(_
, ref source_items
) => {
181 // Make sure there's at most one `mod` import in the list.
182 let mod_spans
= source_items
.iter().filter_map(|item
| {
183 if item
.node
.name
.name
== keywords
::SelfValue
.name() {
188 }).collect
::<Vec
<Span
>>();
190 if mod_spans
.len() > 1 {
191 let mut e
= resolve_struct_error(self,
193 ResolutionError
::SelfImportCanOnlyAppearOnceInTheList
);
194 for other_span
in mod_spans
.iter().skip(1) {
195 e
.span_note(*other_span
, "another `self` import appears here");
200 for source_item
in source_items
{
201 let node
= source_item
.node
;
202 let (module_path
, ident
, rename
, type_ns_only
) = {
203 if node
.name
.name
!= keywords
::SelfValue
.name() {
204 let rename
= node
.rename
.unwrap_or(node
.name
);
205 (module_path
.clone(), node
.name
, rename
, false)
207 let ident
= *module_path
.last().unwrap();
208 if ident
.name
== keywords
::CrateRoot
.name() {
213 SelfImportOnlyInImportListWithNonEmptyPrefix
217 let module_path
= module_path
.split_last().unwrap().1;
218 let rename
= node
.rename
.unwrap_or(ident
);
219 (module_path
.to_vec(), ident
, rename
, true)
222 let subclass
= SingleImport
{
225 result
: self.per_ns(|_
, _
| Cell
::new(Err(Undetermined
))),
226 type_ns_only
: type_ns_only
,
228 let id
= source_item
.node
.id
;
229 self.add_import_directive(
230 module_path
, subclass
, source_item
.span
, id
, vis
, expansion
,
235 let subclass
= GlobImport
{
236 is_prelude
: is_prelude
,
237 max_vis
: Cell
::new(ty
::Visibility
::Invisible
),
239 self.add_import_directive(
240 module_path
, subclass
, view_path
.span
, item
.id
, vis
, expansion
,
246 ItemKind
::ExternCrate(_
) => {
247 self.crate_loader
.process_item(item
, &self.definitions
);
249 // n.b. we don't need to look at the path option here, because cstore already did
250 let crate_id
= self.session
.cstore
.extern_mod_stmt_cnum(item
.id
).unwrap();
252 self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }
);
253 self.populate_module_if_necessary(module
);
254 let used
= self.process_legacy_macro_imports(item
, module
, expansion
);
256 (module
, ty
::Visibility
::Public
, sp
, expansion
).to_name_binding(self.arenas
);
257 let directive
= self.arenas
.alloc_import_directive(ImportDirective
{
260 imported_module
: Cell
::new(Some(module
)),
261 subclass
: ImportDirectiveSubclass
::ExternCrate
,
263 module_path
: Vec
::new(),
265 expansion
: expansion
,
266 used
: Cell
::new(used
),
268 self.potentially_unused_imports
.push(directive
);
269 let imported_binding
= self.import(binding
, directive
);
270 self.define(parent
, ident
, TypeNS
, imported_binding
);
273 ItemKind
::GlobalAsm(..) => {}
275 ItemKind
::Mod(..) if item
.ident
== keywords
::Invalid
.ident() => {}
// Crate root
277 ItemKind
::Mod(..) => {
278 let def_id
= self.definitions
.local_def_id(item
.id
);
279 let module_kind
= ModuleKind
::Def(Def
::Mod(def_id
), ident
.name
);
280 let module
= self.arenas
.alloc_module(ModuleData
{
281 no_implicit_prelude
: parent
.no_implicit_prelude
|| {
282 attr
::contains_name(&item
.attrs
, "no_implicit_prelude")
284 ..ModuleData
::new(Some(parent
), module_kind
, def_id
, expansion
, item
.span
)
286 self.define(parent
, ident
, TypeNS
, (module
, vis
, sp
, expansion
));
287 self.module_map
.insert(def_id
, module
);
289 // Descend into the module.
290 self.current_module
= module
;
293 ItemKind
::ForeignMod(..) => self.crate_loader
.process_item(item
, &self.definitions
),
295 // These items live in the value namespace.
296 ItemKind
::Static(_
, m
, _
) => {
297 let mutbl
= m
== Mutability
::Mutable
;
298 let def
= Def
::Static(self.definitions
.local_def_id(item
.id
), mutbl
);
299 self.define(parent
, ident
, ValueNS
, (def
, vis
, sp
, expansion
));
301 ItemKind
::Const(..) => {
302 let def
= Def
::Const(self.definitions
.local_def_id(item
.id
));
303 self.define(parent
, ident
, ValueNS
, (def
, vis
, sp
, expansion
));
305 ItemKind
::Fn(..) => {
306 let def
= Def
::Fn(self.definitions
.local_def_id(item
.id
));
307 self.define(parent
, ident
, ValueNS
, (def
, vis
, sp
, expansion
));
310 // These items live in the type namespace.
311 ItemKind
::Ty(..) => {
312 let def
= Def
::TyAlias(self.definitions
.local_def_id(item
.id
));
313 self.define(parent
, ident
, TypeNS
, (def
, vis
, sp
, expansion
));
316 ItemKind
::Enum(ref enum_definition
, _
) => {
317 let def
= Def
::Enum(self.definitions
.local_def_id(item
.id
));
318 let module_kind
= ModuleKind
::Def(def
, ident
.name
);
319 let module
= self.new_module(parent
,
321 parent
.normal_ancestor_id
,
324 self.define(parent
, ident
, TypeNS
, (module
, vis
, sp
, expansion
));
326 for variant
in &(*enum_definition
).variants
{
327 self.build_reduced_graph_for_variant(variant
, module
, vis
, expansion
);
331 // These items live in both the type and value namespaces.
332 ItemKind
::Struct(ref struct_def
, _
) => {
333 // Define a name in the type namespace.
334 let def
= Def
::Struct(self.definitions
.local_def_id(item
.id
));
335 self.define(parent
, ident
, TypeNS
, (def
, vis
, sp
, expansion
));
337 // Record field names for error reporting.
338 let mut ctor_vis
= vis
;
339 let field_names
= struct_def
.fields().iter().filter_map(|field
| {
340 let field_vis
= self.resolve_visibility(&field
.vis
);
341 if ctor_vis
.is_at_least(field_vis
, &*self) {
342 ctor_vis
= field_vis
;
344 field
.ident
.map(|ident
| ident
.name
)
346 let item_def_id
= self.definitions
.local_def_id(item
.id
);
347 self.insert_field_names(item_def_id
, field_names
);
349 // If this is a tuple or unit struct, define a name
350 // in the value namespace as well.
351 if !struct_def
.is_struct() {
352 let ctor_def
= Def
::StructCtor(self.definitions
.local_def_id(struct_def
.id()),
353 CtorKind
::from_ast(struct_def
));
354 self.define(parent
, ident
, ValueNS
, (ctor_def
, ctor_vis
, sp
, expansion
));
355 self.struct_constructors
.insert(def
.def_id(), (ctor_def
, ctor_vis
));
359 ItemKind
::Union(ref vdata
, _
) => {
360 let def
= Def
::Union(self.definitions
.local_def_id(item
.id
));
361 self.define(parent
, ident
, TypeNS
, (def
, vis
, sp
, expansion
));
363 // Record field names for error reporting.
364 let field_names
= vdata
.fields().iter().filter_map(|field
| {
365 self.resolve_visibility(&field
.vis
);
366 field
.ident
.map(|ident
| ident
.name
)
368 let item_def_id
= self.definitions
.local_def_id(item
.id
);
369 self.insert_field_names(item_def_id
, field_names
);
372 ItemKind
::DefaultImpl(..) | ItemKind
::Impl(..) => {}
374 ItemKind
::Trait(..) => {
375 let def_id
= self.definitions
.local_def_id(item
.id
);
377 // Add all the items within to a new module.
378 let module_kind
= ModuleKind
::Def(Def
::Trait(def_id
), ident
.name
);
379 let module
= self.new_module(parent
,
381 parent
.normal_ancestor_id
,
384 self.define(parent
, ident
, TypeNS
, (module
, vis
, sp
, expansion
));
385 self.current_module
= module
;
387 ItemKind
::MacroDef(..) | ItemKind
::Mac(_
) => unreachable
!(),
391 // Constructs the reduced graph for one variant. Variants exist in the
392 // type and value namespaces.
393 fn build_reduced_graph_for_variant(&mut self,
398 let ident
= variant
.node
.name
;
399 let def_id
= self.definitions
.local_def_id(variant
.node
.data
.id());
401 // Define a name in the type namespace.
402 let def
= Def
::Variant(def_id
);
403 self.define(parent
, ident
, TypeNS
, (def
, vis
, variant
.span
, expansion
));
405 // Define a constructor name in the value namespace.
406 // Braced variants, unlike structs, generate unusable names in
407 // value namespace, they are reserved for possible future use.
408 let ctor_kind
= CtorKind
::from_ast(&variant
.node
.data
);
409 let ctor_def
= Def
::VariantCtor(def_id
, ctor_kind
);
410 self.define(parent
, ident
, ValueNS
, (ctor_def
, vis
, variant
.span
, expansion
));
413 /// Constructs the reduced graph for one foreign item.
414 fn build_reduced_graph_for_foreign_item(&mut self, item
: &ForeignItem
, expansion
: Mark
) {
415 let def
= match item
.node
{
416 ForeignItemKind
::Fn(..) => {
417 Def
::Fn(self.definitions
.local_def_id(item
.id
))
419 ForeignItemKind
::Static(_
, m
) => {
420 Def
::Static(self.definitions
.local_def_id(item
.id
), m
)
423 let parent
= self.current_module
;
424 let vis
= self.resolve_visibility(&item
.vis
);
425 self.define(parent
, item
.ident
, ValueNS
, (def
, vis
, item
.span
, expansion
));
428 fn build_reduced_graph_for_block(&mut self, block
: &Block
, expansion
: Mark
) {
429 let parent
= self.current_module
;
430 if self.block_needs_anonymous_module(block
) {
431 let module
= self.new_module(parent
,
432 ModuleKind
::Block(block
.id
),
433 parent
.normal_ancestor_id
,
436 self.block_map
.insert(block
.id
, module
);
437 self.current_module
= module
; // Descend into the block.
441 /// Builds the reduced graph for a single item in an external crate.
442 fn build_reduced_graph_for_external_crate_def(&mut self, parent
: Module
<'a
>, child
: Export
) {
443 let ident
= child
.ident
;
445 let def_id
= def
.def_id();
446 let vis
= self.session
.cstore
.visibility(def_id
);
447 let span
= child
.span
;
448 let expansion
= Mark
::root(); // FIXME(jseyfried) intercrate hygiene
450 Def
::Mod(..) | Def
::Enum(..) => {
451 let module
= self.new_module(parent
,
452 ModuleKind
::Def(def
, ident
.name
),
456 self.define(parent
, ident
, TypeNS
, (module
, vis
, DUMMY_SP
, expansion
));
458 Def
::Variant(..) | Def
::TyAlias(..) => {
459 self.define(parent
, ident
, TypeNS
, (def
, vis
, DUMMY_SP
, expansion
));
461 Def
::Fn(..) | Def
::Static(..) | Def
::Const(..) | Def
::VariantCtor(..) => {
462 self.define(parent
, ident
, ValueNS
, (def
, vis
, DUMMY_SP
, expansion
));
464 Def
::StructCtor(..) => {
465 self.define(parent
, ident
, ValueNS
, (def
, vis
, DUMMY_SP
, expansion
));
467 if let Some(struct_def_id
) =
468 self.session
.cstore
.def_key(def_id
).parent
469 .map(|index
| DefId { krate: def_id.krate, index: index }
) {
470 self.struct_constructors
.insert(struct_def_id
, (def
, vis
));
474 let module_kind
= ModuleKind
::Def(def
, ident
.name
);
475 let module
= self.new_module(parent
,
477 parent
.normal_ancestor_id
,
480 self.define(parent
, ident
, TypeNS
, (module
, vis
, DUMMY_SP
, expansion
));
482 for child
in self.session
.cstore
.item_children(def_id
, self.session
) {
483 let ns
= if let Def
::AssociatedTy(..) = child
.def { TypeNS }
else { ValueNS }
;
484 self.define(module
, child
.ident
, ns
,
485 (child
.def
, ty
::Visibility
::Public
, DUMMY_SP
, expansion
));
487 if self.session
.cstore
.associated_item_cloned(child
.def
.def_id())
488 .method_has_self_argument
{
489 self.has_self
.insert(child
.def
.def_id());
492 module
.populated
.set(true);
494 Def
::Struct(..) | Def
::Union(..) => {
495 self.define(parent
, ident
, TypeNS
, (def
, vis
, DUMMY_SP
, expansion
));
497 // Record field names for error reporting.
498 let field_names
= self.session
.cstore
.struct_field_names(def_id
);
499 self.insert_field_names(def_id
, field_names
);
502 self.define(parent
, ident
, MacroNS
, (def
, vis
, DUMMY_SP
, expansion
));
504 _
=> bug
!("unexpected definition: {:?}", def
)
508 pub fn get_module(&mut self, def_id
: DefId
) -> Module
<'a
> {
509 if def_id
.krate
== LOCAL_CRATE
{
510 return self.module_map
[&def_id
]
513 let macros_only
= self.session
.cstore
.dep_kind(def_id
.krate
).macros_only();
514 if let Some(&module
) = self.extern_module_map
.get(&(def_id
, macros_only
)) {
518 let (name
, parent
) = if def_id
.index
== CRATE_DEF_INDEX
{
519 (self.session
.cstore
.crate_name(def_id
.krate
), None
)
521 let def_key
= self.session
.cstore
.def_key(def_id
);
522 (def_key
.disambiguated_data
.data
.get_opt_name().unwrap(),
523 Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }
)))
526 let kind
= ModuleKind
::Def(Def
::Mod(def_id
), name
);
528 self.arenas
.alloc_module(ModuleData
::new(parent
, kind
, def_id
, Mark
::root(), DUMMY_SP
));
529 self.extern_module_map
.insert((def_id
, macros_only
), module
);
533 pub fn macro_def_scope(&mut self, expansion
: Mark
) -> Module
<'a
> {
534 let def_id
= self.macro_defs
[&expansion
];
535 if let Some(id
) = self.definitions
.as_local_node_id(def_id
) {
536 self.local_macro_def_scopes
[&id
]
537 } else if def_id
.krate
== BUILTIN_MACROS_CRATE
{
538 // FIXME(jseyfried): This happens when `include!()`ing a `$crate::` path, c.f, #40469.
541 let module_def_id
= ty
::DefIdTree
::parent(&*self, def_id
).unwrap();
542 self.get_module(module_def_id
)
546 pub fn get_macro(&mut self, def
: Def
) -> Rc
<SyntaxExtension
> {
547 let def_id
= match def
{
548 Def
::Macro(def_id
, ..) => def_id
,
549 _
=> panic
!("Expected Def::Macro(..)"),
551 if let Some(ext
) = self.macro_map
.get(&def_id
) {
555 let macro_def
= match self.session
.cstore
.load_macro(def_id
, &self.session
) {
556 LoadedMacro
::MacroDef(macro_def
) => macro_def
,
557 LoadedMacro
::ProcMacro(ext
) => return ext
,
560 let ext
= Rc
::new(macro_rules
::compile(&self.session
.parse_sess
,
561 &self.session
.features
,
563 self.macro_map
.insert(def_id
, ext
.clone());
567 /// Ensures that the reduced graph rooted at the given external module
568 /// is built, building it if it is not.
569 pub fn populate_module_if_necessary(&mut self, module
: Module
<'a
>) {
570 if module
.populated
.get() { return }
571 for child
in self.session
.cstore
.item_children(module
.def_id().unwrap(), self.session
) {
572 self.build_reduced_graph_for_external_crate_def(module
, child
);
574 module
.populated
.set(true)
577 fn legacy_import_macro(&mut self,
579 binding
: &'a NameBinding
<'a
>,
581 allow_shadowing
: bool
) {
582 if self.global_macros
.insert(name
, binding
).is_some() && !allow_shadowing
{
583 let msg
= format
!("`{}` is already in scope", name
);
585 "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
586 self.session
.struct_span_err(span
, &msg
).note(note
).emit();
590 // This returns true if we should consider the underlying `extern crate` to be used.
591 fn process_legacy_macro_imports(&mut self, item
: &Item
, module
: Module
<'a
>, expansion
: Mark
)
593 let allow_shadowing
= expansion
== Mark
::root();
594 let legacy_imports
= self.legacy_macro_imports(&item
.attrs
);
595 let mut used
= legacy_imports
!= LegacyMacroImports
::default();
597 // `#[macro_use]` and `#[macro_reexport]` are only allowed at the crate root.
598 if self.current_module
.parent
.is_some() && used
{
599 span_err
!(self.session
, item
.span
, E0468
,
600 "an `extern crate` loading macros must be at the crate root");
601 } else if !self.use_extern_macros
&& !used
&&
602 self.session
.cstore
.dep_kind(module
.def_id().unwrap().krate
).macros_only() {
603 let msg
= "proc macro crates and `#[no_link]` crates have no effect without \
605 self.session
.span_warn(item
.span
, msg
);
606 used
= true; // Avoid the normal unused extern crate warning
609 let (graph_root
, arenas
) = (self.graph_root
, self.arenas
);
610 let macro_use_directive
= |span
| arenas
.alloc_import_directive(ImportDirective
{
613 imported_module
: Cell
::new(Some(module
)),
614 subclass
: ImportDirectiveSubclass
::MacroUse
,
616 module_path
: Vec
::new(),
617 vis
: Cell
::new(ty
::Visibility
::Restricted(DefId
::local(CRATE_DEF_INDEX
))),
618 expansion
: expansion
,
619 used
: Cell
::new(false),
622 if let Some(span
) = legacy_imports
.import_all
{
623 let directive
= macro_use_directive(span
);
624 self.potentially_unused_imports
.push(directive
);
625 module
.for_each_child(|ident
, ns
, binding
| if ns
== MacroNS
{
626 let imported_binding
= self.import(binding
, directive
);
627 self.legacy_import_macro(ident
.name
, imported_binding
, span
, allow_shadowing
);
630 for (name
, span
) in legacy_imports
.imports
{
631 let ident
= Ident
::with_empty_ctxt(name
);
632 let result
= self.resolve_ident_in_module(module
, ident
, MacroNS
,
634 if let Ok(binding
) = result
{
635 let directive
= macro_use_directive(span
);
636 self.potentially_unused_imports
.push(directive
);
637 let imported_binding
= self.import(binding
, directive
);
638 self.legacy_import_macro(name
, imported_binding
, span
, allow_shadowing
);
640 span_err
!(self.session
, span
, E0469
, "imported macro not found");
644 for (name
, span
) in legacy_imports
.reexports
{
645 self.session
.cstore
.export_macros(module
.def_id().unwrap().krate
);
646 let ident
= Ident
::with_empty_ctxt(name
);
647 let result
= self.resolve_ident_in_module(module
, ident
, MacroNS
, false, false, span
);
648 if let Ok(binding
) = result
{
649 self.macro_exports
.push(Export { ident: ident, def: binding.def(), span: span }
);
651 span_err
!(self.session
, span
, E0470
, "reexported macro not found");
657 // does this attribute list contain "macro_use"?
658 fn contains_macro_use(&mut self, attrs
: &[ast
::Attribute
]) -> bool
{
660 if attr
.check_name("macro_escape") {
661 let msg
= "macro_escape is a deprecated synonym for macro_use";
662 let mut err
= self.session
.struct_span_warn(attr
.span
, msg
);
663 if let ast
::AttrStyle
::Inner
= attr
.style
{
664 err
.help("consider an outer attribute, #[macro_use] mod ...").emit();
668 } else if !attr
.check_name("macro_use") {
673 self.session
.span_err(attr
.span
, "arguments to macro_use are not allowed here");
681 fn legacy_macro_imports(&mut self, attrs
: &[ast
::Attribute
]) -> LegacyMacroImports
{
682 let mut imports
= LegacyMacroImports
::default();
684 if attr
.check_name("macro_use") {
685 match attr
.meta_item_list() {
686 Some(names
) => for attr
in names
{
687 if let Some(word
) = attr
.word() {
688 imports
.imports
.push((word
.name(), attr
.span()));
690 span_err
!(self.session
, attr
.span(), E0466
, "bad macro import");
693 None
=> imports
.import_all
= Some(attr
.span
),
695 } else if attr
.check_name("macro_reexport") {
696 let bad_macro_reexport
= |this
: &mut Self, span
| {
697 span_err
!(this
.session
, span
, E0467
, "bad macro reexport");
699 if let Some(names
) = attr
.meta_item_list() {
701 if let Some(word
) = attr
.word() {
702 imports
.reexports
.push((word
.name(), attr
.span()));
704 bad_macro_reexport(self, attr
.span());
708 bad_macro_reexport(self, attr
.span());
716 pub struct BuildReducedGraphVisitor
<'a
, 'b
: 'a
> {
717 pub resolver
: &'a
mut Resolver
<'b
>,
718 pub legacy_scope
: LegacyScope
<'b
>,
722 impl<'a
, 'b
> BuildReducedGraphVisitor
<'a
, 'b
> {
723 fn visit_invoc(&mut self, id
: ast
::NodeId
) -> &'b InvocationData
<'b
> {
724 let mark
= id
.placeholder_to_mark();
725 self.resolver
.current_module
.unresolved_invocations
.borrow_mut().insert(mark
);
726 let invocation
= self.resolver
.invocations
[&mark
];
727 invocation
.module
.set(self.resolver
.current_module
);
728 invocation
.legacy_scope
.set(self.legacy_scope
);
733 macro_rules
! method
{
734 ($visit
:ident
: $ty
:ty
, $invoc
:path
, $walk
:ident
) => {
735 fn $
visit(&mut self, node
: &'a $ty
) {
736 if let $
invoc(..) = node
.node
{
737 self.visit_invoc(node
.id
);
739 visit
::$
walk(self, node
);
745 impl<'a
, 'b
> Visitor
<'a
> for BuildReducedGraphVisitor
<'a
, 'b
> {
746 method
!(visit_impl_item
: ast
::ImplItem
, ast
::ImplItemKind
::Macro
, walk_impl_item
);
747 method
!(visit_expr
: ast
::Expr
, ast
::ExprKind
::Mac
, walk_expr
);
748 method
!(visit_pat
: ast
::Pat
, ast
::PatKind
::Mac
, walk_pat
);
749 method
!(visit_ty
: ast
::Ty
, ast
::TyKind
::Mac
, walk_ty
);
751 fn visit_item(&mut self, item
: &'a Item
) {
752 let macro_use
= match item
.node
{
753 ItemKind
::MacroDef(..) => {
754 self.resolver
.define_macro(item
, self.expansion
, &mut self.legacy_scope
);
757 ItemKind
::Mac(..) => {
758 self.legacy_scope
= LegacyScope
::Expansion(self.visit_invoc(item
.id
));
761 ItemKind
::Mod(..) => self.resolver
.contains_macro_use(&item
.attrs
),
765 let (parent
, legacy_scope
) = (self.resolver
.current_module
, self.legacy_scope
);
766 self.resolver
.build_reduced_graph_for_item(item
, self.expansion
);
767 visit
::walk_item(self, item
);
768 self.resolver
.current_module
= parent
;
770 self.legacy_scope
= legacy_scope
;
774 fn visit_stmt(&mut self, stmt
: &'a ast
::Stmt
) {
775 if let ast
::StmtKind
::Mac(..) = stmt
.node
{
776 self.legacy_scope
= LegacyScope
::Expansion(self.visit_invoc(stmt
.id
));
778 visit
::walk_stmt(self, stmt
);
782 fn visit_foreign_item(&mut self, foreign_item
: &'a ForeignItem
) {
783 self.resolver
.build_reduced_graph_for_foreign_item(foreign_item
, self.expansion
);
784 visit
::walk_foreign_item(self, foreign_item
);
787 fn visit_block(&mut self, block
: &'a Block
) {
788 let (parent
, legacy_scope
) = (self.resolver
.current_module
, self.legacy_scope
);
789 self.resolver
.build_reduced_graph_for_block(block
, self.expansion
);
790 visit
::walk_block(self, block
);
791 self.resolver
.current_module
= parent
;
792 self.legacy_scope
= legacy_scope
;
795 fn visit_trait_item(&mut self, item
: &'a TraitItem
) {
796 let parent
= self.resolver
.current_module
;
798 if let TraitItemKind
::Macro(_
) = item
.node
{
799 self.visit_invoc(item
.id
);
803 // Add the item to the trait info.
804 let item_def_id
= self.resolver
.definitions
.local_def_id(item
.id
);
805 let (def
, ns
) = match item
.node
{
806 TraitItemKind
::Const(..) => (Def
::AssociatedConst(item_def_id
), ValueNS
),
807 TraitItemKind
::Method(ref sig
, _
) => {
808 if sig
.decl
.has_self() {
809 self.resolver
.has_self
.insert(item_def_id
);
811 (Def
::Method(item_def_id
), ValueNS
)
813 TraitItemKind
::Type(..) => (Def
::AssociatedTy(item_def_id
), TypeNS
),
814 TraitItemKind
::Macro(_
) => bug
!(), // handled above
817 let vis
= ty
::Visibility
::Public
;
818 self.resolver
.define(parent
, item
.ident
, ns
, (def
, vis
, item
.span
, self.expansion
));
820 self.resolver
.current_module
= parent
.parent
.unwrap(); // nearest normal ancestor
821 visit
::walk_trait_item(self, item
);
822 self.resolver
.current_module
= parent
;