1 //! Reduced graph building
3 //! Here we build the "reduced graph": the graph of the module tree without
4 //! any imports resolved.
6 use macros
::{InvocationData, ParentScope, LegacyScope}
;
7 use resolve_imports
::ImportDirective
;
8 use resolve_imports
::ImportDirectiveSubclass
::{self, GlobImport, SingleImport}
;
9 use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding}
;
10 use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry}
;
11 use Namespace
::{self, TypeNS, ValueNS, MacroNS}
;
12 use {resolve_error, resolve_struct_error, ResolutionError}
;
14 use rustc
::hir
::def
::*;
15 use rustc
::hir
::def_id
::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}
;
17 use rustc
::middle
::cstore
::CrateStore
;
18 use rustc_metadata
::cstore
::LoadedMacro
;
22 use rustc_data_structures
::sync
::Lrc
;
24 use syntax
::ast
::{Name, Ident}
;
27 use syntax
::ast
::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}
;
28 use syntax
::ast
::{MetaItemKind, Mutability, StmtKind, TraitItem, TraitItemKind, Variant}
;
29 use syntax
::ext
::base
::{MacroKind, SyntaxExtension}
;
30 use syntax
::ext
::base
::Determinacy
::Undetermined
;
31 use syntax
::ext
::hygiene
::Mark
;
32 use syntax
::ext
::tt
::macro_rules
;
33 use syntax
::feature_gate
::{is_builtin_attr, emit_feature_err, GateIssue}
;
34 use syntax
::parse
::token
::{self, Token}
;
35 use syntax
::std_inject
::injected_crate_name
;
36 use syntax
::symbol
::keywords
;
37 use syntax
::visit
::{self, Visitor}
;
39 use syntax_pos
::{Span, DUMMY_SP}
;
41 impl<'a
> ToNameBinding
<'a
> for (Module
<'a
>, ty
::Visibility
, Span
, Mark
) {
42 fn to_name_binding(self, arenas
: &'a ResolverArenas
<'a
>) -> &'a NameBinding
<'a
> {
43 arenas
.alloc_name_binding(NameBinding
{
44 kind
: NameBindingKind
::Module(self.0),
53 impl<'a
> ToNameBinding
<'a
> for (Def
, ty
::Visibility
, Span
, Mark
) {
54 fn to_name_binding(self, arenas
: &'a ResolverArenas
<'a
>) -> &'a NameBinding
<'a
> {
55 arenas
.alloc_name_binding(NameBinding
{
56 kind
: NameBindingKind
::Def(self.0, false),
65 pub(crate) struct IsMacroExport
;
67 impl<'a
> ToNameBinding
<'a
> for (Def
, ty
::Visibility
, Span
, Mark
, IsMacroExport
) {
68 fn to_name_binding(self, arenas
: &'a ResolverArenas
<'a
>) -> &'a NameBinding
<'a
> {
69 arenas
.alloc_name_binding(NameBinding
{
70 kind
: NameBindingKind
::Def(self.0, true),
79 impl<'a
> Resolver
<'a
> {
80 /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
81 /// otherwise, reports an error.
82 pub fn define
<T
>(&mut self, parent
: Module
<'a
>, ident
: Ident
, ns
: Namespace
, def
: T
)
83 where T
: ToNameBinding
<'a
>,
85 let binding
= def
.to_name_binding(self.arenas
);
86 if let Err(old_binding
) = self.try_define(parent
, ident
, ns
, binding
) {
87 self.report_conflict(parent
, ident
, ns
, old_binding
, &binding
);
91 fn block_needs_anonymous_module(&mut self, block
: &Block
) -> bool
{
92 // If any statements are items, we need to create an anonymous module
93 block
.stmts
.iter().any(|statement
| match statement
.node
{
94 StmtKind
::Item(_
) | StmtKind
::Mac(_
) => true,
99 fn insert_field_names(&mut self, def_id
: DefId
, field_names
: Vec
<Name
>) {
100 if !field_names
.is_empty() {
101 self.field_names
.insert(def_id
, field_names
);
105 fn build_reduced_graph_for_use_tree(
107 // This particular use tree
108 use_tree
: &ast
::UseTree
,
110 parent_prefix
: &[Segment
],
112 // The whole `use` item
113 parent_scope
: ParentScope
<'a
>,
118 debug
!("build_reduced_graph_for_use_tree(parent_prefix={:?}, use_tree={:?}, nested={})",
119 parent_prefix
, use_tree
, nested
);
121 let mut prefix_iter
= parent_prefix
.iter().cloned()
122 .chain(use_tree
.prefix
.segments
.iter().map(|seg
| seg
.into())).peekable();
124 // On 2015 edition imports are resolved as crate-relative by default,
125 // so prefixes are prepended with crate root segment if necessary.
126 // The root is prepended lazily, when the first non-empty prefix or terminating glob
127 // appears, so imports in braced groups can have roots prepended independently.
128 // 2015 identifiers used on global 2018 edition enter special "virtual 2015 mode", don't
129 // get crate root prepended, but get special treatment during in-scope resolution instead.
130 let is_glob
= if let ast
::UseTreeKind
::Glob
= use_tree
.kind { true }
else { false }
;
131 let crate_root
= match prefix_iter
.peek() {
132 Some(seg
) if !seg
.ident
.is_path_segment_keyword() &&
133 seg
.ident
.span
.rust_2015() && self.session
.rust_2015() => {
134 Some(seg
.ident
.span
.ctxt())
136 None
if is_glob
&& use_tree
.span
.rust_2015() => {
137 Some(use_tree
.span
.ctxt())
140 }.map(|ctxt
| Segment
::from_ident(Ident
::new(
141 keywords
::PathRoot
.name(), use_tree
.prefix
.span
.shrink_to_lo().with_ctxt(ctxt
)
144 let prefix
= crate_root
.into_iter().chain(prefix_iter
).collect
::<Vec
<_
>>();
145 debug
!("build_reduced_graph_for_use_tree: prefix={:?}", prefix
);
147 let empty_for_self
= |prefix
: &[Segment
]| {
149 prefix
.len() == 1 && prefix
[0].ident
.name
== keywords
::PathRoot
.name()
151 match use_tree
.kind
{
152 ast
::UseTreeKind
::Simple(rename
, ..) => {
153 let mut ident
= use_tree
.ident().gensym_if_underscore();
154 let mut module_path
= prefix
;
155 let mut source
= module_path
.pop().unwrap();
156 let mut type_ns_only
= false;
159 // Correctly handle `self`
160 if source
.ident
.name
== keywords
::SelfLower
.name() {
163 if empty_for_self(&module_path
) {
168 SelfImportOnlyInImportListWithNonEmptyPrefix
173 // Replace `use foo::self;` with `use foo;`
174 source
= module_path
.pop().unwrap();
175 if rename
.is_none() {
176 ident
= source
.ident
;
181 if source
.ident
.name
== keywords
::SelfLower
.name() {
184 ResolutionError
::SelfImportsOnlyAllowedWithin
);
187 // Disallow `use $crate;`
188 if source
.ident
.name
== keywords
::DollarCrate
.name() && module_path
.is_empty() {
189 let crate_root
= self.resolve_crate_root(source
.ident
);
190 let crate_name
= match crate_root
.kind
{
191 ModuleKind
::Def(_
, name
) => name
,
192 ModuleKind
::Block(..) => unreachable
!(),
194 // HACK(eddyb) unclear how good this is, but keeping `$crate`
195 // in `source` breaks `src/test/compile-fail/import-crate-var.rs`,
196 // while the current crate doesn't have a valid `crate_name`.
197 if crate_name
!= keywords
::Invalid
.name() {
198 // `crate_name` should not be interpreted as relative.
199 module_path
.push(Segment
{
201 name
: keywords
::PathRoot
.name(),
202 span
: source
.ident
.span
,
204 id
: Some(self.session
.next_node_id()),
206 source
.ident
.name
= crate_name
;
208 if rename
.is_none() {
209 ident
.name
= crate_name
;
212 self.session
.struct_span_warn(item
.span
, "`$crate` may not be imported")
213 .note("`use $crate;` was erroneously allowed and \
214 will become a hard error in a future release")
219 if ident
.name
== keywords
::Crate
.name() {
220 self.session
.span_err(ident
.span
,
221 "crate root imports need to be explicitly named: \
222 `use crate as name;`");
225 let subclass
= SingleImport
{
226 source
: source
.ident
,
228 source_bindings
: PerNS
{
229 type_ns
: Cell
::new(Err(Undetermined
)),
230 value_ns
: Cell
::new(Err(Undetermined
)),
231 macro_ns
: Cell
::new(Err(Undetermined
)),
233 target_bindings
: PerNS
{
234 type_ns
: Cell
::new(None
),
235 value_ns
: Cell
::new(None
),
236 macro_ns
: Cell
::new(None
),
240 self.add_import_directive(
251 ast
::UseTreeKind
::Glob
=> {
252 let subclass
= GlobImport
{
253 is_prelude
: attr
::contains_name(&item
.attrs
, "prelude_import"),
254 max_vis
: Cell
::new(ty
::Visibility
::Invisible
),
256 self.add_import_directive(
267 ast
::UseTreeKind
::Nested(ref items
) => {
268 // Ensure there is at most one `self` in the list
269 let self_spans
= items
.iter().filter_map(|&(ref use_tree
, _
)| {
270 if let ast
::UseTreeKind
::Simple(..) = use_tree
.kind
{
271 if use_tree
.ident().name
== keywords
::SelfLower
.name() {
272 return Some(use_tree
.span
);
277 }).collect
::<Vec
<_
>>();
278 if self_spans
.len() > 1 {
279 let mut e
= resolve_struct_error(self,
281 ResolutionError
::SelfImportCanOnlyAppearOnceInTheList
);
283 for other_span
in self_spans
.iter().skip(1) {
284 e
.span_label(*other_span
, "another `self` import appears here");
290 for &(ref tree
, id
) in items
{
291 self.build_reduced_graph_for_use_tree(
292 // This particular use tree
293 tree
, id
, &prefix
, true,
294 // The whole `use` item
295 parent_scope
.clone(), item
, vis
, root_span
,
299 // Empty groups `a::b::{}` are turned into synthetic `self` imports
300 // `a::b::c::{self as _}`, so that their prefixes are correctly
301 // resolved and checked for privacy/stability/etc.
302 if items
.is_empty() && !empty_for_self(&prefix
) {
303 let new_span
= prefix
[prefix
.len() - 1].ident
.span
;
304 let tree
= ast
::UseTree
{
305 prefix
: ast
::Path
::from_ident(
306 Ident
::new(keywords
::SelfLower
.name(), new_span
)
308 kind
: ast
::UseTreeKind
::Simple(
309 Some(Ident
::new(keywords
::Underscore
.name().gensymed(), new_span
)),
315 self.build_reduced_graph_for_use_tree(
316 // This particular use tree
317 &tree
, id
, &prefix
, true,
318 // The whole `use` item
319 parent_scope
, item
, ty
::Visibility
::Invisible
, root_span
,
326 /// Constructs the reduced graph for one item.
327 fn build_reduced_graph_for_item(&mut self, item
: &Item
, parent_scope
: ParentScope
<'a
>) {
328 let parent
= parent_scope
.module
;
329 let expansion
= parent_scope
.expansion
;
330 let ident
= item
.ident
.gensym_if_underscore();
332 let vis
= self.resolve_visibility(&item
.vis
);
335 ItemKind
::Use(ref use_tree
) => {
336 self.build_reduced_graph_for_use_tree(
337 // This particular use tree
338 use_tree
, item
.id
, &[], false,
339 // The whole `use` item
340 parent_scope
, item
, vis
, use_tree
.span
,
344 ItemKind
::ExternCrate(orig_name
) => {
345 let module
= if orig_name
.is_none() && ident
.name
== keywords
::SelfLower
.name() {
347 .struct_span_err(item
.span
, "`extern crate self;` requires renaming")
348 .span_suggestion(item
.span
, "try", "extern crate self as name;".into())
351 } else if orig_name
== Some(keywords
::SelfLower
.name()) {
352 if !self.session
.features_untracked().extern_crate_self
{
353 emit_feature_err(&self.session
.parse_sess
, "extern_crate_self", item
.span
,
354 GateIssue
::Language
, "`extern crate self` is unstable");
358 let crate_id
= self.crate_loader
.process_extern_crate(item
, &self.definitions
);
359 self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }
)
362 self.populate_module_if_necessary(module
);
363 if injected_crate_name().map_or(false, |name
| ident
.name
== name
) {
364 self.injected_crate
= Some(module
);
367 let used
= self.process_legacy_macro_imports(item
, module
, &parent_scope
);
369 (module
, ty
::Visibility
::Public
, sp
, expansion
).to_name_binding(self.arenas
);
370 let directive
= self.arenas
.alloc_import_directive(ImportDirective
{
374 imported_module
: Cell
::new(Some(ModuleOrUniformRoot
::Module(module
))),
375 subclass
: ImportDirectiveSubclass
::ExternCrate
{
379 root_span
: item
.span
,
381 module_path
: Vec
::new(),
383 used
: Cell
::new(used
),
385 self.potentially_unused_imports
.push(directive
);
386 let imported_binding
= self.import(binding
, directive
);
387 if ptr
::eq(self.current_module
, self.graph_root
) {
388 if let Some(entry
) = self.extern_prelude
.get(&ident
.modern()) {
389 if expansion
!= Mark
::root() && orig_name
.is_some() &&
390 entry
.extern_crate_item
.is_none() {
391 self.session
.span_err(item
.span
, "macro-expanded `extern crate` items \
392 cannot shadow names passed with \
396 let entry
= self.extern_prelude
.entry(ident
.modern())
397 .or_insert(ExternPreludeEntry
{
398 extern_crate_item
: None
,
399 introduced_by_item
: true,
401 entry
.extern_crate_item
= Some(imported_binding
);
402 if orig_name
.is_some() {
403 entry
.introduced_by_item
= true;
406 self.define(parent
, ident
, TypeNS
, imported_binding
);
409 ItemKind
::GlobalAsm(..) => {}
411 ItemKind
::Mod(..) if ident
== keywords
::Invalid
.ident() => {}
// Crate root
413 ItemKind
::Mod(..) => {
414 let def_id
= self.definitions
.local_def_id(item
.id
);
415 let module_kind
= ModuleKind
::Def(Def
::Mod(def_id
), ident
.name
);
416 let module
= self.arenas
.alloc_module(ModuleData
{
417 no_implicit_prelude
: parent
.no_implicit_prelude
|| {
418 attr
::contains_name(&item
.attrs
, "no_implicit_prelude")
420 ..ModuleData
::new(Some(parent
), module_kind
, def_id
, expansion
, item
.span
)
422 self.define(parent
, ident
, TypeNS
, (module
, vis
, sp
, expansion
));
423 self.module_map
.insert(def_id
, module
);
425 // Descend into the module.
426 self.current_module
= module
;
429 // Handled in `rustc_metadata::{native_libs,link_args}`
430 ItemKind
::ForeignMod(..) => {}
432 // These items live in the value namespace.
433 ItemKind
::Static(_
, m
, _
) => {
434 let mutbl
= m
== Mutability
::Mutable
;
435 let def
= Def
::Static(self.definitions
.local_def_id(item
.id
), mutbl
);
436 self.define(parent
, ident
, ValueNS
, (def
, vis
, sp
, expansion
));
438 ItemKind
::Const(..) => {
439 let def
= Def
::Const(self.definitions
.local_def_id(item
.id
));
440 self.define(parent
, ident
, ValueNS
, (def
, vis
, sp
, expansion
));
442 ItemKind
::Fn(..) => {
443 let def
= Def
::Fn(self.definitions
.local_def_id(item
.id
));
444 self.define(parent
, ident
, ValueNS
, (def
, vis
, sp
, expansion
));
446 // Functions introducing procedural macros reserve a slot
447 // in the macro namespace as well (see #52225).
448 if attr
::contains_name(&item
.attrs
, "proc_macro") ||
449 attr
::contains_name(&item
.attrs
, "proc_macro_attribute") {
450 let def
= Def
::Macro(def
.def_id(), MacroKind
::ProcMacroStub
);
451 self.define(parent
, ident
, MacroNS
, (def
, vis
, sp
, expansion
));
453 if let Some(attr
) = attr
::find_by_name(&item
.attrs
, "proc_macro_derive") {
454 if let Some(trait_attr
) =
455 attr
.meta_item_list().and_then(|list
| list
.get(0).cloned()) {
456 if let Some(ident
) = trait_attr
.name().map(Ident
::with_empty_ctxt
) {
457 let sp
= trait_attr
.span
;
458 let def
= Def
::Macro(def
.def_id(), MacroKind
::ProcMacroStub
);
459 self.define(parent
, ident
, MacroNS
, (def
, vis
, sp
, expansion
));
465 // These items live in the type namespace.
466 ItemKind
::Ty(..) => {
467 let def
= Def
::TyAlias(self.definitions
.local_def_id(item
.id
));
468 self.define(parent
, ident
, TypeNS
, (def
, vis
, sp
, expansion
));
471 ItemKind
::Existential(_
, _
) => {
472 let def
= Def
::Existential(self.definitions
.local_def_id(item
.id
));
473 self.define(parent
, ident
, TypeNS
, (def
, vis
, sp
, expansion
));
476 ItemKind
::Enum(ref enum_definition
, _
) => {
477 let def
= Def
::Enum(self.definitions
.local_def_id(item
.id
));
478 let module_kind
= ModuleKind
::Def(def
, ident
.name
);
479 let module
= self.new_module(parent
,
481 parent
.normal_ancestor_id
,
484 self.define(parent
, ident
, TypeNS
, (module
, vis
, sp
, expansion
));
486 for variant
in &(*enum_definition
).variants
{
487 self.build_reduced_graph_for_variant(variant
, module
, vis
, expansion
);
491 ItemKind
::TraitAlias(..) => {
492 let def
= Def
::TraitAlias(self.definitions
.local_def_id(item
.id
));
493 self.define(parent
, ident
, TypeNS
, (def
, vis
, sp
, expansion
));
496 // These items live in both the type and value namespaces.
497 ItemKind
::Struct(ref struct_def
, _
) => {
498 // Define a name in the type namespace.
499 let def_id
= self.definitions
.local_def_id(item
.id
);
500 let def
= Def
::Struct(def_id
);
501 self.define(parent
, ident
, TypeNS
, (def
, vis
, sp
, expansion
));
503 let mut ctor_vis
= vis
;
505 let has_non_exhaustive
= attr
::contains_name(&item
.attrs
, "non_exhaustive");
507 // If the structure is marked as non_exhaustive then lower the visibility
508 // to within the crate.
509 if has_non_exhaustive
&& vis
== ty
::Visibility
::Public
{
510 ctor_vis
= ty
::Visibility
::Restricted(DefId
::local(CRATE_DEF_INDEX
));
513 // Record field names for error reporting.
514 let field_names
= struct_def
.fields().iter().filter_map(|field
| {
515 let field_vis
= self.resolve_visibility(&field
.vis
);
516 if ctor_vis
.is_at_least(field_vis
, &*self) {
517 ctor_vis
= field_vis
;
519 field
.ident
.map(|ident
| ident
.name
)
521 let item_def_id
= self.definitions
.local_def_id(item
.id
);
522 self.insert_field_names(item_def_id
, field_names
);
524 // If this is a tuple or unit struct, define a name
525 // in the value namespace as well.
526 if !struct_def
.is_struct() {
527 let ctor_def
= Def
::StructCtor(self.definitions
.local_def_id(struct_def
.id()),
528 CtorKind
::from_ast(struct_def
));
529 self.define(parent
, ident
, ValueNS
, (ctor_def
, ctor_vis
, sp
, expansion
));
530 self.struct_constructors
.insert(def
.def_id(), (ctor_def
, ctor_vis
));
534 ItemKind
::Union(ref vdata
, _
) => {
535 let def
= Def
::Union(self.definitions
.local_def_id(item
.id
));
536 self.define(parent
, ident
, TypeNS
, (def
, vis
, sp
, expansion
));
538 // Record field names for error reporting.
539 let field_names
= vdata
.fields().iter().filter_map(|field
| {
540 self.resolve_visibility(&field
.vis
);
541 field
.ident
.map(|ident
| ident
.name
)
543 let item_def_id
= self.definitions
.local_def_id(item
.id
);
544 self.insert_field_names(item_def_id
, field_names
);
547 ItemKind
::Impl(..) => {}
549 ItemKind
::Trait(..) => {
550 let def_id
= self.definitions
.local_def_id(item
.id
);
552 // Add all the items within to a new module.
553 let module_kind
= ModuleKind
::Def(Def
::Trait(def_id
), ident
.name
);
554 let module
= self.new_module(parent
,
556 parent
.normal_ancestor_id
,
559 self.define(parent
, ident
, TypeNS
, (module
, vis
, sp
, expansion
));
560 self.current_module
= module
;
563 ItemKind
::MacroDef(..) | ItemKind
::Mac(_
) => unreachable
!(),
567 // Constructs the reduced graph for one variant. Variants exist in the
568 // type and value namespaces.
569 fn build_reduced_graph_for_variant(&mut self,
574 let ident
= variant
.node
.ident
;
575 let def_id
= self.definitions
.local_def_id(variant
.node
.data
.id());
577 // Define a name in the type namespace.
578 let def
= Def
::Variant(def_id
);
579 self.define(parent
, ident
, TypeNS
, (def
, vis
, variant
.span
, expansion
));
581 // Define a constructor name in the value namespace.
582 // Braced variants, unlike structs, generate unusable names in
583 // value namespace, they are reserved for possible future use.
584 let ctor_kind
= CtorKind
::from_ast(&variant
.node
.data
);
585 let ctor_def
= Def
::VariantCtor(def_id
, ctor_kind
);
587 self.define(parent
, ident
, ValueNS
, (ctor_def
, vis
, variant
.span
, expansion
));
590 /// Constructs the reduced graph for one foreign item.
591 fn build_reduced_graph_for_foreign_item(&mut self, item
: &ForeignItem
, expansion
: Mark
) {
592 let (def
, ns
) = match item
.node
{
593 ForeignItemKind
::Fn(..) => {
594 (Def
::Fn(self.definitions
.local_def_id(item
.id
)), ValueNS
)
596 ForeignItemKind
::Static(_
, m
) => {
597 (Def
::Static(self.definitions
.local_def_id(item
.id
), m
), ValueNS
)
599 ForeignItemKind
::Ty
=> {
600 (Def
::ForeignTy(self.definitions
.local_def_id(item
.id
)), TypeNS
)
602 ForeignItemKind
::Macro(_
) => unreachable
!(),
604 let parent
= self.current_module
;
605 let vis
= self.resolve_visibility(&item
.vis
);
606 self.define(parent
, item
.ident
, ns
, (def
, vis
, item
.span
, expansion
));
609 fn build_reduced_graph_for_block(&mut self, block
: &Block
, expansion
: Mark
) {
610 let parent
= self.current_module
;
611 if self.block_needs_anonymous_module(block
) {
612 let module
= self.new_module(parent
,
613 ModuleKind
::Block(block
.id
),
614 parent
.normal_ancestor_id
,
617 self.block_map
.insert(block
.id
, module
);
618 self.current_module
= module
; // Descend into the block.
622 /// Builds the reduced graph for a single item in an external crate.
623 fn build_reduced_graph_for_external_crate_def(&mut self, parent
: Module
<'a
>, child
: Export
) {
624 let Export { ident, def, vis, span }
= child
;
625 // FIXME: We shouldn't create the gensym here, it should come from metadata,
626 // but metadata cannot encode gensyms currently, so we create it here.
627 // This is only a guess, two equivalent idents may incorrectly get different gensyms here.
628 let ident
= ident
.gensym_if_underscore();
629 let def_id
= def
.def_id();
630 let expansion
= Mark
::root(); // FIXME(jseyfried) intercrate hygiene
632 Def
::Mod(..) | Def
::Enum(..) => {
633 let module
= self.new_module(parent
,
634 ModuleKind
::Def(def
, ident
.name
),
638 self.define(parent
, ident
, TypeNS
, (module
, vis
, DUMMY_SP
, expansion
));
640 Def
::Variant(..) | Def
::TyAlias(..) | Def
::ForeignTy(..) => {
641 self.define(parent
, ident
, TypeNS
, (def
, vis
, DUMMY_SP
, expansion
));
643 Def
::Fn(..) | Def
::Static(..) | Def
::Const(..) | Def
::VariantCtor(..) => {
644 self.define(parent
, ident
, ValueNS
, (def
, vis
, DUMMY_SP
, expansion
));
646 Def
::StructCtor(..) => {
647 self.define(parent
, ident
, ValueNS
, (def
, vis
, DUMMY_SP
, expansion
));
649 if let Some(struct_def_id
) =
650 self.cstore
.def_key(def_id
).parent
651 .map(|index
| DefId { krate: def_id.krate, index: index }
) {
652 self.struct_constructors
.insert(struct_def_id
, (def
, vis
));
656 let module_kind
= ModuleKind
::Def(def
, ident
.name
);
657 let module
= self.new_module(parent
,
659 parent
.normal_ancestor_id
,
662 self.define(parent
, ident
, TypeNS
, (module
, vis
, DUMMY_SP
, expansion
));
664 for child
in self.cstore
.item_children_untracked(def_id
, self.session
) {
665 let ns
= if let Def
::AssociatedTy(..) = child
.def { TypeNS }
else { ValueNS }
;
666 self.define(module
, child
.ident
, ns
,
667 (child
.def
, ty
::Visibility
::Public
, DUMMY_SP
, expansion
));
669 if self.cstore
.associated_item_cloned_untracked(child
.def
.def_id())
670 .method_has_self_argument
{
671 self.has_self
.insert(child
.def
.def_id());
674 module
.populated
.set(true);
676 Def
::Struct(..) | Def
::Union(..) => {
677 self.define(parent
, ident
, TypeNS
, (def
, vis
, DUMMY_SP
, expansion
));
679 // Record field names for error reporting.
680 let field_names
= self.cstore
.struct_field_names_untracked(def_id
);
681 self.insert_field_names(def_id
, field_names
);
684 self.define(parent
, ident
, MacroNS
, (def
, vis
, DUMMY_SP
, expansion
));
686 _
=> bug
!("unexpected definition: {:?}", def
)
690 pub fn get_module(&mut self, def_id
: DefId
) -> Module
<'a
> {
691 if def_id
.krate
== LOCAL_CRATE
{
692 return self.module_map
[&def_id
]
695 let macros_only
= self.cstore
.dep_kind_untracked(def_id
.krate
).macros_only();
696 if let Some(&module
) = self.extern_module_map
.get(&(def_id
, macros_only
)) {
700 let (name
, parent
) = if def_id
.index
== CRATE_DEF_INDEX
{
701 (self.cstore
.crate_name_untracked(def_id
.krate
).as_interned_str(), None
)
703 let def_key
= self.cstore
.def_key(def_id
);
704 (def_key
.disambiguated_data
.data
.get_opt_name().unwrap(),
705 Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }
)))
708 let kind
= ModuleKind
::Def(Def
::Mod(def_id
), name
.as_symbol());
710 self.arenas
.alloc_module(ModuleData
::new(parent
, kind
, def_id
, Mark
::root(), DUMMY_SP
));
711 self.extern_module_map
.insert((def_id
, macros_only
), module
);
715 pub fn macro_def_scope(&mut self, expansion
: Mark
) -> Module
<'a
> {
716 let def_id
= self.macro_defs
[&expansion
];
717 if let Some(id
) = self.definitions
.as_local_node_id(def_id
) {
718 self.local_macro_def_scopes
[&id
]
719 } else if def_id
.krate
== CrateNum
::BuiltinMacros
{
720 self.injected_crate
.unwrap_or(self.graph_root
)
722 let module_def_id
= ty
::DefIdTree
::parent(&*self, def_id
).unwrap();
723 self.get_module(module_def_id
)
727 pub fn get_macro(&mut self, def
: Def
) -> Lrc
<SyntaxExtension
> {
728 let def_id
= match def
{
729 Def
::Macro(def_id
, ..) => def_id
,
730 Def
::NonMacroAttr(attr_kind
) => return Lrc
::new(SyntaxExtension
::NonMacroAttr
{
731 mark_used
: attr_kind
== NonMacroAttrKind
::Tool
,
733 _
=> panic
!("expected `Def::Macro` or `Def::NonMacroAttr`"),
735 if let Some(ext
) = self.macro_map
.get(&def_id
) {
739 let macro_def
= match self.cstore
.load_macro_untracked(def_id
, &self.session
) {
740 LoadedMacro
::MacroDef(macro_def
) => macro_def
,
741 LoadedMacro
::ProcMacro(ext
) => return ext
,
744 let ext
= Lrc
::new(macro_rules
::compile(&self.session
.parse_sess
,
745 &self.session
.features_untracked(),
747 self.cstore
.crate_edition_untracked(def_id
.krate
)));
748 self.macro_map
.insert(def_id
, ext
.clone());
752 /// Ensures that the reduced graph rooted at the given external module
753 /// is built, building it if it is not.
754 pub fn populate_module_if_necessary(&mut self, module
: Module
<'a
>) {
755 if module
.populated
.get() { return }
756 let def_id
= module
.def_id().unwrap();
757 for child
in self.cstore
.item_children_untracked(def_id
, self.session
) {
758 self.build_reduced_graph_for_external_crate_def(module
, child
);
760 module
.populated
.set(true)
763 fn legacy_import_macro(&mut self,
765 binding
: &'a NameBinding
<'a
>,
767 allow_shadowing
: bool
) {
768 if self.macro_use_prelude
.insert(name
, binding
).is_some() && !allow_shadowing
{
769 let msg
= format
!("`{}` is already in scope", name
);
771 "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
772 self.session
.struct_span_err(span
, &msg
).note(note
).emit();
776 // This returns true if we should consider the underlying `extern crate` to be used.
777 fn process_legacy_macro_imports(&mut self, item
: &Item
, module
: Module
<'a
>,
778 parent_scope
: &ParentScope
<'a
>) -> bool
{
779 let mut import_all
= None
;
780 let mut single_imports
= Vec
::new();
781 for attr
in &item
.attrs
{
782 if attr
.check_name("macro_use") {
783 if self.current_module
.parent
.is_some() {
784 span_err
!(self.session
, item
.span
, E0468
,
785 "an `extern crate` loading macros must be at the crate root");
787 if let ItemKind
::ExternCrate(Some(orig_name
)) = item
.node
{
788 if orig_name
== keywords
::SelfLower
.name() {
789 self.session
.span_err(attr
.span
,
790 "`macro_use` is not supported on `extern crate self`");
793 let ill_formed
= |span
| span_err
!(self.session
, span
, E0466
, "bad macro import");
795 Some(meta
) => match meta
.node
{
796 MetaItemKind
::Word
=> {
797 import_all
= Some(meta
.span
);
800 MetaItemKind
::List(nested_metas
) => for nested_meta
in nested_metas
{
801 match nested_meta
.word() {
802 Some(word
) => single_imports
.push((word
.name(), word
.span
)),
803 None
=> ill_formed(nested_meta
.span
),
806 MetaItemKind
::NameValue(..) => ill_formed(meta
.span
),
808 None
=> ill_formed(attr
.span()),
813 let arenas
= self.arenas
;
814 let macro_use_directive
= |span
| arenas
.alloc_import_directive(ImportDirective
{
817 parent_scope
: parent_scope
.clone(),
818 imported_module
: Cell
::new(Some(ModuleOrUniformRoot
::Module(module
))),
819 subclass
: ImportDirectiveSubclass
::MacroUse
,
822 module_path
: Vec
::new(),
823 vis
: Cell
::new(ty
::Visibility
::Restricted(DefId
::local(CRATE_DEF_INDEX
))),
824 used
: Cell
::new(false),
827 let allow_shadowing
= parent_scope
.expansion
== Mark
::root();
828 if let Some(span
) = import_all
{
829 let directive
= macro_use_directive(span
);
830 self.potentially_unused_imports
.push(directive
);
831 module
.for_each_child(|ident
, ns
, binding
| if ns
== MacroNS
{
832 let imported_binding
= self.import(binding
, directive
);
833 self.legacy_import_macro(ident
.name
, imported_binding
, span
, allow_shadowing
);
836 for (name
, span
) in single_imports
.iter().cloned() {
837 let ident
= Ident
::with_empty_ctxt(name
);
838 let result
= self.resolve_ident_in_module(
839 ModuleOrUniformRoot
::Module(module
),
846 if let Ok(binding
) = result
{
847 let directive
= macro_use_directive(span
);
848 self.potentially_unused_imports
.push(directive
);
849 let imported_binding
= self.import(binding
, directive
);
850 self.legacy_import_macro(name
, imported_binding
, span
, allow_shadowing
);
852 span_err
!(self.session
, span
, E0469
, "imported macro not found");
856 import_all
.is_some() || !single_imports
.is_empty()
859 // does this attribute list contain "macro_use"?
860 fn contains_macro_use(&mut self, attrs
: &[ast
::Attribute
]) -> bool
{
862 if attr
.check_name("macro_escape") {
863 let msg
= "macro_escape is a deprecated synonym for macro_use";
864 let mut err
= self.session
.struct_span_warn(attr
.span
, msg
);
865 if let ast
::AttrStyle
::Inner
= attr
.style
{
866 err
.help("consider an outer attribute, #[macro_use] mod ...").emit();
870 } else if !attr
.check_name("macro_use") {
875 self.session
.span_err(attr
.span
, "arguments to macro_use are not allowed here");
884 pub struct BuildReducedGraphVisitor
<'a
, 'b
: 'a
> {
885 pub resolver
: &'a
mut Resolver
<'b
>,
886 pub current_legacy_scope
: LegacyScope
<'b
>,
890 impl<'a
, 'b
> BuildReducedGraphVisitor
<'a
, 'b
> {
891 fn visit_invoc(&mut self, id
: ast
::NodeId
) -> &'b InvocationData
<'b
> {
892 let mark
= id
.placeholder_to_mark();
893 self.resolver
.current_module
.unresolved_invocations
.borrow_mut().insert(mark
);
894 let invocation
= self.resolver
.invocations
[&mark
];
895 invocation
.module
.set(self.resolver
.current_module
);
896 invocation
.parent_legacy_scope
.set(self.current_legacy_scope
);
901 macro_rules
! method
{
902 ($visit
:ident
: $ty
:ty
, $invoc
:path
, $walk
:ident
) => {
903 fn $
visit(&mut self, node
: &'a $ty
) {
904 if let $
invoc(..) = node
.node
{
905 self.visit_invoc(node
.id
);
907 visit
::$
walk(self, node
);
913 impl<'a
, 'b
> Visitor
<'a
> for BuildReducedGraphVisitor
<'a
, 'b
> {
914 method
!(visit_impl_item
: ast
::ImplItem
, ast
::ImplItemKind
::Macro
, walk_impl_item
);
915 method
!(visit_expr
: ast
::Expr
, ast
::ExprKind
::Mac
, walk_expr
);
916 method
!(visit_pat
: ast
::Pat
, ast
::PatKind
::Mac
, walk_pat
);
917 method
!(visit_ty
: ast
::Ty
, ast
::TyKind
::Mac
, walk_ty
);
919 fn visit_item(&mut self, item
: &'a Item
) {
920 let macro_use
= match item
.node
{
921 ItemKind
::MacroDef(..) => {
922 self.resolver
.define_macro(item
, self.expansion
, &mut self.current_legacy_scope
);
925 ItemKind
::Mac(..) => {
926 self.current_legacy_scope
= LegacyScope
::Invocation(self.visit_invoc(item
.id
));
929 ItemKind
::Mod(..) => self.resolver
.contains_macro_use(&item
.attrs
),
933 let orig_current_module
= self.resolver
.current_module
;
934 let orig_current_legacy_scope
= self.current_legacy_scope
;
935 let parent_scope
= ParentScope
{
936 module
: self.resolver
.current_module
,
937 expansion
: self.expansion
,
938 legacy
: self.current_legacy_scope
,
941 self.resolver
.build_reduced_graph_for_item(item
, parent_scope
);
942 visit
::walk_item(self, item
);
943 self.resolver
.current_module
= orig_current_module
;
945 self.current_legacy_scope
= orig_current_legacy_scope
;
949 fn visit_stmt(&mut self, stmt
: &'a ast
::Stmt
) {
950 if let ast
::StmtKind
::Mac(..) = stmt
.node
{
951 self.current_legacy_scope
= LegacyScope
::Invocation(self.visit_invoc(stmt
.id
));
953 visit
::walk_stmt(self, stmt
);
957 fn visit_foreign_item(&mut self, foreign_item
: &'a ForeignItem
) {
958 if let ForeignItemKind
::Macro(_
) = foreign_item
.node
{
959 self.visit_invoc(foreign_item
.id
);
963 self.resolver
.build_reduced_graph_for_foreign_item(foreign_item
, self.expansion
);
964 visit
::walk_foreign_item(self, foreign_item
);
967 fn visit_block(&mut self, block
: &'a Block
) {
968 let orig_current_module
= self.resolver
.current_module
;
969 let orig_current_legacy_scope
= self.current_legacy_scope
;
970 self.resolver
.build_reduced_graph_for_block(block
, self.expansion
);
971 visit
::walk_block(self, block
);
972 self.resolver
.current_module
= orig_current_module
;
973 self.current_legacy_scope
= orig_current_legacy_scope
;
976 fn visit_trait_item(&mut self, item
: &'a TraitItem
) {
977 let parent
= self.resolver
.current_module
;
979 if let TraitItemKind
::Macro(_
) = item
.node
{
980 self.visit_invoc(item
.id
);
984 // Add the item to the trait info.
985 let item_def_id
= self.resolver
.definitions
.local_def_id(item
.id
);
986 let (def
, ns
) = match item
.node
{
987 TraitItemKind
::Const(..) => (Def
::AssociatedConst(item_def_id
), ValueNS
),
988 TraitItemKind
::Method(ref sig
, _
) => {
989 if sig
.decl
.has_self() {
990 self.resolver
.has_self
.insert(item_def_id
);
992 (Def
::Method(item_def_id
), ValueNS
)
994 TraitItemKind
::Type(..) => (Def
::AssociatedTy(item_def_id
), TypeNS
),
995 TraitItemKind
::Macro(_
) => bug
!(), // handled above
998 let vis
= ty
::Visibility
::Public
;
999 self.resolver
.define(parent
, item
.ident
, ns
, (def
, vis
, item
.span
, self.expansion
));
1001 self.resolver
.current_module
= parent
.parent
.unwrap(); // nearest normal ancestor
1002 visit
::walk_trait_item(self, item
);
1003 self.resolver
.current_module
= parent
;
1006 fn visit_token(&mut self, t
: Token
) {
1007 if let Token
::Interpolated(nt
) = t
{
1008 if let token
::NtExpr(ref expr
) = nt
.0 {
1009 if let ast
::ExprKind
::Mac(..) = expr
.node
{
1010 self.visit_invoc(expr
.id
);
1016 fn visit_attribute(&mut self, attr
: &'a ast
::Attribute
) {
1017 if !attr
.is_sugared_doc
&& is_builtin_attr(attr
) {
1018 let parent_scope
= ParentScope
{
1019 module
: self.resolver
.current_module
.nearest_item_scope(),
1020 expansion
: self.expansion
,
1021 legacy
: self.current_legacy_scope
,
1022 // Let's hope discerning built-in attributes from derive helpers is not necessary
1023 derives
: Vec
::new(),
1025 parent_scope
.module
.builtin_attrs
.borrow_mut().push((
1026 attr
.path
.segments
[0].ident
, parent_scope
1029 visit
::walk_attribute(self, attr
);