]>
Commit | Line | Data |
---|---|---|
c34b1796 AL |
1 | // Copyright 2015 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 | use self::ImportDirectiveSubclass::*; | |
12 | ||
94b46f34 | 13 | use {AmbiguityError, CrateLint, Module, PerNS}; |
476ff2be | 14 | use Namespace::{self, TypeNS, MacroNS}; |
ff7c6d11 | 15 | use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; |
c34b1796 | 16 | use Resolver; |
c34b1796 | 17 | use {names_to_string, module_to_string}; |
c1a9b12d | 18 | use {resolve_error, ResolutionError}; |
c34b1796 | 19 | |
a7813a04 | 20 | use rustc::ty; |
94b46f34 XL |
21 | use rustc::lint::builtin::BuiltinLintDiagnostics; |
22 | use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE}; | |
ff7c6d11 | 23 | use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; |
54a0048b | 24 | use rustc::hir::def::*; |
ff7c6d11 | 25 | use rustc::session::DiagnosticMessageId; |
3b2f2976 | 26 | use rustc::util::nodemap::{FxHashMap, FxHashSet}; |
c34b1796 | 27 | |
94b46f34 | 28 | use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID}; |
c30ab7b3 | 29 | use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; |
476ff2be SL |
30 | use syntax::ext::hygiene::Mark; |
31 | use syntax::symbol::keywords; | |
9cc50fc6 | 32 | use syntax::util::lev_distance::find_best_match_for_name; |
9e0c209e | 33 | use syntax_pos::Span; |
c34b1796 | 34 | |
54a0048b | 35 | use std::cell::{Cell, RefCell}; |
83c7162d | 36 | use std::{mem, ptr}; |
3157f602 | 37 | |
c34b1796 | 38 | /// Contains data for specific types of import directives. |
54a0048b | 39 | #[derive(Clone, Debug)] |
9e0c209e | 40 | pub enum ImportDirectiveSubclass<'a> { |
54a0048b | 41 | SingleImport { |
32a655c1 SL |
42 | target: Ident, |
43 | source: Ident, | |
476ff2be | 44 | result: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>, |
32a655c1 | 45 | type_ns_only: bool, |
9e0c209e SL |
46 | }, |
47 | GlobImport { | |
48 | is_prelude: bool, | |
2c00a5a8 XL |
49 | max_vis: Cell<ty::Visibility>, // The visibility of the greatest re-export. |
50 | // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors. | |
54a0048b | 51 | }, |
abe05a73 | 52 | ExternCrate(Option<Name>), |
32a655c1 | 53 | MacroUse, |
c34b1796 AL |
54 | } |
55 | ||
56 | /// One import directive. | |
7453a54e | 57 | #[derive(Debug,Clone)] |
54a0048b | 58 | pub struct ImportDirective<'a> { |
94b46f34 XL |
59 | /// The id of the `extern crate`, `UseTree` etc that imported this `ImportDirective`. |
60 | /// | |
61 | /// In the case where the `ImportDirective` was expanded from a "nested" use tree, | |
62 | /// this id is the id of the leaf tree. For example: | |
63 | /// | |
64 | /// ```ignore (pacify the mercilous tidy) | |
65 | /// use foo::bar::{a, b} | |
66 | /// ``` | |
67 | /// | |
68 | /// If this is the import directive for `foo::bar::a`, we would have the id of the `UseTree` | |
69 | /// for `a` in this field. | |
a7813a04 | 70 | pub id: NodeId, |
94b46f34 XL |
71 | |
72 | /// The `id` of the "root" use-kind -- this is always the same as | |
73 | /// `id` except in the case of "nested" use trees, in which case | |
74 | /// it will be the `id` of the root use tree. e.g., in the example | |
75 | /// from `id`, this would be the id of the `use foo::bar` | |
76 | /// `UseTree` node. | |
77 | pub root_id: NodeId, | |
78 | ||
79 | /// Span of this use tree. | |
80 | pub span: Span, | |
81 | ||
82 | /// Span of the *root* use tree (see `root_id`). | |
83 | pub root_span: Span, | |
84 | ||
476ff2be | 85 | pub parent: Module<'a>, |
83c7162d | 86 | pub module_path: Vec<Ident>, |
476ff2be SL |
87 | pub imported_module: Cell<Option<Module<'a>>>, // the resolution of `module_path` |
88 | pub subclass: ImportDirectiveSubclass<'a>, | |
476ff2be SL |
89 | pub vis: Cell<ty::Visibility>, |
90 | pub expansion: Mark, | |
32a655c1 | 91 | pub used: Cell<bool>, |
c34b1796 AL |
92 | } |
93 | ||
54a0048b | 94 | impl<'a> ImportDirective<'a> { |
a7813a04 XL |
95 | pub fn is_glob(&self) -> bool { |
96 | match self.subclass { ImportDirectiveSubclass::GlobImport { .. } => true, _ => false } | |
97 | } | |
94b46f34 XL |
98 | |
99 | crate fn crate_lint(&self) -> CrateLint { | |
100 | CrateLint::UsePath { root_id: self.root_id, root_span: self.root_span } | |
101 | } | |
c34b1796 AL |
102 | } |
103 | ||
ff7c6d11 | 104 | #[derive(Clone, Default, Debug)] |
54a0048b | 105 | /// Records information about the resolution of a name in a namespace of a module. |
7453a54e | 106 | pub struct NameResolution<'a> { |
54a0048b SL |
107 | /// The single imports that define the name in the namespace. |
108 | single_imports: SingleImports<'a>, | |
7453a54e SL |
109 | /// The least shadowable known binding for this name, or None if there are no known bindings. |
110 | pub binding: Option<&'a NameBinding<'a>>, | |
476ff2be | 111 | shadows_glob: Option<&'a NameBinding<'a>>, |
54a0048b SL |
112 | } |
113 | ||
114 | #[derive(Clone, Debug)] | |
115 | enum SingleImports<'a> { | |
116 | /// No single imports can define the name in the namespace. | |
117 | None, | |
118 | /// Only the given single import can define the name in the namespace. | |
119 | MaybeOne(&'a ImportDirective<'a>), | |
83c7162d XL |
120 | /// Only one of these two single imports can define the name in the namespace. |
121 | MaybeTwo(&'a ImportDirective<'a>, &'a ImportDirective<'a>), | |
54a0048b SL |
122 | /// At least one single import will define the name in the namespace. |
123 | AtLeastOne, | |
124 | } | |
125 | ||
126 | impl<'a> Default for SingleImports<'a> { | |
9e0c209e | 127 | /// Creates a `SingleImports<'a>` of None type. |
54a0048b SL |
128 | fn default() -> Self { |
129 | SingleImports::None | |
130 | } | |
131 | } | |
132 | ||
133 | impl<'a> SingleImports<'a> { | |
83c7162d | 134 | fn add_directive(&mut self, directive: &'a ImportDirective<'a>, use_extern_macros: bool) { |
54a0048b SL |
135 | match *self { |
136 | SingleImports::None => *self = SingleImports::MaybeOne(directive), | |
83c7162d XL |
137 | SingleImports::MaybeOne(directive_one) => *self = if use_extern_macros { |
138 | SingleImports::MaybeTwo(directive_one, directive) | |
139 | } else { | |
140 | SingleImports::AtLeastOne | |
141 | }, | |
142 | // If three single imports can define the name in the namespace, we can assume that at | |
143 | // least one of them will define it since otherwise we'd get duplicate errors in one of | |
144 | // other namespaces. | |
145 | SingleImports::MaybeTwo(..) => *self = SingleImports::AtLeastOne, | |
54a0048b SL |
146 | SingleImports::AtLeastOne => {} |
147 | }; | |
148 | } | |
149 | ||
83c7162d | 150 | fn directive_failed(&mut self, dir: &'a ImportDirective<'a>) { |
54a0048b SL |
151 | match *self { |
152 | SingleImports::None => unreachable!(), | |
153 | SingleImports::MaybeOne(_) => *self = SingleImports::None, | |
83c7162d XL |
154 | SingleImports::MaybeTwo(dir1, dir2) => |
155 | *self = SingleImports::MaybeOne(if ptr::eq(dir1, dir) { dir1 } else { dir2 }), | |
54a0048b SL |
156 | SingleImports::AtLeastOne => {} |
157 | } | |
158 | } | |
9cc50fc6 SL |
159 | } |
160 | ||
7453a54e | 161 | impl<'a> NameResolution<'a> { |
54a0048b SL |
162 | // Returns the binding for the name if it is known or None if it not known. |
163 | fn binding(&self) -> Option<&'a NameBinding<'a>> { | |
164 | self.binding.and_then(|binding| match self.single_imports { | |
165 | SingleImports::None => Some(binding), | |
a7813a04 | 166 | _ if !binding.is_glob_import() => Some(binding), |
54a0048b SL |
167 | _ => None, // The binding could be shadowed by a single import, so it is not known. |
168 | }) | |
169 | } | |
9e0c209e SL |
170 | } |
171 | ||
172 | impl<'a> Resolver<'a> { | |
32a655c1 | 173 | fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace) |
9e0c209e | 174 | -> &'a RefCell<NameResolution<'a>> { |
7cac9316 | 175 | *module.resolutions.borrow_mut().entry((ident.modern(), ns)) |
9e0c209e SL |
176 | .or_insert_with(|| self.arenas.alloc_name_resolution()) |
177 | } | |
178 | ||
32a655c1 | 179 | /// Attempts to resolve `ident` in namespaces `ns` of `module`. |
9e0c209e | 180 | /// Invariant: if `record_used` is `Some`, import resolution must be complete. |
7cac9316 XL |
181 | pub fn resolve_ident_in_module_unadjusted(&mut self, |
182 | module: Module<'a>, | |
183 | ident: Ident, | |
184 | ns: Namespace, | |
185 | restricted_shadowing: bool, | |
186 | record_used: bool, | |
187 | path_span: Span) | |
188 | -> Result<&'a NameBinding<'a>, Determinacy> { | |
9e0c209e SL |
189 | self.populate_module_if_necessary(module); |
190 | ||
32a655c1 | 191 | let resolution = self.resolution(module, ident, ns) |
476ff2be SL |
192 | .try_borrow_mut() |
193 | .map_err(|_| Determined)?; // This happens when there is a cycle of imports | |
9e0c209e | 194 | |
7cac9316 | 195 | if record_used { |
9e0c209e | 196 | if let Some(binding) = resolution.binding { |
476ff2be | 197 | if let Some(shadowed_glob) = resolution.shadows_glob { |
32a655c1 | 198 | let name = ident.name; |
cc61c64b XL |
199 | // Forbid expanded shadowing to avoid time travel. |
200 | if restricted_shadowing && | |
476ff2be SL |
201 | binding.expansion != Mark::root() && |
202 | ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing | |
203 | binding.def() != shadowed_glob.def() { | |
204 | self.ambiguity_errors.push(AmbiguityError { | |
7cac9316 | 205 | span: path_span, |
3b2f2976 | 206 | name, |
7cac9316 XL |
207 | lexical: false, |
208 | b1: binding, | |
209 | b2: shadowed_glob, | |
476ff2be SL |
210 | }); |
211 | } | |
9e0c209e | 212 | } |
7cac9316 | 213 | if self.record_use(ident, ns, binding, path_span) { |
476ff2be | 214 | return Ok(self.dummy_binding); |
9e0c209e SL |
215 | } |
216 | if !self.is_accessible(binding.vis) { | |
7cac9316 | 217 | self.privacy_errors.push(PrivacyError(path_span, ident.name, binding)); |
9e0c209e SL |
218 | } |
219 | } | |
220 | ||
476ff2be | 221 | return resolution.binding.ok_or(Determined); |
9e0c209e SL |
222 | } |
223 | ||
476ff2be | 224 | let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { |
0531ce1d | 225 | // `extern crate` are always usable for backwards compatibility, see issue #37020. |
476ff2be SL |
226 | let usable = this.is_accessible(binding.vis) || binding.is_extern_crate(); |
227 | if usable { Ok(binding) } else { Err(Determined) } | |
228 | }; | |
9e0c209e | 229 | |
476ff2be SL |
230 | // Items and single imports are not shadowable. |
231 | if let Some(binding) = resolution.binding { | |
232 | if !binding.is_glob_import() { | |
233 | return check_usable(self, binding); | |
9e0c209e SL |
234 | } |
235 | } | |
236 | ||
54a0048b | 237 | // Check if a single import can still define the name. |
83c7162d XL |
238 | let resolve_single_import = |this: &mut Self, directive: &'a ImportDirective<'a>| { |
239 | let module = match directive.imported_module.get() { | |
240 | Some(module) => module, | |
241 | None => return false, | |
242 | }; | |
243 | let ident = match directive.subclass { | |
244 | SingleImport { source, .. } => source, | |
245 | _ => unreachable!(), | |
246 | }; | |
247 | match this.resolve_ident_in_module(module, ident, ns, false, false, path_span) { | |
248 | Err(Determined) => {} | |
249 | _ => return false, | |
250 | } | |
251 | true | |
252 | }; | |
9e0c209e | 253 | match resolution.single_imports { |
476ff2be | 254 | SingleImports::AtLeastOne => return Err(Undetermined), |
83c7162d XL |
255 | SingleImports::MaybeOne(directive) => { |
256 | let accessible = self.is_accessible(directive.vis.get()); | |
257 | if accessible { | |
258 | if !resolve_single_import(self, directive) { | |
259 | return Err(Undetermined) | |
260 | } | |
261 | } | |
262 | } | |
263 | SingleImports::MaybeTwo(directive1, directive2) => { | |
264 | let accessible1 = self.is_accessible(directive1.vis.get()); | |
265 | let accessible2 = self.is_accessible(directive2.vis.get()); | |
266 | if accessible1 && accessible2 { | |
267 | if !resolve_single_import(self, directive1) && | |
268 | !resolve_single_import(self, directive2) { | |
269 | return Err(Undetermined) | |
270 | } | |
271 | } else if accessible1 { | |
272 | if !resolve_single_import(self, directive1) { | |
273 | return Err(Undetermined) | |
274 | } | |
275 | } else { | |
276 | if !resolve_single_import(self, directive2) { | |
277 | return Err(Undetermined) | |
278 | } | |
54a0048b | 279 | } |
7453a54e | 280 | } |
83c7162d | 281 | SingleImports::None => {}, |
7453a54e | 282 | } |
c34b1796 | 283 | |
476ff2be | 284 | let no_unresolved_invocations = |
cc61c64b | 285 | restricted_shadowing || module.unresolved_invocations.borrow().is_empty(); |
476ff2be SL |
286 | match resolution.binding { |
287 | // In `MacroNS`, expanded bindings do not shadow (enforced in `try_define`). | |
288 | Some(binding) if no_unresolved_invocations || ns == MacroNS => | |
289 | return check_usable(self, binding), | |
290 | None if no_unresolved_invocations => {} | |
291 | _ => return Err(Undetermined), | |
292 | } | |
293 | ||
294 | // Check if the globs are determined | |
cc61c64b XL |
295 | if restricted_shadowing && module.def().is_some() { |
296 | return Err(Determined); | |
297 | } | |
476ff2be | 298 | for directive in module.globs.borrow().iter() { |
7cac9316 XL |
299 | if !self.is_accessible(directive.vis.get()) { |
300 | continue | |
301 | } | |
302 | let module = unwrap_or!(directive.imported_module.get(), return Err(Undetermined)); | |
303 | let (orig_current_module, mut ident) = (self.current_module, ident.modern()); | |
83c7162d | 304 | match ident.span.glob_adjust(module.expansion, directive.span.ctxt().modern()) { |
7cac9316 XL |
305 | Some(Some(def)) => self.current_module = self.macro_def_scope(def), |
306 | Some(None) => {} | |
307 | None => continue, | |
308 | }; | |
309 | let result = self.resolve_ident_in_module_unadjusted( | |
310 | module, ident, ns, false, false, path_span, | |
311 | ); | |
312 | self.current_module = orig_current_module; | |
313 | if let Err(Undetermined) = result { | |
314 | return Err(Undetermined); | |
476ff2be SL |
315 | } |
316 | } | |
317 | ||
318 | Err(Determined) | |
54a0048b SL |
319 | } |
320 | ||
9e0c209e SL |
321 | // Add an import directive to the current module. |
322 | pub fn add_import_directive(&mut self, | |
83c7162d | 323 | module_path: Vec<Ident>, |
9e0c209e | 324 | subclass: ImportDirectiveSubclass<'a>, |
54a0048b SL |
325 | span: Span, |
326 | id: NodeId, | |
94b46f34 XL |
327 | root_span: Span, |
328 | root_id: NodeId, | |
476ff2be SL |
329 | vis: ty::Visibility, |
330 | expansion: Mark) { | |
9e0c209e | 331 | let current_module = self.current_module; |
54a0048b | 332 | let directive = self.arenas.alloc_import_directive(ImportDirective { |
9e0c209e | 333 | parent: current_module, |
3b2f2976 | 334 | module_path, |
9e0c209e | 335 | imported_module: Cell::new(None), |
3b2f2976 XL |
336 | subclass, |
337 | span, | |
338 | id, | |
94b46f34 XL |
339 | root_span, |
340 | root_id, | |
9e0c209e | 341 | vis: Cell::new(vis), |
3b2f2976 | 342 | expansion, |
32a655c1 | 343 | used: Cell::new(false), |
54a0048b SL |
344 | }); |
345 | ||
9e0c209e | 346 | self.indeterminate_imports.push(directive); |
54a0048b | 347 | match directive.subclass { |
94b46f34 XL |
348 | SingleImport { target, type_ns_only, .. } => { |
349 | self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { | |
476ff2be | 350 | let mut resolution = this.resolution(current_module, target, ns).borrow_mut(); |
83c7162d | 351 | resolution.single_imports.add_directive(directive, this.use_extern_macros); |
476ff2be | 352 | }); |
7453a54e | 353 | } |
54a0048b SL |
354 | // We don't add prelude imports to the globs since they only affect lexical scopes, |
355 | // which are not relevant to import resolution. | |
9e0c209e SL |
356 | GlobImport { is_prelude: true, .. } => {} |
357 | GlobImport { .. } => self.current_module.globs.borrow_mut().push(directive), | |
476ff2be | 358 | _ => unreachable!(), |
c34b1796 | 359 | } |
54a0048b | 360 | } |
5bcae85e | 361 | |
5bcae85e SL |
362 | // Given a binding and an import directive that resolves to it, |
363 | // return the corresponding binding defined by the import directive. | |
32a655c1 SL |
364 | pub fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>) |
365 | -> &'a NameBinding<'a> { | |
9e0c209e | 366 | let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) || |
041b39d2 XL |
367 | // c.f. `PUB_USE_OF_PRIVATE_EXTERN_CRATE` |
368 | !directive.is_glob() && binding.is_extern_crate() { | |
9e0c209e SL |
369 | directive.vis.get() |
370 | } else { | |
371 | binding.pseudo_vis() | |
372 | }; | |
373 | ||
374 | if let GlobImport { ref max_vis, .. } = directive.subclass { | |
375 | if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) { | |
376 | max_vis.set(vis) | |
377 | } | |
378 | } | |
379 | ||
32a655c1 | 380 | self.arenas.alloc_name_binding(NameBinding { |
5bcae85e | 381 | kind: NameBindingKind::Import { |
3b2f2976 XL |
382 | binding, |
383 | directive, | |
9e0c209e | 384 | used: Cell::new(false), |
5bcae85e SL |
385 | }, |
386 | span: directive.span, | |
3b2f2976 | 387 | vis, |
476ff2be | 388 | expansion: directive.expansion, |
32a655c1 | 389 | }) |
5bcae85e | 390 | } |
54a0048b | 391 | |
5bcae85e | 392 | // Define the name or return the existing binding if there is a collision. |
32a655c1 SL |
393 | pub fn try_define(&mut self, |
394 | module: Module<'a>, | |
395 | ident: Ident, | |
396 | ns: Namespace, | |
397 | binding: &'a NameBinding<'a>) | |
398 | -> Result<(), &'a NameBinding<'a>> { | |
399 | self.update_resolution(module, ident, ns, |this, resolution| { | |
5bcae85e SL |
400 | if let Some(old_binding) = resolution.binding { |
401 | if binding.is_glob_import() { | |
476ff2be SL |
402 | if !old_binding.is_glob_import() && |
403 | !(ns == MacroNS && old_binding.expansion != Mark::root()) { | |
404 | resolution.shadows_glob = Some(binding); | |
9e0c209e | 405 | } else if binding.def() != old_binding.def() { |
476ff2be | 406 | resolution.binding = Some(this.ambiguity(old_binding, binding)); |
32a655c1 | 407 | } else if !old_binding.vis.is_at_least(binding.vis, &*this) { |
9e0c209e SL |
408 | // We are glob-importing the same item but with greater visibility. |
409 | resolution.binding = Some(binding); | |
410 | } | |
5bcae85e | 411 | } else if old_binding.is_glob_import() { |
476ff2be SL |
412 | if ns == MacroNS && binding.expansion != Mark::root() && |
413 | binding.def() != old_binding.def() { | |
414 | resolution.binding = Some(this.ambiguity(binding, old_binding)); | |
415 | } else { | |
416 | resolution.binding = Some(binding); | |
417 | resolution.shadows_glob = Some(old_binding); | |
418 | } | |
5bcae85e SL |
419 | } else { |
420 | return Err(old_binding); | |
421 | } | |
422 | } else { | |
423 | resolution.binding = Some(binding); | |
424 | } | |
425 | ||
426 | Ok(()) | |
427 | }) | |
428 | } | |
429 | ||
32a655c1 | 430 | pub fn ambiguity(&self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>) |
476ff2be SL |
431 | -> &'a NameBinding<'a> { |
432 | self.arenas.alloc_name_binding(NameBinding { | |
94b46f34 | 433 | kind: NameBindingKind::Ambiguity { b1, b2 }, |
476ff2be SL |
434 | vis: if b1.vis.is_at_least(b2.vis, self) { b1.vis } else { b2.vis }, |
435 | span: b1.span, | |
436 | expansion: Mark::root(), | |
437 | }) | |
438 | } | |
439 | ||
5bcae85e | 440 | // Use `f` to mutate the resolution of the name in the module. |
54a0048b | 441 | // If the resolution becomes a success, define it in the module's glob importers. |
32a655c1 SL |
442 | fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F) |
443 | -> T | |
5bcae85e | 444 | where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T |
54a0048b | 445 | { |
5bcae85e SL |
446 | // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, |
447 | // during which the resolution might end up getting re-defined via a glob cycle. | |
9e0c209e | 448 | let (binding, t) = { |
3b2f2976 | 449 | let resolution = &mut *self.resolution(module, ident, ns).borrow_mut(); |
9e0c209e | 450 | let old_binding = resolution.binding(); |
54a0048b | 451 | |
5bcae85e | 452 | let t = f(self, resolution); |
54a0048b | 453 | |
54a0048b | 454 | match resolution.binding() { |
476ff2be | 455 | _ if old_binding.is_some() => return t, |
54a0048b | 456 | None => return t, |
9e0c209e SL |
457 | Some(binding) => match old_binding { |
458 | Some(old_binding) if old_binding as *const _ == binding as *const _ => return t, | |
459 | _ => (binding, t), | |
460 | } | |
54a0048b SL |
461 | } |
462 | }; | |
c34b1796 | 463 | |
9e0c209e SL |
464 | // Define `binding` in `module`s glob importers. |
465 | for directive in module.glob_importers.borrow_mut().iter() { | |
7cac9316 | 466 | let mut ident = ident.modern(); |
83c7162d | 467 | let scope = match ident.span.reverse_glob_adjust(module.expansion, |
ea8adc8c | 468 | directive.span.ctxt().modern()) { |
7cac9316 XL |
469 | Some(Some(def)) => self.macro_def_scope(def), |
470 | Some(None) => directive.parent, | |
471 | None => continue, | |
472 | }; | |
473 | if self.is_accessible_from(binding.vis, scope) { | |
9e0c209e | 474 | let imported_binding = self.import(binding, directive); |
32a655c1 | 475 | let _ = self.try_define(directive.parent, ident, ns, imported_binding); |
5bcae85e | 476 | } |
54a0048b | 477 | } |
5bcae85e SL |
478 | |
479 | t | |
c34b1796 | 480 | } |
476ff2be SL |
481 | |
482 | // Define a "dummy" resolution containing a Def::Err as a placeholder for a | |
483 | // failed resolution | |
484 | fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) { | |
485 | if let SingleImport { target, .. } = directive.subclass { | |
486 | let dummy_binding = self.dummy_binding; | |
487 | let dummy_binding = self.import(dummy_binding, directive); | |
488 | self.per_ns(|this, ns| { | |
32a655c1 | 489 | let _ = this.try_define(directive.parent, target, ns, dummy_binding); |
476ff2be SL |
490 | }); |
491 | } | |
492 | } | |
c34b1796 AL |
493 | } |
494 | ||
476ff2be SL |
495 | pub struct ImportResolver<'a, 'b: 'a> { |
496 | pub resolver: &'a mut Resolver<'b>, | |
c34b1796 AL |
497 | } |
498 | ||
5bcae85e SL |
499 | impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> { |
500 | type Target = Resolver<'b>; | |
501 | fn deref(&self) -> &Resolver<'b> { | |
502 | self.resolver | |
503 | } | |
504 | } | |
505 | ||
506 | impl<'a, 'b: 'a> ::std::ops::DerefMut for ImportResolver<'a, 'b> { | |
507 | fn deref_mut(&mut self) -> &mut Resolver<'b> { | |
508 | self.resolver | |
509 | } | |
510 | } | |
511 | ||
32a655c1 SL |
512 | impl<'a, 'b: 'a> ty::DefIdTree for &'a ImportResolver<'a, 'b> { |
513 | fn parent(self, id: DefId) -> Option<DefId> { | |
514 | self.resolver.parent(id) | |
5bcae85e SL |
515 | } |
516 | } | |
517 | ||
a7813a04 | 518 | impl<'a, 'b:'a> ImportResolver<'a, 'b> { |
c34b1796 AL |
519 | // Import resolution |
520 | // | |
521 | // This is a fixed-point algorithm. We resolve imports until our efforts | |
522 | // are stymied by an unresolved import; then we bail out of the current | |
523 | // module and continue. We terminate successfully once no more imports | |
524 | // remain or unsuccessfully when no forward progress in resolving imports | |
525 | // is made. | |
526 | ||
527 | /// Resolves all imports for the crate. This method performs the fixed- | |
528 | /// point iteration. | |
476ff2be | 529 | pub fn resolve_imports(&mut self) { |
9e0c209e | 530 | let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1; |
9e0c209e SL |
531 | while self.indeterminate_imports.len() < prev_num_indeterminates { |
532 | prev_num_indeterminates = self.indeterminate_imports.len(); | |
476ff2be | 533 | for import in mem::replace(&mut self.indeterminate_imports, Vec::new()) { |
9e0c209e | 534 | match self.resolve_import(&import) { |
476ff2be SL |
535 | true => self.determined_imports.push(import), |
536 | false => self.indeterminate_imports.push(import), | |
a7813a04 | 537 | } |
c34b1796 | 538 | } |
9e0c209e | 539 | } |
476ff2be | 540 | } |
9e0c209e | 541 | |
476ff2be | 542 | pub fn finalize_imports(&mut self) { |
9e0c209e SL |
543 | for module in self.arenas.local_modules().iter() { |
544 | self.finalize_resolutions_in(module); | |
545 | } | |
546 | ||
547 | let mut errors = false; | |
3b2f2976 | 548 | let mut seen_spans = FxHashSet(); |
9e0c209e SL |
549 | for i in 0 .. self.determined_imports.len() { |
550 | let import = self.determined_imports[i]; | |
3b2f2976 | 551 | if let Some((span, err)) = self.finalize_import(import) { |
9e0c209e | 552 | errors = true; |
9e0c209e | 553 | |
041b39d2 XL |
554 | if let SingleImport { source, ref result, .. } = import.subclass { |
555 | if source.name == "self" { | |
556 | // Silence `unresolved import` error if E0429 is already emitted | |
557 | match result.value_ns.get() { | |
558 | Err(Determined) => continue, | |
559 | _ => {}, | |
560 | } | |
561 | } | |
562 | } | |
563 | ||
9e0c209e SL |
564 | // If the error is a single failed import then create a "fake" import |
565 | // resolution for it so that later resolve stages won't complain. | |
566 | self.import_dummy_binding(import); | |
3b2f2976 XL |
567 | if !seen_spans.contains(&span) { |
568 | let path = import_path_to_string(&import.module_path[..], | |
569 | &import.subclass, | |
570 | span); | |
571 | let error = ResolutionError::UnresolvedImport(Some((span, &path, &err))); | |
572 | resolve_error(self.resolver, span, error); | |
573 | seen_spans.insert(span); | |
574 | } | |
c34b1796 | 575 | } |
9e0c209e | 576 | } |
c34b1796 | 577 | |
9e0c209e SL |
578 | // Report unresolved imports only if no hard error was already reported |
579 | // to avoid generating multiple errors on the same import. | |
580 | if !errors { | |
581 | if let Some(import) = self.indeterminate_imports.iter().next() { | |
582 | let error = ResolutionError::UnresolvedImport(None); | |
583 | resolve_error(self.resolver, import.span, error); | |
584 | } | |
c34b1796 AL |
585 | } |
586 | } | |
587 | ||
476ff2be | 588 | /// Attempts to resolve the given import, returning true if its resolution is determined. |
c34b1796 | 589 | /// If successful, the resolved bindings are written into the module. |
476ff2be | 590 | fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool { |
c34b1796 | 591 | debug!("(resolving import for module) resolving import `{}::...` in `{}`", |
3b2f2976 | 592 | names_to_string(&directive.module_path[..]), |
2c00a5a8 | 593 | module_to_string(self.current_module).unwrap_or("???".to_string())); |
54a0048b | 594 | |
9e0c209e SL |
595 | self.current_module = directive.parent; |
596 | ||
597 | let module = if let Some(module) = directive.imported_module.get() { | |
598 | module | |
599 | } else { | |
600 | let vis = directive.vis.get(); | |
601 | // For better failure detection, pretend that the import will not define any names | |
602 | // while resolving its module path. | |
32a655c1 | 603 | directive.vis.set(ty::Visibility::Invisible); |
83c7162d | 604 | let result = self.resolve_path(&directive.module_path[..], None, false, |
94b46f34 | 605 | directive.span, directive.crate_lint()); |
9e0c209e SL |
606 | directive.vis.set(vis); |
607 | ||
608 | match result { | |
476ff2be SL |
609 | PathResult::Module(module) => module, |
610 | PathResult::Indeterminate => return false, | |
611 | _ => return true, | |
9e0c209e | 612 | } |
c34b1796 AL |
613 | }; |
614 | ||
9e0c209e | 615 | directive.imported_module.set(Some(module)); |
32a655c1 SL |
616 | let (source, target, result, type_ns_only) = match directive.subclass { |
617 | SingleImport { source, target, ref result, type_ns_only } => | |
618 | (source, target, result, type_ns_only), | |
9e0c209e SL |
619 | GlobImport { .. } => { |
620 | self.resolve_glob_import(directive); | |
476ff2be | 621 | return true; |
9e0c209e | 622 | } |
476ff2be | 623 | _ => unreachable!(), |
54a0048b | 624 | }; |
c34b1796 | 625 | |
9e0c209e | 626 | let mut indeterminate = false; |
32a655c1 | 627 | self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { |
476ff2be | 628 | if let Err(Undetermined) = result[ns].get() { |
7cac9316 XL |
629 | result[ns].set(this.resolve_ident_in_module(module, |
630 | source, | |
631 | ns, | |
632 | false, | |
633 | false, | |
634 | directive.span)); | |
9e0c209e | 635 | } else { |
476ff2be | 636 | return |
9e0c209e SL |
637 | }; |
638 | ||
32a655c1 | 639 | let parent = directive.parent; |
476ff2be | 640 | match result[ns].get() { |
9e0c209e SL |
641 | Err(Undetermined) => indeterminate = true, |
642 | Err(Determined) => { | |
32a655c1 | 643 | this.update_resolution(parent, target, ns, |_, resolution| { |
83c7162d | 644 | resolution.single_imports.directive_failed(directive) |
5bcae85e SL |
645 | }); |
646 | } | |
9e0c209e | 647 | Ok(binding) if !binding.is_importable() => { |
54a0048b | 648 | let msg = format!("`{}` is not directly importable", target); |
476ff2be | 649 | struct_span_err!(this.session, directive.span, E0253, "{}", &msg) |
7cac9316 | 650 | .span_label(directive.span, "cannot be imported directly") |
5bcae85e SL |
651 | .emit(); |
652 | // Do not import this illegal binding. Import a dummy binding and pretend | |
653 | // everything is fine | |
476ff2be | 654 | this.import_dummy_binding(directive); |
54a0048b | 655 | } |
9e0c209e | 656 | Ok(binding) => { |
476ff2be | 657 | let imported_binding = this.import(binding, directive); |
32a655c1 | 658 | let conflict = this.try_define(parent, target, ns, imported_binding); |
5bcae85e | 659 | if let Err(old_binding) = conflict { |
32a655c1 | 660 | this.report_conflict(parent, target, ns, imported_binding, old_binding); |
5bcae85e | 661 | } |
54a0048b | 662 | } |
54a0048b | 663 | } |
476ff2be | 664 | }); |
c34b1796 | 665 | |
476ff2be | 666 | !indeterminate |
9e0c209e SL |
667 | } |
668 | ||
476ff2be | 669 | // If appropriate, returns an error to report. |
3b2f2976 | 670 | fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> { |
9e0c209e | 671 | self.current_module = directive.parent; |
9e0c209e | 672 | let ImportDirective { ref module_path, span, .. } = *directive; |
94b46f34 | 673 | let mut warn_if_binding_comes_from_local_crate = false; |
ff7c6d11 | 674 | |
2c00a5a8 XL |
675 | // FIXME: Last path segment is treated specially in import resolution, so extern crate |
676 | // mode for absolute paths needs some special support for single-segment imports. | |
83c7162d XL |
677 | if module_path.len() == 1 && (module_path[0].name == keywords::CrateRoot.name() || |
678 | module_path[0].name == keywords::Extern.name()) { | |
679 | let is_extern = module_path[0].name == keywords::Extern.name() || | |
680 | (self.session.features_untracked().extern_absolute_paths && | |
681 | self.session.rust_2018()); | |
ff7c6d11 | 682 | match directive.subclass { |
2c00a5a8 | 683 | GlobImport { .. } if is_extern => { |
ff7c6d11 XL |
684 | return Some((directive.span, |
685 | "cannot glob-import all possible crates".to_string())); | |
686 | } | |
94b46f34 XL |
687 | GlobImport { .. } if self.session.features_untracked().extern_absolute_paths => { |
688 | self.lint_path_starts_with_module( | |
689 | directive.root_id, | |
690 | directive.root_span, | |
691 | ); | |
692 | } | |
ff7c6d11 | 693 | SingleImport { source, target, .. } => { |
2c00a5a8 | 694 | let crate_root = if source.name == keywords::Crate.name() && |
83c7162d | 695 | module_path[0].name != keywords::Extern.name() { |
ff7c6d11 XL |
696 | if target.name == keywords::Crate.name() { |
697 | return Some((directive.span, | |
698 | "crate root imports need to be explicitly named: \ | |
699 | `use crate as name;`".to_string())); | |
700 | } else { | |
83c7162d | 701 | Some(self.resolve_crate_root(source.span.ctxt().modern(), false)) |
ff7c6d11 | 702 | } |
94b46f34 | 703 | } else if is_extern && !source.is_path_segment_keyword() { |
ff7c6d11 | 704 | let crate_id = |
83c7162d XL |
705 | self.resolver.crate_loader.process_use_extern( |
706 | source.name, | |
707 | directive.span, | |
708 | directive.id, | |
709 | &self.resolver.definitions, | |
710 | ); | |
ff7c6d11 XL |
711 | let crate_root = |
712 | self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); | |
713 | self.populate_module_if_necessary(crate_root); | |
714 | Some(crate_root) | |
715 | } else { | |
94b46f34 | 716 | warn_if_binding_comes_from_local_crate = true; |
ff7c6d11 XL |
717 | None |
718 | }; | |
719 | ||
720 | if let Some(crate_root) = crate_root { | |
721 | let binding = (crate_root, ty::Visibility::Public, directive.span, | |
722 | directive.expansion).to_name_binding(self.arenas); | |
723 | let binding = self.arenas.alloc_name_binding(NameBinding { | |
724 | kind: NameBindingKind::Import { | |
725 | binding, | |
726 | directive, | |
727 | used: Cell::new(false), | |
ff7c6d11 XL |
728 | }, |
729 | vis: directive.vis.get(), | |
730 | span: directive.span, | |
731 | expansion: directive.expansion, | |
732 | }); | |
733 | let _ = self.try_define(directive.parent, target, TypeNS, binding); | |
734 | return None; | |
735 | } | |
736 | } | |
737 | _ => {} | |
738 | } | |
739 | } | |
740 | ||
94b46f34 XL |
741 | let module_result = self.resolve_path( |
742 | &module_path, | |
743 | None, | |
744 | true, | |
745 | span, | |
746 | directive.crate_lint(), | |
747 | ); | |
9e0c209e | 748 | let module = match module_result { |
476ff2be | 749 | PathResult::Module(module) => module, |
ff7c6d11 XL |
750 | PathResult::Failed(span, msg, false) => { |
751 | resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); | |
752 | return None; | |
753 | } | |
754 | PathResult::Failed(span, msg, true) => { | |
32a655c1 | 755 | let (mut self_path, mut self_result) = (module_path.clone(), None); |
94b46f34 XL |
756 | let is_special = |ident: Ident| ident.is_path_segment_keyword() && |
757 | ident.name != keywords::CrateRoot.name(); | |
83c7162d XL |
758 | if !self_path.is_empty() && !is_special(self_path[0]) && |
759 | !(self_path.len() > 1 && is_special(self_path[1])) { | |
760 | self_path[0].name = keywords::SelfValue.name(); | |
761 | self_result = Some(self.resolve_path(&self_path, None, false, | |
94b46f34 | 762 | span, CrateLint::No)); |
32a655c1 SL |
763 | } |
764 | return if let Some(PathResult::Module(..)) = self_result { | |
3b2f2976 | 765 | Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..])))) |
9e0c209e | 766 | } else { |
3b2f2976 | 767 | Some((span, msg)) |
9e0c209e SL |
768 | }; |
769 | }, | |
476ff2be | 770 | _ => return None, |
9e0c209e SL |
771 | }; |
772 | ||
32a655c1 SL |
773 | let (ident, result, type_ns_only) = match directive.subclass { |
774 | SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only), | |
9e0c209e SL |
775 | GlobImport { .. } if module.def_id() == directive.parent.def_id() => { |
776 | // Importing a module into itself is not allowed. | |
3b2f2976 XL |
777 | return Some((directive.span, |
778 | "Cannot glob-import a module into itself.".to_string())); | |
9e0c209e SL |
779 | } |
780 | GlobImport { is_prelude, ref max_vis } => { | |
781 | if !is_prelude && | |
32a655c1 SL |
782 | max_vis.get() != ty::Visibility::Invisible && // Allow empty globs. |
783 | !max_vis.get().is_at_least(directive.vis.get(), &*self) { | |
9e0c209e SL |
784 | let msg = "A non-empty glob must import something with the glob's visibility"; |
785 | self.session.span_err(directive.span, msg); | |
786 | } | |
476ff2be | 787 | return None; |
9e0c209e | 788 | } |
476ff2be | 789 | _ => unreachable!(), |
9e0c209e SL |
790 | }; |
791 | ||
476ff2be | 792 | let mut all_ns_err = true; |
32a655c1 | 793 | self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { |
476ff2be SL |
794 | if let Ok(binding) = result[ns].get() { |
795 | all_ns_err = false; | |
32a655c1 SL |
796 | if this.record_use(ident, ns, binding, directive.span) { |
797 | this.resolution(module, ident, ns).borrow_mut().binding = | |
476ff2be | 798 | Some(this.dummy_binding); |
9e0c209e SL |
799 | } |
800 | } | |
476ff2be | 801 | }); |
9e0c209e | 802 | |
476ff2be SL |
803 | if all_ns_err { |
804 | let mut all_ns_failed = true; | |
32a655c1 | 805 | self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { |
7cac9316 | 806 | match this.resolve_ident_in_module(module, ident, ns, false, true, span) { |
476ff2be SL |
807 | Ok(_) => all_ns_failed = false, |
808 | _ => {} | |
809 | } | |
810 | }); | |
9e0c209e | 811 | |
476ff2be | 812 | return if all_ns_failed { |
9e0c209e | 813 | let resolutions = module.resolutions.borrow(); |
32a655c1 SL |
814 | let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| { |
815 | if *i == ident { return None; } // Never suggest the same name | |
54a0048b | 816 | match *resolution.borrow() { |
8bb4bdeb XL |
817 | NameResolution { binding: Some(name_binding), .. } => { |
818 | match name_binding.kind { | |
819 | NameBindingKind::Import { binding, .. } => { | |
820 | match binding.kind { | |
821 | // Never suggest the name that has binding error | |
822 | // i.e. the name that cannot be previously resolved | |
823 | NameBindingKind::Def(Def::Err) => return None, | |
824 | _ => Some(&i.name), | |
825 | } | |
826 | }, | |
827 | _ => Some(&i.name), | |
828 | } | |
829 | }, | |
54a0048b | 830 | NameResolution { single_imports: SingleImports::None, .. } => None, |
32a655c1 | 831 | _ => Some(&i.name), |
54a0048b SL |
832 | } |
833 | }); | |
32a655c1 | 834 | let lev_suggestion = |
94b46f34 | 835 | match find_best_match_for_name(names, &ident.as_str(), None) { |
32a655c1 SL |
836 | Some(name) => format!(". Did you mean to use `{}`?", name), |
837 | None => "".to_owned(), | |
838 | }; | |
9e0c209e | 839 | let module_str = module_to_string(module); |
2c00a5a8 | 840 | let msg = if let Some(module_str) = module_str { |
32a655c1 | 841 | format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion) |
2c00a5a8 XL |
842 | } else { |
843 | format!("no `{}` in the root{}", ident, lev_suggestion) | |
a7813a04 | 844 | }; |
3b2f2976 | 845 | Some((span, msg)) |
9e0c209e | 846 | } else { |
32a655c1 | 847 | // `resolve_ident_in_module` reported a privacy error. |
9e0c209e | 848 | self.import_dummy_binding(directive); |
476ff2be | 849 | None |
7453a54e | 850 | } |
7453a54e | 851 | } |
c34b1796 | 852 | |
476ff2be SL |
853 | let mut reexport_error = None; |
854 | let mut any_successful_reexport = false; | |
855 | self.per_ns(|this, ns| { | |
856 | if let Ok(binding) = result[ns].get() { | |
9e0c209e | 857 | let vis = directive.vis.get(); |
32a655c1 | 858 | if !binding.pseudo_vis().is_at_least(vis, &*this) { |
476ff2be | 859 | reexport_error = Some((ns, binding)); |
54a0048b | 860 | } else { |
476ff2be | 861 | any_successful_reexport = true; |
c34b1796 AL |
862 | } |
863 | } | |
476ff2be | 864 | }); |
c34b1796 | 865 | |
476ff2be SL |
866 | // All namespaces must be re-exported with extra visibility for an error to occur. |
867 | if !any_successful_reexport { | |
868 | let (ns, binding) = reexport_error.unwrap(); | |
869 | if ns == TypeNS && binding.is_extern_crate() { | |
2c00a5a8 XL |
870 | let msg = format!("extern crate `{}` is private, and cannot be \ |
871 | re-exported (error E0365), consider declaring with \ | |
872 | `pub`", | |
32a655c1 | 873 | ident); |
3b2f2976 XL |
874 | self.session.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE, |
875 | directive.id, | |
876 | directive.span, | |
877 | &msg); | |
476ff2be SL |
878 | } else if ns == TypeNS { |
879 | struct_span_err!(self.session, directive.span, E0365, | |
2c00a5a8 XL |
880 | "`{}` is private, and cannot be re-exported", ident) |
881 | .span_label(directive.span, format!("re-export of private `{}`", ident)) | |
32a655c1 | 882 | .note(&format!("consider declaring type or module `{}` with `pub`", ident)) |
476ff2be SL |
883 | .emit(); |
884 | } else { | |
2c00a5a8 | 885 | let msg = format!("`{}` is private, and cannot be re-exported", ident); |
476ff2be | 886 | let note_msg = |
32a655c1 | 887 | format!("consider marking `{}` as `pub` in the imported module", ident); |
476ff2be SL |
888 | struct_span_err!(self.session, directive.span, E0364, "{}", &msg) |
889 | .span_note(directive.span, ¬e_msg) | |
890 | .emit(); | |
891 | } | |
c34b1796 AL |
892 | } |
893 | ||
94b46f34 XL |
894 | if warn_if_binding_comes_from_local_crate { |
895 | let mut warned = false; | |
896 | self.per_ns(|this, ns| { | |
897 | let binding = match result[ns].get().ok() { | |
898 | Some(b) => b, | |
899 | None => return | |
900 | }; | |
901 | if let NameBindingKind::Import { directive: d, .. } = binding.kind { | |
902 | if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass { | |
903 | return | |
904 | } | |
905 | } | |
906 | if warned { | |
907 | return | |
908 | } | |
909 | warned = true; | |
910 | this.lint_path_starts_with_module( | |
911 | directive.root_id, | |
912 | directive.root_span, | |
913 | ); | |
914 | }); | |
915 | } | |
916 | ||
c34b1796 AL |
917 | // Record what this import resolves to for later uses in documentation, |
918 | // this may resolve to either a value or a type, but for documentation | |
919 | // purposes it's good enough to just favor one over the other. | |
476ff2be | 920 | self.per_ns(|this, ns| if let Some(binding) = result[ns].get().ok() { |
94b46f34 XL |
921 | let mut import = this.import_map.entry(directive.id).or_default(); |
922 | import[ns] = Some(PathResolution::new(binding.def())); | |
476ff2be | 923 | }); |
c34b1796 AL |
924 | |
925 | debug!("(resolving single import) successfully resolved import"); | |
476ff2be | 926 | None |
c34b1796 AL |
927 | } |
928 | ||
9e0c209e SL |
929 | fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) { |
930 | let module = directive.imported_module.get().unwrap(); | |
931 | self.populate_module_if_necessary(module); | |
c34b1796 | 932 | |
9e0c209e SL |
933 | if let Some(Def::Trait(_)) = module.def() { |
934 | self.session.span_err(directive.span, "items in traits are not importable."); | |
935 | return; | |
936 | } else if module.def_id() == directive.parent.def_id() { | |
937 | return; | |
938 | } else if let GlobImport { is_prelude: true, .. } = directive.subclass { | |
939 | self.prelude = Some(module); | |
940 | return; | |
54a0048b SL |
941 | } |
942 | ||
9e0c209e SL |
943 | // Add to module's glob_importers |
944 | module.glob_importers.borrow_mut().push(directive); | |
54a0048b | 945 | |
5bcae85e | 946 | // Ensure that `resolutions` isn't borrowed during `try_define`, |
54a0048b | 947 | // since it might get updated via a glob cycle. |
32a655c1 SL |
948 | let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| { |
949 | resolution.borrow().binding().map(|binding| (ident, binding)) | |
54a0048b | 950 | }).collect::<Vec<_>>(); |
7cac9316 | 951 | for ((mut ident, ns), binding) in bindings { |
83c7162d | 952 | let scope = match ident.span.reverse_glob_adjust(module.expansion, |
ea8adc8c | 953 | directive.span.ctxt().modern()) { |
7cac9316 XL |
954 | Some(Some(def)) => self.macro_def_scope(def), |
955 | Some(None) => self.current_module, | |
956 | None => continue, | |
957 | }; | |
958 | if self.is_accessible_from(binding.pseudo_vis(), scope) { | |
5bcae85e | 959 | let imported_binding = self.import(binding, directive); |
32a655c1 | 960 | let _ = self.try_define(directive.parent, ident, ns, imported_binding); |
7453a54e | 961 | } |
54a0048b | 962 | } |
c34b1796 | 963 | |
c34b1796 | 964 | // Record the destination of this import |
32a655c1 | 965 | self.record_def(directive.id, PathResolution::new(module.def().unwrap())); |
c34b1796 AL |
966 | } |
967 | ||
2c00a5a8 | 968 | // Miscellaneous post-processing, including recording re-exports, |
7cac9316 | 969 | // reporting conflicts, and reporting unresolved imports. |
9e0c209e | 970 | fn finalize_resolutions_in(&mut self, module: Module<'b>) { |
54a0048b SL |
971 | // Since import resolution is finished, globs will not define any more names. |
972 | *module.globs.borrow_mut() = Vec::new(); | |
973 | ||
974 | let mut reexports = Vec::new(); | |
cc61c64b | 975 | let mut exported_macro_names = FxHashMap(); |
476ff2be | 976 | if module as *const _ == self.graph_root as *const _ { |
cc61c64b XL |
977 | let macro_exports = mem::replace(&mut self.macro_exports, Vec::new()); |
978 | for export in macro_exports.into_iter().rev() { | |
94b46f34 XL |
979 | if let Some(later_span) = exported_macro_names.insert(export.ident.modern(), |
980 | export.span) { | |
981 | self.session.buffer_lint_with_diagnostic( | |
982 | DUPLICATE_MACRO_EXPORTS, | |
983 | CRATE_NODE_ID, | |
984 | later_span, | |
985 | &format!("a macro named `{}` has already been exported", export.ident), | |
986 | BuiltinLintDiagnostics::DuplicatedMacroExports( | |
987 | export.ident, export.span, later_span)); | |
988 | } else { | |
476ff2be SL |
989 | reexports.push(export); |
990 | } | |
991 | } | |
992 | } | |
993 | ||
32a655c1 | 994 | for (&(ident, ns), resolution) in module.resolutions.borrow().iter() { |
476ff2be | 995 | let resolution = &mut *resolution.borrow_mut(); |
54a0048b SL |
996 | let binding = match resolution.binding { |
997 | Some(binding) => binding, | |
998 | None => continue, | |
999 | }; | |
1000 | ||
ff7c6d11 | 1001 | if binding.is_import() || binding.is_macro_def() { |
9e0c209e SL |
1002 | let def = binding.def(); |
1003 | if def != Def::Err { | |
476ff2be | 1004 | if !def.def_id().is_local() { |
ea8adc8c | 1005 | self.cstore.export_macros_untracked(def.def_id().krate); |
476ff2be | 1006 | } |
cc61c64b | 1007 | if let Def::Macro(..) = def { |
7cac9316 | 1008 | if let Some(&span) = exported_macro_names.get(&ident.modern()) { |
cc61c64b XL |
1009 | let msg = |
1010 | format!("a macro named `{}` has already been exported", ident); | |
1011 | self.session.struct_span_err(span, &msg) | |
7cac9316 | 1012 | .span_label(span, format!("`{}` already exported", ident)) |
cc61c64b XL |
1013 | .span_note(binding.span, "previous macro export here") |
1014 | .emit(); | |
1015 | } | |
1016 | } | |
ff7c6d11 XL |
1017 | reexports.push(Export { |
1018 | ident: ident.modern(), | |
1019 | def: def, | |
1020 | span: binding.span, | |
1021 | vis: binding.vis, | |
ff7c6d11 | 1022 | }); |
54a0048b SL |
1023 | } |
1024 | } | |
1025 | ||
476ff2be | 1026 | match binding.kind { |
ff7c6d11 | 1027 | NameBindingKind::Import { binding: orig_binding, directive, .. } => { |
476ff2be | 1028 | if ns == TypeNS && orig_binding.is_variant() && |
ff7c6d11 XL |
1029 | !orig_binding.vis.is_at_least(binding.vis, &*self) { |
1030 | let msg = match directive.subclass { | |
1031 | ImportDirectiveSubclass::SingleImport { .. } => { | |
2c00a5a8 | 1032 | format!("variant `{}` is private and cannot be re-exported", |
ff7c6d11 XL |
1033 | ident) |
1034 | }, | |
1035 | ImportDirectiveSubclass::GlobImport { .. } => { | |
1036 | let msg = "enum is private and its variants \ | |
2c00a5a8 | 1037 | cannot be re-exported".to_owned(); |
ff7c6d11 XL |
1038 | let error_id = (DiagnosticMessageId::ErrorId(0), // no code?! |
1039 | Some(binding.span), | |
1040 | msg.clone()); | |
1041 | let fresh = self.session.one_time_diagnostics | |
1042 | .borrow_mut().insert(error_id); | |
1043 | if !fresh { | |
1044 | continue; | |
1045 | } | |
1046 | msg | |
1047 | }, | |
1048 | ref s @ _ => bug!("unexpected import subclass {:?}", s) | |
1049 | }; | |
1050 | let mut err = self.session.struct_span_err(binding.span, &msg); | |
1051 | ||
1052 | let imported_module = directive.imported_module.get() | |
1053 | .expect("module should exist"); | |
1054 | let resolutions = imported_module.parent.expect("parent should exist") | |
1055 | .resolutions.borrow(); | |
1056 | let enum_path_segment_index = directive.module_path.len() - 1; | |
83c7162d | 1057 | let enum_ident = directive.module_path[enum_path_segment_index]; |
ff7c6d11 XL |
1058 | |
1059 | let enum_resolution = resolutions.get(&(enum_ident, TypeNS)) | |
1060 | .expect("resolution should exist"); | |
1061 | let enum_span = enum_resolution.borrow() | |
1062 | .binding.expect("binding should exist") | |
1063 | .span; | |
1064 | let enum_def_span = self.session.codemap().def_span(enum_span); | |
1065 | let enum_def_snippet = self.session.codemap() | |
1066 | .span_to_snippet(enum_def_span).expect("snippet should exist"); | |
1067 | // potentially need to strip extant `crate`/`pub(path)` for suggestion | |
1068 | let after_vis_index = enum_def_snippet.find("enum") | |
1069 | .expect("`enum` keyword should exist in snippet"); | |
1070 | let suggestion = format!("pub {}", | |
1071 | &enum_def_snippet[after_vis_index..]); | |
1072 | ||
1073 | self.session | |
1074 | .diag_span_suggestion_once(&mut err, | |
1075 | DiagnosticMessageId::ErrorId(0), | |
1076 | enum_def_span, | |
1077 | "consider making the enum public", | |
1078 | suggestion); | |
1079 | err.emit(); | |
476ff2be SL |
1080 | } |
1081 | } | |
476ff2be | 1082 | _ => {} |
c34b1796 | 1083 | } |
c34b1796 | 1084 | } |
c34b1796 | 1085 | |
54a0048b SL |
1086 | if reexports.len() > 0 { |
1087 | if let Some(def_id) = module.def_id() { | |
ea8adc8c | 1088 | self.export_map.insert(def_id, reexports); |
54a0048b | 1089 | } |
c34b1796 | 1090 | } |
c34b1796 AL |
1091 | } |
1092 | } | |
1093 | ||
83c7162d | 1094 | fn import_path_to_string(names: &[Ident], |
3b2f2976 XL |
1095 | subclass: &ImportDirectiveSubclass, |
1096 | span: Span) -> String { | |
1097 | let pos = names.iter() | |
83c7162d XL |
1098 | .position(|p| span == p.span && p.name != keywords::CrateRoot.name()); |
1099 | let global = !names.is_empty() && names[0].name == keywords::CrateRoot.name(); | |
3b2f2976 XL |
1100 | if let Some(pos) = pos { |
1101 | let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] }; | |
1102 | names_to_string(names) | |
c34b1796 | 1103 | } else { |
3b2f2976 XL |
1104 | let names = if global { &names[1..] } else { names }; |
1105 | if names.is_empty() { | |
1106 | import_directive_subclass_to_string(subclass) | |
1107 | } else { | |
0531ce1d XL |
1108 | format!("{}::{}", |
1109 | names_to_string(names), | |
1110 | import_directive_subclass_to_string(subclass)) | |
3b2f2976 | 1111 | } |
c34b1796 AL |
1112 | } |
1113 | } | |
1114 | ||
54a0048b SL |
1115 | fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass) -> String { |
1116 | match *subclass { | |
1117 | SingleImport { source, .. } => source.to_string(), | |
a7813a04 | 1118 | GlobImport { .. } => "*".to_string(), |
abe05a73 | 1119 | ExternCrate(_) => "<extern crate>".to_string(), |
32a655c1 | 1120 | MacroUse => "#[macro_use]".to_string(), |
c34b1796 AL |
1121 | } |
1122 | } |