]>
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::*; |
8bb4bdeb | 26 | use rustc::hir::def_id::{CrateNum, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, 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. | |
32a655c1 SL |
80 | fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) |
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 SL |
152 | } else if source_name == "$crate" && full_path.segments.len() == 1 { |
153 | let crate_root = self.resolve_crate_var(source.ctxt); | |
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 SL |
249 | let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap(); |
250 | let module = self.get_extern_crate_root(crate_id); | |
32a655c1 SL |
251 | self.populate_module_if_necessary(module); |
252 | let used = self.process_legacy_macro_imports(item, module, expansion); | |
253 | let binding = | |
254 | (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas); | |
476ff2be SL |
255 | let directive = self.arenas.alloc_import_directive(ImportDirective { |
256 | id: item.id, | |
257 | parent: parent, | |
258 | imported_module: Cell::new(Some(module)), | |
259 | subclass: ImportDirectiveSubclass::ExternCrate, | |
260 | span: item.span, | |
261 | module_path: Vec::new(), | |
262 | vis: Cell::new(vis), | |
263 | expansion: expansion, | |
32a655c1 | 264 | used: Cell::new(used), |
476ff2be | 265 | }); |
32a655c1 | 266 | self.potentially_unused_imports.push(directive); |
476ff2be | 267 | let imported_binding = self.import(binding, directive); |
32a655c1 | 268 | self.define(parent, ident, TypeNS, imported_binding); |
85aaf69f SL |
269 | } |
270 | ||
c30ab7b3 SL |
271 | ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root |
272 | ||
a7813a04 | 273 | ItemKind::Mod(..) => { |
32a655c1 SL |
274 | let def_id = self.definitions.local_def_id(item.id); |
275 | let module_kind = ModuleKind::Def(Def::Mod(def_id), ident.name); | |
276 | let module = self.arenas.alloc_module(ModuleData { | |
9e0c209e | 277 | no_implicit_prelude: parent.no_implicit_prelude || { |
3157f602 | 278 | attr::contains_name(&item.attrs, "no_implicit_prelude") |
9e0c209e | 279 | }, |
32a655c1 | 280 | ..ModuleData::new(Some(parent), module_kind, def_id) |
3157f602 | 281 | }); |
32a655c1 SL |
282 | self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); |
283 | self.module_map.insert(def_id, module); | |
9e0c209e SL |
284 | |
285 | // Descend into the module. | |
286 | self.current_module = module; | |
1a4d82fc JJ |
287 | } |
288 | ||
476ff2be | 289 | ItemKind::ForeignMod(..) => self.crate_loader.process_item(item, &self.definitions), |
1a4d82fc JJ |
290 | |
291 | // These items live in the value namespace. | |
a7813a04 XL |
292 | ItemKind::Static(_, m, _) => { |
293 | let mutbl = m == Mutability::Mutable; | |
294 | let def = Def::Static(self.definitions.local_def_id(item.id), mutbl); | |
32a655c1 | 295 | self.define(parent, ident, ValueNS, (def, vis, sp, expansion)); |
1a4d82fc | 296 | } |
9e0c209e | 297 | ItemKind::Const(..) => { |
a7813a04 | 298 | let def = Def::Const(self.definitions.local_def_id(item.id)); |
32a655c1 | 299 | self.define(parent, ident, ValueNS, (def, vis, sp, expansion)); |
1a4d82fc | 300 | } |
9e0c209e | 301 | ItemKind::Fn(..) => { |
a7813a04 | 302 | let def = Def::Fn(self.definitions.local_def_id(item.id)); |
32a655c1 | 303 | self.define(parent, ident, ValueNS, (def, vis, sp, expansion)); |
1a4d82fc JJ |
304 | } |
305 | ||
306 | // These items live in the type namespace. | |
a7813a04 XL |
307 | ItemKind::Ty(..) => { |
308 | let def = Def::TyAlias(self.definitions.local_def_id(item.id)); | |
32a655c1 | 309 | self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); |
1a4d82fc JJ |
310 | } |
311 | ||
a7813a04 | 312 | ItemKind::Enum(ref enum_definition, _) => { |
a7813a04 | 313 | let def = Def::Enum(self.definitions.local_def_id(item.id)); |
32a655c1 SL |
314 | let module_kind = ModuleKind::Def(def, ident.name); |
315 | let module = self.new_module(parent, module_kind, parent.normal_ancestor_id); | |
316 | self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); | |
a7813a04 | 317 | |
85aaf69f | 318 | for variant in &(*enum_definition).variants { |
476ff2be | 319 | self.build_reduced_graph_for_variant(variant, module, vis, expansion); |
1a4d82fc | 320 | } |
1a4d82fc JJ |
321 | } |
322 | ||
323 | // These items live in both the type and value namespaces. | |
a7813a04 | 324 | ItemKind::Struct(ref struct_def, _) => { |
1a4d82fc | 325 | // Define a name in the type namespace. |
a7813a04 | 326 | let def = Def::Struct(self.definitions.local_def_id(item.id)); |
32a655c1 | 327 | self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); |
1a4d82fc | 328 | |
c30ab7b3 | 329 | // Record field names for error reporting. |
8bb4bdeb | 330 | let mut ctor_vis = vis; |
c30ab7b3 | 331 | let field_names = struct_def.fields().iter().filter_map(|field| { |
8bb4bdeb XL |
332 | let field_vis = self.resolve_visibility(&field.vis); |
333 | if ctor_vis.is_at_least(field_vis, &*self) { | |
334 | ctor_vis = field_vis; | |
335 | } | |
a7813a04 | 336 | field.ident.map(|ident| ident.name) |
a7813a04 XL |
337 | }).collect(); |
338 | let item_def_id = self.definitions.local_def_id(item.id); | |
c30ab7b3 | 339 | self.insert_field_names(item_def_id, field_names); |
8bb4bdeb XL |
340 | |
341 | // If this is a tuple or unit struct, define a name | |
342 | // in the value namespace as well. | |
343 | if !struct_def.is_struct() { | |
344 | let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), | |
345 | CtorKind::from_ast(struct_def)); | |
346 | self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion)); | |
347 | self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis)); | |
348 | } | |
1a4d82fc JJ |
349 | } |
350 | ||
9e0c209e SL |
351 | ItemKind::Union(ref vdata, _) => { |
352 | let def = Def::Union(self.definitions.local_def_id(item.id)); | |
32a655c1 | 353 | self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); |
1a4d82fc | 354 | |
c30ab7b3 SL |
355 | // Record field names for error reporting. |
356 | let field_names = vdata.fields().iter().filter_map(|field| { | |
9e0c209e SL |
357 | self.resolve_visibility(&field.vis); |
358 | field.ident.map(|ident| ident.name) | |
9e0c209e SL |
359 | }).collect(); |
360 | let item_def_id = self.definitions.local_def_id(item.id); | |
c30ab7b3 | 361 | self.insert_field_names(item_def_id, field_names); |
9e0c209e | 362 | } |
1a4d82fc | 363 | |
9e0c209e | 364 | ItemKind::DefaultImpl(..) | ItemKind::Impl(..) => {} |
1a4d82fc | 365 | |
9e0c209e SL |
366 | ItemKind::Trait(..) => { |
367 | let def_id = self.definitions.local_def_id(item.id); | |
7453a54e | 368 | |
9e0c209e | 369 | // Add all the items within to a new module. |
32a655c1 SL |
370 | let module_kind = ModuleKind::Def(Def::Trait(def_id), ident.name); |
371 | let module = self.new_module(parent, module_kind, parent.normal_ancestor_id); | |
372 | self.define(parent, ident, TypeNS, (module, vis, sp, expansion)); | |
9e0c209e | 373 | self.current_module = module; |
1a4d82fc | 374 | } |
8bb4bdeb | 375 | ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(), |
1a4d82fc JJ |
376 | } |
377 | } | |
378 | ||
379 | // Constructs the reduced graph for one variant. Variants exist in the | |
380 | // type and value namespaces. | |
381 | fn build_reduced_graph_for_variant(&mut self, | |
382 | variant: &Variant, | |
32a655c1 | 383 | parent: Module<'a>, |
476ff2be SL |
384 | vis: ty::Visibility, |
385 | expansion: Mark) { | |
32a655c1 | 386 | let ident = variant.node.name; |
c30ab7b3 | 387 | let def_id = self.definitions.local_def_id(variant.node.data.id()); |
7453a54e | 388 | |
c30ab7b3 SL |
389 | // Define a name in the type namespace. |
390 | let def = Def::Variant(def_id); | |
32a655c1 | 391 | self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion)); |
c30ab7b3 SL |
392 | |
393 | // Define a constructor name in the value namespace. | |
394 | // Braced variants, unlike structs, generate unusable names in | |
395 | // value namespace, they are reserved for possible future use. | |
396 | let ctor_kind = CtorKind::from_ast(&variant.node.data); | |
397 | let ctor_def = Def::VariantCtor(def_id, ctor_kind); | |
32a655c1 | 398 | self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); |
1a4d82fc JJ |
399 | } |
400 | ||
1a4d82fc | 401 | /// Constructs the reduced graph for one foreign item. |
476ff2be | 402 | fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) { |
476ff2be | 403 | let def = match item.node { |
a7813a04 | 404 | ForeignItemKind::Fn(..) => { |
476ff2be | 405 | Def::Fn(self.definitions.local_def_id(item.id)) |
1a4d82fc | 406 | } |
a7813a04 | 407 | ForeignItemKind::Static(_, m) => { |
476ff2be | 408 | Def::Static(self.definitions.local_def_id(item.id), m) |
1a4d82fc | 409 | } |
c34b1796 | 410 | }; |
32a655c1 | 411 | let parent = self.current_module; |
476ff2be | 412 | let vis = self.resolve_visibility(&item.vis); |
32a655c1 | 413 | self.define(parent, item.ident, ValueNS, (def, vis, item.span, expansion)); |
1a4d82fc JJ |
414 | } |
415 | ||
9e0c209e SL |
416 | fn build_reduced_graph_for_block(&mut self, block: &Block) { |
417 | let parent = self.current_module; | |
1a4d82fc | 418 | if self.block_needs_anonymous_module(block) { |
32a655c1 SL |
419 | let module = |
420 | self.new_module(parent, ModuleKind::Block(block.id), parent.normal_ancestor_id); | |
421 | self.block_map.insert(block.id, module); | |
422 | self.current_module = module; // Descend into the block. | |
1a4d82fc JJ |
423 | } |
424 | } | |
425 | ||
54a0048b | 426 | /// Builds the reduced graph for a single item in an external crate. |
32a655c1 SL |
427 | fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) { |
428 | let ident = Ident::with_empty_ctxt(child.name); | |
c30ab7b3 SL |
429 | let def = child.def; |
430 | let def_id = def.def_id(); | |
32a655c1 | 431 | let vis = self.session.cstore.visibility(def_id); |
7453a54e | 432 | |
1a4d82fc | 433 | match def { |
c30ab7b3 | 434 | Def::Mod(..) | Def::Enum(..) => { |
32a655c1 SL |
435 | let module = self.new_module(parent, ModuleKind::Def(def, ident.name), def_id); |
436 | self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root())); | |
c30ab7b3 | 437 | } |
32a655c1 SL |
438 | Def::Variant(..) | Def::TyAlias(..) => { |
439 | self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); | |
c30ab7b3 | 440 | } |
8bb4bdeb | 441 | Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => { |
32a655c1 | 442 | self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); |
1a4d82fc | 443 | } |
8bb4bdeb XL |
444 | Def::StructCtor(..) => { |
445 | self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); | |
446 | ||
447 | if let Some(struct_def_id) = | |
448 | self.session.cstore.def_key(def_id).parent | |
449 | .map(|index| DefId { krate: def_id.krate, index: index }) { | |
450 | self.struct_constructors.insert(struct_def_id, (def, vis)); | |
451 | } | |
452 | } | |
c30ab7b3 | 453 | Def::Trait(..) => { |
32a655c1 SL |
454 | let module_kind = ModuleKind::Def(def, ident.name); |
455 | let module = self.new_module(parent, module_kind, parent.normal_ancestor_id); | |
456 | self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root())); | |
457 | ||
458 | for child in self.session.cstore.item_children(def_id) { | |
459 | let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS }; | |
460 | let ident = Ident::with_empty_ctxt(child.name); | |
461 | self.define(module, ident, ns, (child.def, ty::Visibility::Public, | |
462 | DUMMY_SP, Mark::root())); | |
463 | ||
8bb4bdeb XL |
464 | let has_self = self.session.cstore.associated_item_cloned(child.def.def_id()) |
465 | .method_has_self_argument; | |
32a655c1 | 466 | self.trait_item_map.insert((def_id, child.name, ns), (child.def, has_self)); |
92a42be0 | 467 | } |
32a655c1 | 468 | module.populated.set(true); |
92a42be0 | 469 | } |
32a655c1 SL |
470 | Def::Struct(..) | Def::Union(..) => { |
471 | self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); | |
9e0c209e | 472 | |
c30ab7b3 SL |
473 | // Record field names for error reporting. |
474 | let field_names = self.session.cstore.struct_field_names(def_id); | |
475 | self.insert_field_names(def_id, field_names); | |
9e0c209e | 476 | } |
476ff2be | 477 | Def::Macro(..) => { |
32a655c1 | 478 | self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, Mark::root())); |
92a42be0 | 479 | } |
32a655c1 | 480 | _ => bug!("unexpected definition: {:?}", def) |
1a4d82fc JJ |
481 | } |
482 | } | |
483 | ||
32a655c1 | 484 | fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> { |
476ff2be SL |
485 | let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; |
486 | let name = self.session.cstore.crate_name(cnum); | |
487 | let macros_only = self.session.cstore.dep_kind(cnum).macros_only(); | |
32a655c1 | 488 | let module_kind = ModuleKind::Def(Def::Mod(def_id), name); |
476ff2be SL |
489 | let arenas = self.arenas; |
490 | *self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| { | |
32a655c1 | 491 | arenas.alloc_module(ModuleData::new(None, module_kind, def_id)) |
476ff2be SL |
492 | }) |
493 | } | |
494 | ||
8bb4bdeb XL |
495 | pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> { |
496 | let def_id = self.macro_defs[&expansion]; | |
497 | if let Some(id) = self.definitions.as_local_node_id(def_id) { | |
498 | self.local_macro_def_scopes[&id] | |
499 | } else if def_id.krate == BUILTIN_MACROS_CRATE { | |
500 | // FIXME(jseyfried): This happens when `include!()`ing a `$crate::` path, c.f, #40469. | |
501 | self.graph_root | |
502 | } else { | |
503 | let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap(); | |
504 | self.get_extern_crate_root(module_def_id.krate) | |
505 | } | |
506 | } | |
507 | ||
476ff2be SL |
508 | pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> { |
509 | let def_id = match def { | |
8bb4bdeb | 510 | Def::Macro(def_id, ..) => def_id, |
476ff2be SL |
511 | _ => panic!("Expected Def::Macro(..)"), |
512 | }; | |
513 | if let Some(ext) = self.macro_map.get(&def_id) { | |
514 | return ext.clone(); | |
515 | } | |
516 | ||
8bb4bdeb XL |
517 | let macro_def = match self.session.cstore.load_macro(def_id, &self.session) { |
518 | LoadedMacro::MacroDef(macro_def) => macro_def, | |
476ff2be SL |
519 | LoadedMacro::ProcMacro(ext) => return ext, |
520 | }; | |
521 | ||
8bb4bdeb | 522 | let ext = Rc::new(macro_rules::compile(&self.session.parse_sess, ¯o_def)); |
476ff2be SL |
523 | self.macro_map.insert(def_id, ext.clone()); |
524 | ext | |
525 | } | |
526 | ||
54a0048b SL |
527 | /// Ensures that the reduced graph rooted at the given external module |
528 | /// is built, building it if it is not. | |
32a655c1 | 529 | pub fn populate_module_if_necessary(&mut self, module: Module<'a>) { |
54a0048b SL |
530 | if module.populated.get() { return } |
531 | for child in self.session.cstore.item_children(module.def_id().unwrap()) { | |
532 | self.build_reduced_graph_for_external_crate_def(module, child); | |
1a4d82fc | 533 | } |
54a0048b | 534 | module.populated.set(true) |
1a4d82fc | 535 | } |
c30ab7b3 | 536 | |
476ff2be SL |
537 | fn legacy_import_macro(&mut self, |
538 | name: Name, | |
32a655c1 | 539 | binding: &'a NameBinding<'a>, |
476ff2be SL |
540 | span: Span, |
541 | allow_shadowing: bool) { | |
476ff2be SL |
542 | if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing { |
543 | let msg = format!("`{}` is already in scope", name); | |
544 | let note = | |
545 | "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)"; | |
546 | self.session.struct_span_err(span, &msg).note(note).emit(); | |
547 | } | |
548 | } | |
c30ab7b3 | 549 | |
32a655c1 SL |
550 | // This returns true if we should consider the underlying `extern crate` to be used. |
551 | fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expansion: Mark) | |
552 | -> bool { | |
476ff2be SL |
553 | let allow_shadowing = expansion == Mark::root(); |
554 | let legacy_imports = self.legacy_macro_imports(&item.attrs); | |
32a655c1 | 555 | let mut used = legacy_imports != LegacyMacroImports::default(); |
476ff2be SL |
556 | |
557 | // `#[macro_use]` and `#[macro_reexport]` are only allowed at the crate root. | |
32a655c1 | 558 | if self.current_module.parent.is_some() && used { |
476ff2be SL |
559 | span_err!(self.session, item.span, E0468, |
560 | "an `extern crate` loading macros must be at the crate root"); | |
32a655c1 SL |
561 | } else if !self.use_extern_macros && !used && |
562 | self.session.cstore.dep_kind(module.def_id().unwrap().krate).macros_only() { | |
8bb4bdeb | 563 | let msg = "proc macro crates and `#[no_link]` crates have no effect without \ |
476ff2be SL |
564 | `#[macro_use]`"; |
565 | self.session.span_warn(item.span, msg); | |
32a655c1 | 566 | used = true; // Avoid the normal unused extern crate warning |
476ff2be | 567 | } |
c30ab7b3 | 568 | |
32a655c1 SL |
569 | let (graph_root, arenas) = (self.graph_root, self.arenas); |
570 | let macro_use_directive = |span| arenas.alloc_import_directive(ImportDirective { | |
571 | id: item.id, | |
572 | parent: graph_root, | |
573 | imported_module: Cell::new(Some(module)), | |
574 | subclass: ImportDirectiveSubclass::MacroUse, | |
575 | span: span, | |
576 | module_path: Vec::new(), | |
577 | vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))), | |
578 | expansion: expansion, | |
579 | used: Cell::new(false), | |
580 | }); | |
581 | ||
476ff2be | 582 | if let Some(span) = legacy_imports.import_all { |
32a655c1 SL |
583 | let directive = macro_use_directive(span); |
584 | self.potentially_unused_imports.push(directive); | |
585 | module.for_each_child(|ident, ns, binding| if ns == MacroNS { | |
586 | let imported_binding = self.import(binding, directive); | |
587 | self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); | |
476ff2be SL |
588 | }); |
589 | } else { | |
590 | for (name, span) in legacy_imports.imports { | |
32a655c1 SL |
591 | let ident = Ident::with_empty_ctxt(name); |
592 | let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None); | |
476ff2be | 593 | if let Ok(binding) = result { |
32a655c1 SL |
594 | let directive = macro_use_directive(span); |
595 | self.potentially_unused_imports.push(directive); | |
596 | let imported_binding = self.import(binding, directive); | |
597 | self.legacy_import_macro(name, imported_binding, span, allow_shadowing); | |
c30ab7b3 | 598 | } else { |
476ff2be | 599 | span_err!(self.session, span, E0469, "imported macro not found"); |
c30ab7b3 SL |
600 | } |
601 | } | |
476ff2be SL |
602 | } |
603 | for (name, span) in legacy_imports.reexports { | |
32a655c1 SL |
604 | self.session.cstore.export_macros(module.def_id().unwrap().krate); |
605 | let ident = Ident::with_empty_ctxt(name); | |
606 | let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None); | |
476ff2be SL |
607 | if let Ok(binding) = result { |
608 | self.macro_exports.push(Export { name: name, def: binding.def() }); | |
609 | } else { | |
610 | span_err!(self.session, span, E0470, "reexported macro not found"); | |
c30ab7b3 SL |
611 | } |
612 | } | |
32a655c1 | 613 | used |
c30ab7b3 SL |
614 | } |
615 | ||
616 | // does this attribute list contain "macro_use"? | |
617 | fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool { | |
618 | for attr in attrs { | |
619 | if attr.check_name("macro_escape") { | |
620 | let msg = "macro_escape is a deprecated synonym for macro_use"; | |
621 | let mut err = self.session.struct_span_warn(attr.span, msg); | |
476ff2be | 622 | if let ast::AttrStyle::Inner = attr.style { |
c30ab7b3 SL |
623 | err.help("consider an outer attribute, #[macro_use] mod ...").emit(); |
624 | } else { | |
625 | err.emit(); | |
626 | } | |
627 | } else if !attr.check_name("macro_use") { | |
628 | continue; | |
629 | } | |
630 | ||
631 | if !attr.is_word() { | |
632 | self.session.span_err(attr.span, "arguments to macro_use are not allowed here"); | |
633 | } | |
634 | return true; | |
635 | } | |
636 | ||
637 | false | |
638 | } | |
639 | ||
640 | fn legacy_macro_imports(&mut self, attrs: &[ast::Attribute]) -> LegacyMacroImports { | |
641 | let mut imports = LegacyMacroImports::default(); | |
642 | for attr in attrs { | |
643 | if attr.check_name("macro_use") { | |
644 | match attr.meta_item_list() { | |
645 | Some(names) => for attr in names { | |
646 | if let Some(word) = attr.word() { | |
476ff2be | 647 | imports.imports.push((word.name(), attr.span())); |
c30ab7b3 SL |
648 | } else { |
649 | span_err!(self.session, attr.span(), E0466, "bad macro import"); | |
650 | } | |
651 | }, | |
652 | None => imports.import_all = Some(attr.span), | |
653 | } | |
654 | } else if attr.check_name("macro_reexport") { | |
655 | let bad_macro_reexport = |this: &mut Self, span| { | |
656 | span_err!(this.session, span, E0467, "bad macro reexport"); | |
657 | }; | |
658 | if let Some(names) = attr.meta_item_list() { | |
659 | for attr in names { | |
660 | if let Some(word) = attr.word() { | |
476ff2be | 661 | imports.reexports.push((word.name(), attr.span())); |
c30ab7b3 SL |
662 | } else { |
663 | bad_macro_reexport(self, attr.span()); | |
664 | } | |
665 | } | |
666 | } else { | |
667 | bad_macro_reexport(self, attr.span()); | |
668 | } | |
c30ab7b3 SL |
669 | } |
670 | } | |
671 | imports | |
672 | } | |
1a4d82fc JJ |
673 | } |
674 | ||
c30ab7b3 SL |
675 | pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { |
676 | pub resolver: &'a mut Resolver<'b>, | |
677 | pub legacy_scope: LegacyScope<'b>, | |
678 | pub expansion: Mark, | |
679 | } | |
680 | ||
681 | impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { | |
682 | fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> { | |
476ff2be SL |
683 | let mark = Mark::from_placeholder_id(id); |
684 | self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark); | |
685 | let invocation = self.resolver.invocations[&mark]; | |
c30ab7b3 SL |
686 | invocation.module.set(self.resolver.current_module); |
687 | invocation.legacy_scope.set(self.legacy_scope); | |
688 | invocation | |
689 | } | |
690 | } | |
691 | ||
692 | macro_rules! method { | |
693 | ($visit:ident: $ty:ty, $invoc:path, $walk:ident) => { | |
476ff2be | 694 | fn $visit(&mut self, node: &'a $ty) { |
c30ab7b3 SL |
695 | if let $invoc(..) = node.node { |
696 | self.visit_invoc(node.id); | |
697 | } else { | |
698 | visit::$walk(self, node); | |
699 | } | |
700 | } | |
701 | } | |
1a4d82fc JJ |
702 | } |
703 | ||
476ff2be | 704 | impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { |
c30ab7b3 SL |
705 | method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item); |
706 | method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr); | |
707 | method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat); | |
708 | method!(visit_ty: ast::Ty, ast::TyKind::Mac, walk_ty); | |
709 | ||
476ff2be | 710 | fn visit_item(&mut self, item: &'a Item) { |
c30ab7b3 | 711 | let macro_use = match item.node { |
8bb4bdeb XL |
712 | ItemKind::MacroDef(..) => { |
713 | self.resolver.define_macro(item, &mut self.legacy_scope); | |
714 | return | |
715 | } | |
716 | ItemKind::Mac(..) => { | |
717 | self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id)); | |
32a655c1 | 718 | return |
c30ab7b3 SL |
719 | } |
720 | ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs), | |
721 | _ => false, | |
722 | }; | |
723 | ||
724 | let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); | |
725 | self.resolver.build_reduced_graph_for_item(item, self.expansion); | |
a7813a04 | 726 | visit::walk_item(self, item); |
9e0c209e | 727 | self.resolver.current_module = parent; |
c30ab7b3 SL |
728 | if !macro_use { |
729 | self.legacy_scope = legacy_scope; | |
730 | } | |
731 | } | |
732 | ||
476ff2be | 733 | fn visit_stmt(&mut self, stmt: &'a ast::Stmt) { |
c30ab7b3 SL |
734 | if let ast::StmtKind::Mac(..) = stmt.node { |
735 | self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(stmt.id)); | |
736 | } else { | |
737 | visit::walk_stmt(self, stmt); | |
738 | } | |
1a4d82fc JJ |
739 | } |
740 | ||
476ff2be SL |
741 | fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { |
742 | self.resolver.build_reduced_graph_for_foreign_item(foreign_item, self.expansion); | |
c30ab7b3 | 743 | visit::walk_foreign_item(self, foreign_item); |
1a4d82fc JJ |
744 | } |
745 | ||
476ff2be | 746 | fn visit_block(&mut self, block: &'a Block) { |
c30ab7b3 | 747 | let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope); |
9e0c209e | 748 | self.resolver.build_reduced_graph_for_block(block); |
a7813a04 | 749 | visit::walk_block(self, block); |
9e0c209e | 750 | self.resolver.current_module = parent; |
c30ab7b3 | 751 | self.legacy_scope = legacy_scope; |
9e0c209e SL |
752 | } |
753 | ||
476ff2be | 754 | fn visit_trait_item(&mut self, item: &'a TraitItem) { |
9e0c209e SL |
755 | let parent = self.resolver.current_module; |
756 | let def_id = parent.def_id().unwrap(); | |
757 | ||
c30ab7b3 SL |
758 | if let TraitItemKind::Macro(_) = item.node { |
759 | self.visit_invoc(item.id); | |
760 | return | |
761 | } | |
762 | ||
9e0c209e SL |
763 | // Add the item to the trait info. |
764 | let item_def_id = self.resolver.definitions.local_def_id(item.id); | |
32a655c1 SL |
765 | let (def, ns, has_self) = match item.node { |
766 | TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS, false), | |
767 | TraitItemKind::Method(ref sig, _) => | |
768 | (Def::Method(item_def_id), ValueNS, sig.decl.has_self()), | |
769 | TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS, false), | |
c30ab7b3 | 770 | TraitItemKind::Macro(_) => bug!(), // handled above |
9e0c209e SL |
771 | }; |
772 | ||
32a655c1 | 773 | self.resolver.trait_item_map.insert((def_id, item.ident.name, ns), (def, has_self)); |
9e0c209e SL |
774 | |
775 | let vis = ty::Visibility::Public; | |
32a655c1 | 776 | self.resolver.define(parent, item.ident, ns, (def, vis, item.span, self.expansion)); |
9e0c209e SL |
777 | |
778 | self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor | |
779 | visit::walk_trait_item(self, item); | |
780 | self.resolver.current_module = parent; | |
1a4d82fc JJ |
781 | } |
782 | } |