]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! Reduced graph building | |
12 | //! | |
13 | //! Here we build the "reduced graph": the graph of the module tree without | |
14 | //! any imports resolved. | |
15 | ||
c30ab7b3 | 16 | use macros::{InvocationData, LegacyScope}; |
476ff2be SL |
17 | use resolve_imports::ImportDirective; |
18 | use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; | |
32a655c1 SL |
19 | use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; |
20 | use {Resolver, ResolverArenas}; | |
476ff2be | 21 | use Namespace::{self, TypeNS, ValueNS, MacroNS}; |
9cc50fc6 | 22 | use {resolve_error, resolve_struct_error, ResolutionError}; |
1a4d82fc | 23 | |
476ff2be | 24 | use rustc::middle::cstore::LoadedMacro; |
54a0048b | 25 | use rustc::hir::def::*; |
7cac9316 | 26 | use rustc::hir::def_id::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; |
9e0c209e SL |
27 | use rustc::ty; |
28 | ||
29 | use std::cell::Cell; | |
c30ab7b3 | 30 | use std::rc::Rc; |
1a4d82fc | 31 | |
32a655c1 | 32 | use syntax::ast::{Name, Ident}; |
3157f602 | 33 | use syntax::attr; |
e9174d1e | 34 | |
c30ab7b3 | 35 | use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}; |
9e0c209e | 36 | use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; |
3157f602 | 37 | use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; |
476ff2be SL |
38 | use syntax::ext::base::SyntaxExtension; |
39 | use syntax::ext::base::Determinacy::Undetermined; | |
c30ab7b3 | 40 | use syntax::ext::hygiene::Mark; |
c30ab7b3 | 41 | use syntax::ext::tt::macro_rules; |
32a655c1 | 42 | use syntax::parse::token; |
476ff2be | 43 | use syntax::symbol::keywords; |
a7813a04 | 44 | use syntax::visit::{self, Visitor}; |
1a4d82fc | 45 | |
3157f602 XL |
46 | use syntax_pos::{Span, DUMMY_SP}; |
47 | ||
476ff2be | 48 | impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) { |
32a655c1 SL |
49 | fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { |
50 | arenas.alloc_name_binding(NameBinding { | |
476ff2be SL |
51 | kind: NameBindingKind::Module(self.0), |
52 | vis: self.1, | |
53 | span: self.2, | |
54 | expansion: self.3, | |
32a655c1 | 55 | }) |
7453a54e SL |
56 | } |
57 | } | |
58 | ||
476ff2be | 59 | impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) { |
32a655c1 SL |
60 | fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { |
61 | arenas.alloc_name_binding(NameBinding { | |
476ff2be SL |
62 | kind: NameBindingKind::Def(self.0), |
63 | vis: self.1, | |
64 | span: self.2, | |
65 | expansion: self.3, | |
32a655c1 | 66 | }) |
7453a54e SL |
67 | } |
68 | } | |
69 | ||
c30ab7b3 SL |
70 | #[derive(Default, PartialEq, Eq)] |
71 | struct LegacyMacroImports { | |
72 | import_all: Option<Span>, | |
73 | imports: Vec<(Name, Span)>, | |
74 | reexports: Vec<(Name, Span)>, | |
c30ab7b3 | 75 | } |
1a4d82fc | 76 | |
32a655c1 | 77 | impl<'a> Resolver<'a> { |
7453a54e SL |
78 | /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; |
79 | /// otherwise, reports an error. | |
7cac9316 | 80 | pub fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) |
32a655c1 | 81 | where T: ToNameBinding<'a>, |
5bcae85e | 82 | { |
32a655c1 SL |
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); | |
1a4d82fc JJ |
86 | } |
87 | } | |
88 | ||
89 | fn block_needs_anonymous_module(&mut self, block: &Block) -> bool { | |
7453a54e | 90 | // If any statements are items, we need to create an anonymous module |
3157f602 | 91 | block.stmts.iter().any(|statement| match statement.node { |
c30ab7b3 | 92 | StmtKind::Item(_) | StmtKind::Mac(_) => true, |
3157f602 XL |
93 | _ => false, |
94 | }) | |
a7813a04 XL |
95 | } |
96 | ||
c30ab7b3 SL |
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); | |
100 | } | |
101 | } | |
9e0c209e | 102 | |
c30ab7b3 SL |
103 | /// Constructs the reduced graph for one item. |
104 | fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) { | |
9e0c209e | 105 | let parent = self.current_module; |
32a655c1 | 106 | let ident = item.ident; |
1a4d82fc | 107 | let sp = item.span; |
a7813a04 | 108 | let vis = self.resolve_visibility(&item.vis); |
1a4d82fc JJ |
109 | |
110 | match item.node { | |
a7813a04 | 111 | ItemKind::Use(ref view_path) => { |
85aaf69f SL |
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. | |
32a655c1 | 115 | let mut module_path: Vec<_> = match view_path.node { |
85aaf69f SL |
116 | ViewPathSimple(_, ref full_path) => { |
117 | full_path.segments | |
92a42be0 SL |
118 | .split_last() |
119 | .unwrap() | |
120 | .1 | |
121 | .iter() | |
c30ab7b3 | 122 | .map(|seg| seg.identifier) |
92a42be0 | 123 | .collect() |
85aaf69f SL |
124 | } |
125 | ||
126 | ViewPathGlob(ref module_ident_path) | | |
127 | ViewPathList(ref module_ident_path, _) => { | |
128 | module_ident_path.segments | |
92a42be0 | 129 | .iter() |
c30ab7b3 | 130 | .map(|seg| seg.identifier) |
92a42be0 | 131 | .collect() |
85aaf69f SL |
132 | } |
133 | }; | |
134 | ||
32a655c1 SL |
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); | |
139 | } | |
140 | ||
85aaf69f | 141 | // Build up the import directives. |
3157f602 | 142 | let is_prelude = attr::contains_name(&item.attrs, "prelude_import"); |
85aaf69f SL |
143 | |
144 | match view_path.node { | |
476ff2be | 145 | ViewPathSimple(mut binding, ref full_path) => { |
c30ab7b3 | 146 | let mut source = full_path.segments.last().unwrap().identifier; |
476ff2be | 147 | let source_name = source.name; |
c30ab7b3 | 148 | if source_name == "mod" || source_name == "self" { |
c1a9b12d SL |
149 | resolve_error(self, |
150 | view_path.span, | |
151 | ResolutionError::SelfImportsOnlyAllowedWithin); | |
c30ab7b3 | 152 | } else if source_name == "$crate" && full_path.segments.len() == 1 { |
7cac9316 | 153 | let crate_root = self.resolve_crate_root(source.ctxt); |
c30ab7b3 SL |
154 | let crate_name = match crate_root.kind { |
155 | ModuleKind::Def(_, name) => name, | |
156 | ModuleKind::Block(..) => unreachable!(), | |
157 | }; | |
158 | source.name = crate_name; | |
476ff2be SL |
159 | if binding.name == "$crate" { |
160 | binding.name = crate_name; | |
161 | } | |
c30ab7b3 SL |
162 | |
163 | self.session.struct_span_warn(item.span, "`$crate` may not be imported") | |
164 | .note("`use $crate;` was erroneously allowed and \ | |
165 | will become a hard error in a future release") | |
166 | .emit(); | |
85aaf69f SL |
167 | } |
168 | ||
476ff2be | 169 | let subclass = SingleImport { |
32a655c1 SL |
170 | target: binding, |
171 | source: source, | |
476ff2be | 172 | result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), |
32a655c1 | 173 | type_ns_only: false, |
476ff2be SL |
174 | }; |
175 | self.add_import_directive( | |
176 | module_path, subclass, view_path.span, item.id, vis, expansion, | |
177 | ); | |
85aaf69f SL |
178 | } |
179 | ViewPathList(_, ref source_items) => { | |
180 | // Make sure there's at most one `mod` import in the list. | |
a7813a04 | 181 | let mod_spans = source_items.iter().filter_map(|item| { |
9e0c209e SL |
182 | if item.node.name.name == keywords::SelfValue.name() { |
183 | Some(item.span) | |
184 | } else { | |
185 | None | |
a7813a04 XL |
186 | } |
187 | }).collect::<Vec<Span>>(); | |
188 | ||
85aaf69f | 189 | if mod_spans.len() > 1 { |
9cc50fc6 | 190 | let mut e = resolve_struct_error(self, |
92a42be0 SL |
191 | mod_spans[0], |
192 | ResolutionError::SelfImportCanOnlyAppearOnceInTheList); | |
85aaf69f | 193 | for other_span in mod_spans.iter().skip(1) { |
9cc50fc6 | 194 | e.span_note(*other_span, "another `self` import appears here"); |
85aaf69f | 195 | } |
9cc50fc6 | 196 | e.emit(); |
85aaf69f SL |
197 | } |
198 | ||
199 | for source_item in source_items { | |
9e0c209e | 200 | let node = source_item.node; |
32a655c1 | 201 | let (module_path, ident, rename, type_ns_only) = { |
9e0c209e | 202 | if node.name.name != keywords::SelfValue.name() { |
32a655c1 SL |
203 | let rename = node.rename.unwrap_or(node.name); |
204 | (module_path.clone(), node.name, rename, false) | |
9e0c209e | 205 | } else { |
32a655c1 SL |
206 | let ident = *module_path.last().unwrap(); |
207 | if ident.name == keywords::CrateRoot.name() { | |
208 | resolve_error( | |
209 | self, | |
210 | source_item.span, | |
211 | ResolutionError:: | |
212 | SelfImportOnlyInImportListWithNonEmptyPrefix | |
213 | ); | |
214 | continue; | |
215 | } | |
c1a9b12d | 216 | let module_path = module_path.split_last().unwrap().1; |
32a655c1 SL |
217 | let rename = node.rename.unwrap_or(ident); |
218 | (module_path.to_vec(), ident, rename, true) | |
85aaf69f SL |
219 | } |
220 | }; | |
476ff2be SL |
221 | let subclass = SingleImport { |
222 | target: rename, | |
32a655c1 | 223 | source: ident, |
476ff2be | 224 | result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), |
32a655c1 | 225 | type_ns_only: type_ns_only, |
476ff2be SL |
226 | }; |
227 | let id = source_item.node.id; | |
228 | self.add_import_directive( | |
229 | module_path, subclass, source_item.span, id, vis, expansion, | |
230 | ); | |
85aaf69f SL |
231 | } |
232 | } | |
233 | ViewPathGlob(_) => { | |
9e0c209e SL |
234 | let subclass = GlobImport { |
235 | is_prelude: is_prelude, | |
32a655c1 | 236 | max_vis: Cell::new(ty::Visibility::Invisible), |
9e0c209e | 237 | }; |
476ff2be SL |
238 | self.add_import_directive( |
239 | module_path, subclass, view_path.span, item.id, vis, expansion, | |
240 | ); | |
85aaf69f SL |
241 | } |
242 | } | |
85aaf69f SL |
243 | } |
244 | ||
a7813a04 | 245 | ItemKind::ExternCrate(_) => { |
476ff2be | 246 | self.crate_loader.process_item(item, &self.definitions); |
c30ab7b3 SL |
247 | |
248 | // n.b. we don't need to look at the path option here, because cstore already did | |
476ff2be | 249 | let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap(); |
7cac9316 XL |
250 | let module = |
251 | self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); | |
32a655c1 SL |
252 | self.populate_module_if_necessary(module); |
253 | let used = self.process_legacy_macro_imports(item, module, expansion); | |
254 | let binding = | |
255 | (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas); | |
476ff2be SL |
256 | let directive = self.arenas.alloc_import_directive(ImportDirective { |
257 | id: item.id, | |
258 | parent: parent, | |
259 | imported_module: Cell::new(Some(module)), | |
260 | subclass: ImportDirectiveSubclass::ExternCrate, | |
261 | span: item.span, | |
262 | module_path: Vec::new(), | |
263 | vis: Cell::new(vis), | |
264 | expansion: expansion, | |
32a655c1 | 265 | used: Cell::new(used), |
476ff2be | 266 | }); |
32a655c1 | 267 | self.potentially_unused_imports.push(directive); |
476ff2be | 268 | let imported_binding = self.import(binding, directive); |
32a655c1 | 269 | self.define(parent, ident, TypeNS, imported_binding); |
85aaf69f SL |
270 | } |
271 | ||
cc61c64b XL |
272 | ItemKind::GlobalAsm(..) => {} |
273 | ||
c30ab7b3 SL |
274 | ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root |
275 | ||
a7813a04 | 276 | ItemKind::Mod(..) => { |
32a655c1 SL |
277 | let def_id = self.definitions.local_def_id(item.id); |
278 | let module_kind = ModuleKind::Def(Def::Mod(def_id), ident.name); | |
279 | let module = self.arenas.alloc_module(ModuleData { | |
9e0c209e | 280 | no_implicit_prelude: parent.no_implicit_prelude || { |
3157f602 | 281 | attr::contains_name(&item.attrs, "no_implicit_prelude") |
9e0c209e | 282 | }, |
7cac9316 | 283 | ..ModuleData::new(Some(parent), module_kind, def_id, expansion, item.span) |
3157f602 | 284 | }); |
32a655c1 SL |
285 | self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); |
286 | self.module_map.insert(def_id, module); | |
9e0c209e SL |
287 | |
288 | // Descend into the module. | |
289 | self.current_module = module; | |
1a4d82fc JJ |
290 | } |
291 | ||
476ff2be | 292 | ItemKind::ForeignMod(..) => self.crate_loader.process_item(item, &self.definitions), |
1a4d82fc JJ |
293 | |
294 | // These items live in the value namespace. | |
a7813a04 XL |
295 | ItemKind::Static(_, m, _) => { |
296 | let mutbl = m == Mutability::Mutable; | |
297 | let def = Def::Static(self.definitions.local_def_id(item.id), mutbl); | |
32a655c1 | 298 | self.define(parent, ident, ValueNS, (def, vis, sp, expansion)); |
1a4d82fc | 299 | } |
9e0c209e | 300 | ItemKind::Const(..) => { |
a7813a04 | 301 | let def = Def::Const(self.definitions.local_def_id(item.id)); |
32a655c1 | 302 | self.define(parent, ident, ValueNS, (def, vis, sp, expansion)); |
1a4d82fc | 303 | } |
9e0c209e | 304 | ItemKind::Fn(..) => { |
a7813a04 | 305 | let def = Def::Fn(self.definitions.local_def_id(item.id)); |
32a655c1 | 306 | self.define(parent, ident, ValueNS, (def, vis, sp, expansion)); |
1a4d82fc JJ |
307 | } |
308 | ||
309 | // These items live in the type namespace. | |
a7813a04 XL |
310 | ItemKind::Ty(..) => { |
311 | let def = Def::TyAlias(self.definitions.local_def_id(item.id)); | |
32a655c1 | 312 | self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); |
1a4d82fc JJ |
313 | } |
314 | ||
a7813a04 | 315 | ItemKind::Enum(ref enum_definition, _) => { |
a7813a04 | 316 | let def = Def::Enum(self.definitions.local_def_id(item.id)); |
32a655c1 | 317 | let module_kind = ModuleKind::Def(def, ident.name); |
7cac9316 XL |
318 | let module = self.new_module(parent, |
319 | module_kind, | |
320 | parent.normal_ancestor_id, | |
321 | expansion, | |
322 | item.span); | |
32a655c1 | 323 | self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); |
a7813a04 | 324 | |
85aaf69f | 325 | for variant in &(*enum_definition).variants { |
476ff2be | 326 | self.build_reduced_graph_for_variant(variant, module, vis, expansion); |
1a4d82fc | 327 | } |
1a4d82fc JJ |
328 | } |
329 | ||
330 | // These items live in both the type and value namespaces. | |
a7813a04 | 331 | ItemKind::Struct(ref struct_def, _) => { |
1a4d82fc | 332 | // Define a name in the type namespace. |
a7813a04 | 333 | let def = Def::Struct(self.definitions.local_def_id(item.id)); |
32a655c1 | 334 | self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); |
1a4d82fc | 335 | |
c30ab7b3 | 336 | // Record field names for error reporting. |
8bb4bdeb | 337 | let mut ctor_vis = vis; |
c30ab7b3 | 338 | let field_names = struct_def.fields().iter().filter_map(|field| { |
8bb4bdeb XL |
339 | let field_vis = self.resolve_visibility(&field.vis); |
340 | if ctor_vis.is_at_least(field_vis, &*self) { | |
341 | ctor_vis = field_vis; | |
342 | } | |
a7813a04 | 343 | field.ident.map(|ident| ident.name) |
a7813a04 XL |
344 | }).collect(); |
345 | let item_def_id = self.definitions.local_def_id(item.id); | |
c30ab7b3 | 346 | self.insert_field_names(item_def_id, field_names); |
8bb4bdeb XL |
347 | |
348 | // If this is a tuple or unit struct, define a name | |
349 | // in the value namespace as well. | |
350 | if !struct_def.is_struct() { | |
351 | let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), | |
352 | CtorKind::from_ast(struct_def)); | |
353 | self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion)); | |
354 | self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis)); | |
355 | } | |
1a4d82fc JJ |
356 | } |
357 | ||
9e0c209e SL |
358 | ItemKind::Union(ref vdata, _) => { |
359 | let def = Def::Union(self.definitions.local_def_id(item.id)); | |
32a655c1 | 360 | self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); |
1a4d82fc | 361 | |
c30ab7b3 SL |
362 | // Record field names for error reporting. |
363 | let field_names = vdata.fields().iter().filter_map(|field| { | |
9e0c209e SL |
364 | self.resolve_visibility(&field.vis); |
365 | field.ident.map(|ident| ident.name) | |
9e0c209e SL |
366 | }).collect(); |
367 | let item_def_id = self.definitions.local_def_id(item.id); | |
c30ab7b3 | 368 | self.insert_field_names(item_def_id, field_names); |
9e0c209e | 369 | } |
1a4d82fc | 370 | |
9e0c209e | 371 | ItemKind::DefaultImpl(..) | ItemKind::Impl(..) => {} |
1a4d82fc | 372 | |
9e0c209e SL |
373 | ItemKind::Trait(..) => { |
374 | let def_id = self.definitions.local_def_id(item.id); | |
7453a54e | 375 | |
9e0c209e | 376 | // Add all the items within to a new module. |
32a655c1 | 377 | let module_kind = ModuleKind::Def(Def::Trait(def_id), ident.name); |
7cac9316 XL |
378 | let module = self.new_module(parent, |
379 | module_kind, | |
380 | parent.normal_ancestor_id, | |
381 | expansion, | |
382 | item.span); | |
32a655c1 | 383 | self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); |
9e0c209e | 384 | self.current_module = module; |
1a4d82fc | 385 | } |
8bb4bdeb | 386 | ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(), |
1a4d82fc JJ |
387 | } |
388 | } | |
389 | ||
390 | // Constructs the reduced graph for one variant. Variants exist in the | |
391 | // type and value namespaces. | |
392 | fn build_reduced_graph_for_variant(&mut self, | |
393 | variant: &Variant, | |
32a655c1 | 394 | parent: Module<'a>, |
476ff2be SL |
395 | vis: ty::Visibility, |
396 | expansion: Mark) { | |
32a655c1 | 397 | let ident = variant.node.name; |
c30ab7b3 | 398 | let def_id = self.definitions.local_def_id(variant.node.data.id()); |
7453a54e | 399 | |
c30ab7b3 SL |
400 | // Define a name in the type namespace. |
401 | let def = Def::Variant(def_id); | |
32a655c1 | 402 | self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion)); |
c30ab7b3 SL |
403 | |
404 | // Define a constructor name in the value namespace. | |
405 | // Braced variants, unlike structs, generate unusable names in | |
406 | // value namespace, they are reserved for possible future use. | |
407 | let ctor_kind = CtorKind::from_ast(&variant.node.data); | |
408 | let ctor_def = Def::VariantCtor(def_id, ctor_kind); | |
32a655c1 | 409 | self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); |
1a4d82fc JJ |
410 | } |
411 | ||
1a4d82fc | 412 | /// Constructs the reduced graph for one foreign item. |
476ff2be | 413 | fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) { |
476ff2be | 414 | let def = match item.node { |
a7813a04 | 415 | ForeignItemKind::Fn(..) => { |
476ff2be | 416 | Def::Fn(self.definitions.local_def_id(item.id)) |
1a4d82fc | 417 | } |
a7813a04 | 418 | ForeignItemKind::Static(_, m) => { |
476ff2be | 419 | Def::Static(self.definitions.local_def_id(item.id), m) |
1a4d82fc | 420 | } |
c34b1796 | 421 | }; |
32a655c1 | 422 | let parent = self.current_module; |
476ff2be | 423 | let vis = self.resolve_visibility(&item.vis); |
32a655c1 | 424 | self.define(parent, item.ident, ValueNS, (def, vis, item.span, expansion)); |
1a4d82fc JJ |
425 | } |
426 | ||
7cac9316 | 427 | fn build_reduced_graph_for_block(&mut self, block: &Block, expansion: Mark) { |
9e0c209e | 428 | let parent = self.current_module; |
1a4d82fc | 429 | if self.block_needs_anonymous_module(block) { |
7cac9316 XL |
430 | let module = self.new_module(parent, |
431 | ModuleKind::Block(block.id), | |
432 | parent.normal_ancestor_id, | |
433 | expansion, | |
434 | block.span); | |
32a655c1 SL |
435 | self.block_map.insert(block.id, module); |
436 | self.current_module = module; // Descend into the block. | |
1a4d82fc JJ |
437 | } |
438 | } | |
439 | ||
54a0048b | 440 | /// Builds the reduced graph for a single item in an external crate. |
32a655c1 | 441 | fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) { |
7cac9316 | 442 | let ident = child.ident; |
c30ab7b3 SL |
443 | let def = child.def; |
444 | let def_id = def.def_id(); | |
32a655c1 | 445 | let vis = self.session.cstore.visibility(def_id); |
7cac9316 XL |
446 | let span = child.span; |
447 | let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene | |
1a4d82fc | 448 | match def { |
c30ab7b3 | 449 | Def::Mod(..) | Def::Enum(..) => { |
7cac9316 XL |
450 | let module = self.new_module(parent, |
451 | ModuleKind::Def(def, ident.name), | |
452 | def_id, | |
453 | expansion, | |
454 | span); | |
455 | self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); | |
c30ab7b3 | 456 | } |
32a655c1 | 457 | Def::Variant(..) | Def::TyAlias(..) => { |
7cac9316 | 458 | self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); |
c30ab7b3 | 459 | } |
8bb4bdeb | 460 | Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => { |
7cac9316 | 461 | self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); |
1a4d82fc | 462 | } |
8bb4bdeb | 463 | Def::StructCtor(..) => { |
7cac9316 | 464 | self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); |
8bb4bdeb XL |
465 | |
466 | if let Some(struct_def_id) = | |
467 | self.session.cstore.def_key(def_id).parent | |
468 | .map(|index| DefId { krate: def_id.krate, index: index }) { | |
469 | self.struct_constructors.insert(struct_def_id, (def, vis)); | |
470 | } | |
471 | } | |
c30ab7b3 | 472 | Def::Trait(..) => { |
32a655c1 | 473 | let module_kind = ModuleKind::Def(def, ident.name); |
7cac9316 XL |
474 | let module = self.new_module(parent, |
475 | module_kind, | |
476 | parent.normal_ancestor_id, | |
477 | expansion, | |
478 | span); | |
479 | self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); | |
32a655c1 SL |
480 | |
481 | for child in self.session.cstore.item_children(def_id) { | |
482 | let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS }; | |
7cac9316 XL |
483 | self.define(module, child.ident, ns, |
484 | (child.def, ty::Visibility::Public, DUMMY_SP, expansion)); | |
32a655c1 | 485 | |
7cac9316 XL |
486 | if self.session.cstore.associated_item_cloned(child.def.def_id()) |
487 | .method_has_self_argument { | |
488 | self.has_self.insert(child.def.def_id()); | |
489 | } | |
92a42be0 | 490 | } |
32a655c1 | 491 | module.populated.set(true); |
92a42be0 | 492 | } |
32a655c1 | 493 | Def::Struct(..) | Def::Union(..) => { |
7cac9316 | 494 | self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); |
9e0c209e | 495 | |
c30ab7b3 SL |
496 | // Record field names for error reporting. |
497 | let field_names = self.session.cstore.struct_field_names(def_id); | |
498 | self.insert_field_names(def_id, field_names); | |
9e0c209e | 499 | } |
476ff2be | 500 | Def::Macro(..) => { |
7cac9316 | 501 | self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, expansion)); |
92a42be0 | 502 | } |
32a655c1 | 503 | _ => bug!("unexpected definition: {:?}", def) |
1a4d82fc JJ |
504 | } |
505 | } | |
506 | ||
7cac9316 XL |
507 | pub fn get_module(&mut self, def_id: DefId) -> Module<'a> { |
508 | if def_id.krate == LOCAL_CRATE { | |
509 | return self.module_map[&def_id] | |
510 | } | |
511 | ||
512 | let macros_only = self.session.cstore.dep_kind(def_id.krate).macros_only(); | |
513 | if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) { | |
514 | return module; | |
515 | } | |
516 | ||
517 | let (name, parent) = if def_id.index == CRATE_DEF_INDEX { | |
518 | (self.session.cstore.crate_name(def_id.krate), None) | |
519 | } else { | |
520 | let def_key = self.session.cstore.def_key(def_id); | |
521 | (def_key.disambiguated_data.data.get_opt_name().unwrap(), | |
522 | Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }))) | |
523 | }; | |
524 | ||
525 | let kind = ModuleKind::Def(Def::Mod(def_id), name); | |
526 | let module = | |
527 | self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP)); | |
528 | self.extern_module_map.insert((def_id, macros_only), module); | |
529 | module | |
476ff2be SL |
530 | } |
531 | ||
8bb4bdeb XL |
532 | pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> { |
533 | let def_id = self.macro_defs[&expansion]; | |
534 | if let Some(id) = self.definitions.as_local_node_id(def_id) { | |
535 | self.local_macro_def_scopes[&id] | |
536 | } else if def_id.krate == BUILTIN_MACROS_CRATE { | |
537 | // FIXME(jseyfried): This happens when `include!()`ing a `$crate::` path, c.f, #40469. | |
538 | self.graph_root | |
539 | } else { | |
540 | let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap(); | |
7cac9316 | 541 | self.get_module(module_def_id) |
8bb4bdeb XL |
542 | } |
543 | } | |
544 | ||
476ff2be SL |
545 | pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> { |
546 | let def_id = match def { | |
8bb4bdeb | 547 | Def::Macro(def_id, ..) => def_id, |
476ff2be SL |
548 | _ => panic!("Expected Def::Macro(..)"), |
549 | }; | |
550 | if let Some(ext) = self.macro_map.get(&def_id) { | |
551 | return ext.clone(); | |
552 | } | |
553 | ||
8bb4bdeb XL |
554 | let macro_def = match self.session.cstore.load_macro(def_id, &self.session) { |
555 | LoadedMacro::MacroDef(macro_def) => macro_def, | |
476ff2be SL |
556 | LoadedMacro::ProcMacro(ext) => return ext, |
557 | }; | |
558 | ||
cc61c64b XL |
559 | let ext = Rc::new(macro_rules::compile(&self.session.parse_sess, |
560 | &self.session.features, | |
561 | ¯o_def)); | |
476ff2be SL |
562 | self.macro_map.insert(def_id, ext.clone()); |
563 | ext | |
564 | } | |
565 | ||
54a0048b SL |
566 | /// Ensures that the reduced graph rooted at the given external module |
567 | /// is built, building it if it is not. | |
32a655c1 | 568 | pub fn populate_module_if_necessary(&mut self, module: Module<'a>) { |
54a0048b SL |
569 | if module.populated.get() { return } |
570 | for child in self.session.cstore.item_children(module.def_id().unwrap()) { | |
571 | self.build_reduced_graph_for_external_crate_def(module, child); | |
1a4d82fc | 572 | } |
54a0048b | 573 | module.populated.set(true) |
1a4d82fc | 574 | } |
c30ab7b3 | 575 | |
476ff2be SL |
576 | fn legacy_import_macro(&mut self, |
577 | name: Name, | |
32a655c1 | 578 | binding: &'a NameBinding<'a>, |
476ff2be SL |
579 | span: Span, |
580 | allow_shadowing: bool) { | |
cc61c64b | 581 | if self.global_macros.insert(name, binding).is_some() && !allow_shadowing { |
476ff2be SL |
582 | let msg = format!("`{}` is already in scope", name); |
583 | let note = | |
584 | "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)"; | |
585 | self.session.struct_span_err(span, &msg).note(note).emit(); | |
586 | } | |
587 | } | |
c30ab7b3 | 588 | |
32a655c1 SL |
589 | // This returns true if we should consider the underlying `extern crate` to be used. |
590 | fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expansion: Mark) | |
591 | -> bool { | |
476ff2be SL |
592 | let allow_shadowing = expansion == Mark::root(); |
593 | let legacy_imports = self.legacy_macro_imports(&item.attrs); | |
32a655c1 | 594 | let mut used = legacy_imports != LegacyMacroImports::default(); |
476ff2be SL |
595 | |
596 | // `#[macro_use]` and `#[macro_reexport]` are only allowed at the crate root. | |
32a655c1 | 597 | if self.current_module.parent.is_some() && used { |
476ff2be SL |
598 | span_err!(self.session, item.span, E0468, |
599 | "an `extern crate` loading macros must be at the crate root"); | |
32a655c1 SL |
600 | } else if !self.use_extern_macros && !used && |
601 | self.session.cstore.dep_kind(module.def_id().unwrap().krate).macros_only() { | |
8bb4bdeb | 602 | let msg = "proc macro crates and `#[no_link]` crates have no effect without \ |
476ff2be SL |
603 | `#[macro_use]`"; |
604 | self.session.span_warn(item.span, msg); | |
32a655c1 | 605 | used = true; // Avoid the normal unused extern crate warning |
476ff2be | 606 | } |
c30ab7b3 | 607 | |
32a655c1 SL |
608 | let (graph_root, arenas) = (self.graph_root, self.arenas); |
609 | let macro_use_directive = |span| arenas.alloc_import_directive(ImportDirective { | |
610 | id: item.id, | |
611 | parent: graph_root, | |
612 | imported_module: Cell::new(Some(module)), | |
613 | subclass: ImportDirectiveSubclass::MacroUse, | |
614 | span: span, | |
615 | module_path: Vec::new(), | |
616 | vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))), | |
617 | expansion: expansion, | |
618 | used: Cell::new(false), | |
619 | }); | |
620 | ||
476ff2be | 621 | if let Some(span) = legacy_imports.import_all { |
32a655c1 SL |
622 | let directive = macro_use_directive(span); |
623 | self.potentially_unused_imports.push(directive); | |
624 | module.for_each_child(|ident, ns, binding| if ns == MacroNS { | |
625 | let imported_binding = self.import(binding, directive); | |
626 | self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); | |
476ff2be SL |
627 | }); |
628 | } else { | |
629 | for (name, span) in legacy_imports.imports { | |
32a655c1 | 630 | let ident = Ident::with_empty_ctxt(name); |
7cac9316 XL |
631 | let result = self.resolve_ident_in_module(module, ident, MacroNS, |
632 | false, false, span); | |
476ff2be | 633 | if let Ok(binding) = result { |
32a655c1 SL |
634 | let directive = macro_use_directive(span); |
635 | self.potentially_unused_imports.push(directive); | |
636 | let imported_binding = self.import(binding, directive); | |
637 | self.legacy_import_macro(name, imported_binding, span, allow_shadowing); | |
c30ab7b3 | 638 | } else { |
476ff2be | 639 | span_err!(self.session, span, E0469, "imported macro not found"); |
c30ab7b3 SL |
640 | } |
641 | } | |
476ff2be SL |
642 | } |
643 | for (name, span) in legacy_imports.reexports { | |
32a655c1 SL |
644 | self.session.cstore.export_macros(module.def_id().unwrap().krate); |
645 | let ident = Ident::with_empty_ctxt(name); | |
7cac9316 | 646 | let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span); |
476ff2be | 647 | if let Ok(binding) = result { |
7cac9316 | 648 | self.macro_exports.push(Export { ident: ident, def: binding.def(), span: span }); |
476ff2be SL |
649 | } else { |
650 | span_err!(self.session, span, E0470, "reexported macro not found"); | |
c30ab7b3 SL |
651 | } |
652 | } | |
32a655c1 | 653 | used |
c30ab7b3 SL |
654 | } |
655 | ||
656 | // does this attribute list contain "macro_use"? | |
657 | fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool { | |
658 | for attr in attrs { | |
659 | if attr.check_name("macro_escape") { | |
660 | let msg = "macro_escape is a deprecated synonym for macro_use"; | |
661 | let mut err = self.session.struct_span_warn(attr.span, msg); | |
476ff2be | 662 | if let ast::AttrStyle::Inner = attr.style { |
c30ab7b3 SL |
663 | err.help("consider an outer attribute, #[macro_use] mod ...").emit(); |
664 | } else { | |
665 | err.emit(); | |
666 | } | |
667 | } else if !attr.check_name("macro_use") { | |
668 | continue; | |
669 | } | |
670 | ||
671 | if !attr.is_word() { | |
672 | self.session.span_err(attr.span, "arguments to macro_use are not allowed here"); | |
673 | } | |
674 | return true; | |
675 | } | |
676 | ||
677 | false | |
678 | } | |
679 | ||
680 | fn legacy_macro_imports(&mut self, attrs: &[ast::Attribute]) -> LegacyMacroImports { | |
681 | let mut imports = LegacyMacroImports::default(); | |
682 | for attr in attrs { | |
683 | if attr.check_name("macro_use") { | |
684 | match attr.meta_item_list() { | |
685 | Some(names) => for attr in names { | |
686 | if let Some(word) = attr.word() { | |
476ff2be | 687 | imports.imports.push((word.name(), attr.span())); |
c30ab7b3 SL |
688 | } else { |
689 | span_err!(self.session, attr.span(), E0466, "bad macro import"); | |
690 | } | |
691 | }, | |
692 | None => imports.import_all = Some(attr.span), | |
693 | } | |
694 | } else if attr.check_name("macro_reexport") { | |
695 | let bad_macro_reexport = |this: &mut Self, span| { | |
696 | span_err!(this.session, span, E0467, "bad macro reexport"); | |
697 | }; | |
698 | if let Some(names) = attr.meta_item_list() { | |
699 | for attr in names { | |
700 | if let Some(word) = attr.word() { | |
476ff2be | 701 | imports.reexports.push((word.name(), attr.span())); |
c30ab7b3 SL |
702 | } else { |
703 | bad_macro_reexport(self, attr.span()); | |
704 | } | |
705 | } | |
706 | } else { | |
707 | bad_macro_reexport(self, attr.span()); | |
708 | } | |
c30ab7b3 SL |
709 | } |
710 | } | |
711 | imports | |
712 | } | |
1a4d82fc JJ |
713 | } |
714 | ||
c30ab7b3 SL |
715 | pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { |
716 | pub resolver: &'a mut Resolver<'b>, | |
717 | pub legacy_scope: LegacyScope<'b>, | |
718 | pub expansion: Mark, | |
719 | } | |
720 | ||
721 | impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { | |
722 | fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> { | |
cc61c64b | 723 | let mark = id.placeholder_to_mark(); |
476ff2be SL |
724 | self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark); |
725 | let invocation = self.resolver.invocations[&mark]; | |
c30ab7b3 SL |
726 | invocation.module.set(self.resolver.current_module); |
727 | invocation.legacy_scope.set(self.legacy_scope); | |
728 | invocation | |
729 | } | |
730 | } | |
731 | ||
732 | macro_rules! method { | |
733 | ($visit:ident: $ty:ty, $invoc:path, $walk:ident) => { | |
476ff2be | 734 | fn $visit(&mut self, node: &'a $ty) { |
c30ab7b3 SL |
735 | if let $invoc(..) = node.node { |
736 | self.visit_invoc(node.id); | |
737 | } else { | |
738 | visit::$walk(self, node); | |
739 | } | |
740 | } | |
741 | } | |
1a4d82fc JJ |
742 | } |
743 | ||
476ff2be | 744 | impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { |
c30ab7b3 SL |
745 | method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item); |
746 | method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr); | |
747 | method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat); | |
748 | method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty); | |
749 | ||
476ff2be | 750 | fn visit_item(&mut self, item: &'a Item) { |
c30ab7b3 | 751 | let macro_use = match item.node { |
8bb4bdeb | 752 | ItemKind::MacroDef(..) => { |
7cac9316 | 753 | self.resolver.define_macro(item, self.expansion, &mut self.legacy_scope); |
8bb4bdeb XL |
754 | return |
755 | } | |
756 | ItemKind::Mac(..) => { | |
757 | self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id)); | |
32a655c1 | 758 | return |
c30ab7b3 SL |
759 | } |
760 | ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs), | |
761 | _ => false, | |
762 | }; | |
763 | ||
764 | let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); | |
765 | self.resolver.build_reduced_graph_for_item(item, self.expansion); | |
a7813a04 | 766 | visit::walk_item(self, item); |
9e0c209e | 767 | self.resolver.current_module = parent; |
c30ab7b3 SL |
768 | if !macro_use { |
769 | self.legacy_scope = legacy_scope; | |
770 | } | |
771 | } | |
772 | ||
476ff2be | 773 | fn visit_stmt(&mut self, stmt: &'a ast::Stmt) { |
c30ab7b3 SL |
774 | if let ast::StmtKind::Mac(..) = stmt.node { |
775 | self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(stmt.id)); | |
776 | } else { | |
777 | visit::walk_stmt(self, stmt); | |
778 | } | |
1a4d82fc JJ |
779 | } |
780 | ||
476ff2be SL |
781 | fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { |
782 | self.resolver.build_reduced_graph_for_foreign_item(foreign_item, self.expansion); | |
c30ab7b3 | 783 | visit::walk_foreign_item(self, foreign_item); |
1a4d82fc JJ |
784 | } |
785 | ||
476ff2be | 786 | fn visit_block(&mut self, block: &'a Block) { |
c30ab7b3 | 787 | let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); |
7cac9316 | 788 | self.resolver.build_reduced_graph_for_block(block, self.expansion); |
a7813a04 | 789 | visit::walk_block(self, block); |
9e0c209e | 790 | self.resolver.current_module = parent; |
c30ab7b3 | 791 | self.legacy_scope = legacy_scope; |
9e0c209e SL |
792 | } |
793 | ||
476ff2be | 794 | fn visit_trait_item(&mut self, item: &'a TraitItem) { |
9e0c209e | 795 | let parent = self.resolver.current_module; |
9e0c209e | 796 | |
c30ab7b3 SL |
797 | if let TraitItemKind::Macro(_) = item.node { |
798 | self.visit_invoc(item.id); | |
799 | return | |
800 | } | |
801 | ||
9e0c209e SL |
802 | // Add the item to the trait info. |
803 | let item_def_id = self.resolver.definitions.local_def_id(item.id); | |
7cac9316 XL |
804 | let (def, ns) = match item.node { |
805 | TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS), | |
806 | TraitItemKind::Method(ref sig, _) => { | |
807 | if sig.decl.has_self() { | |
808 | self.resolver.has_self.insert(item_def_id); | |
809 | } | |
810 | (Def::Method(item_def_id), ValueNS) | |
811 | } | |
812 | TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS), | |
c30ab7b3 | 813 | TraitItemKind::Macro(_) => bug!(), // handled above |
9e0c209e SL |
814 | }; |
815 | ||
9e0c209e | 816 | let vis = ty::Visibility::Public; |
32a655c1 | 817 | self.resolver.define(parent, item.ident, ns, (def, vis, item.span, self.expansion)); |
9e0c209e SL |
818 | |
819 | self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor | |
820 | visit::walk_trait_item(self, item); | |
821 | self.resolver.current_module = parent; | |
1a4d82fc JJ |
822 | } |
823 | } |