]>
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 | ||
d9579d0f | 13 | use DefModifiers; |
c34b1796 AL |
14 | use Module; |
15 | use Namespace::{self, TypeNS, ValueNS}; | |
54a0048b | 16 | use {NameBinding, NameBindingKind, PrivacyError}; |
c34b1796 | 17 | use ResolveResult; |
7453a54e | 18 | use ResolveResult::*; |
c34b1796 | 19 | use Resolver; |
54a0048b | 20 | use UseLexicalScopeFlag::DontUseLexicalScope; |
c34b1796 | 21 | use {names_to_string, module_to_string}; |
c1a9b12d | 22 | use {resolve_error, ResolutionError}; |
c34b1796 | 23 | |
9cc50fc6 | 24 | use rustc::lint; |
54a0048b | 25 | use rustc::hir::def::*; |
c34b1796 | 26 | |
e9174d1e | 27 | use syntax::ast::{NodeId, Name}; |
c34b1796 | 28 | use syntax::attr::AttrMetaMethods; |
c34b1796 | 29 | use syntax::codemap::Span; |
9cc50fc6 | 30 | use syntax::util::lev_distance::find_best_match_for_name; |
c34b1796 AL |
31 | |
32 | use std::mem::replace; | |
54a0048b | 33 | use std::cell::{Cell, RefCell}; |
c34b1796 AL |
34 | |
35 | /// Contains data for specific types of import directives. | |
54a0048b | 36 | #[derive(Clone, Debug)] |
c34b1796 | 37 | pub enum ImportDirectiveSubclass { |
54a0048b SL |
38 | SingleImport { |
39 | target: Name, | |
40 | source: Name, | |
41 | type_determined: Cell<bool>, | |
42 | value_determined: Cell<bool>, | |
43 | }, | |
92a42be0 | 44 | GlobImport, |
c34b1796 AL |
45 | } |
46 | ||
54a0048b SL |
47 | impl ImportDirectiveSubclass { |
48 | pub fn single(target: Name, source: Name) -> Self { | |
49 | SingleImport { | |
50 | target: target, | |
51 | source: source, | |
52 | type_determined: Cell::new(false), | |
53 | value_determined: Cell::new(false), | |
54 | } | |
55 | } | |
c34b1796 AL |
56 | } |
57 | ||
58 | /// One import directive. | |
7453a54e | 59 | #[derive(Debug,Clone)] |
54a0048b SL |
60 | pub struct ImportDirective<'a> { |
61 | module_path: Vec<Name>, | |
62 | target_module: Cell<Option<Module<'a>>>, // the resolution of `module_path` | |
63 | subclass: ImportDirectiveSubclass, | |
64 | span: Span, | |
65 | id: NodeId, | |
66 | is_public: bool, // see note in ImportResolutionPerNamespace about how to use this | |
67 | is_prelude: bool, | |
c34b1796 AL |
68 | } |
69 | ||
54a0048b | 70 | impl<'a> ImportDirective<'a> { |
7453a54e SL |
71 | // Given the binding to which this directive resolves in a particular namespace, |
72 | // this returns the binding for the name this directive defines in that namespace. | |
54a0048b SL |
73 | fn import(&self, binding: &'a NameBinding<'a>, privacy_error: Option<Box<PrivacyError<'a>>>) |
74 | -> NameBinding<'a> { | |
7453a54e SL |
75 | let mut modifiers = match self.is_public { |
76 | true => DefModifiers::PUBLIC | DefModifiers::IMPORTABLE, | |
77 | false => DefModifiers::empty(), | |
78 | }; | |
79 | if let GlobImport = self.subclass { | |
80 | modifiers = modifiers | DefModifiers::GLOB_IMPORTED; | |
81 | } | |
c34b1796 | 82 | |
7453a54e | 83 | NameBinding { |
54a0048b SL |
84 | kind: NameBindingKind::Import { |
85 | binding: binding, | |
86 | id: self.id, | |
87 | privacy_error: privacy_error, | |
88 | }, | |
7453a54e SL |
89 | span: Some(self.span), |
90 | modifiers: modifiers, | |
c34b1796 AL |
91 | } |
92 | } | |
93 | } | |
94 | ||
7453a54e | 95 | #[derive(Clone, Default)] |
54a0048b | 96 | /// Records information about the resolution of a name in a namespace of a module. |
7453a54e | 97 | pub struct NameResolution<'a> { |
54a0048b SL |
98 | /// The single imports that define the name in the namespace. |
99 | single_imports: SingleImports<'a>, | |
7453a54e SL |
100 | /// The least shadowable known binding for this name, or None if there are no known bindings. |
101 | pub binding: Option<&'a NameBinding<'a>>, | |
54a0048b SL |
102 | duplicate_globs: Vec<&'a NameBinding<'a>>, |
103 | } | |
104 | ||
105 | #[derive(Clone, Debug)] | |
106 | enum SingleImports<'a> { | |
107 | /// No single imports can define the name in the namespace. | |
108 | None, | |
109 | /// Only the given single import can define the name in the namespace. | |
110 | MaybeOne(&'a ImportDirective<'a>), | |
111 | /// At least one single import will define the name in the namespace. | |
112 | AtLeastOne, | |
113 | } | |
114 | ||
115 | impl<'a> Default for SingleImports<'a> { | |
116 | fn default() -> Self { | |
117 | SingleImports::None | |
118 | } | |
119 | } | |
120 | ||
121 | impl<'a> SingleImports<'a> { | |
122 | fn add_directive(&mut self, directive: &'a ImportDirective<'a>) { | |
123 | match *self { | |
124 | SingleImports::None => *self = SingleImports::MaybeOne(directive), | |
125 | // If two single imports can define the name in the namespace, we can assume that at | |
126 | // least one of them will define it since otherwise both would have to define only one | |
127 | // namespace, leading to a duplicate error. | |
128 | SingleImports::MaybeOne(_) => *self = SingleImports::AtLeastOne, | |
129 | SingleImports::AtLeastOne => {} | |
130 | }; | |
131 | } | |
132 | ||
133 | fn directive_failed(&mut self) { | |
134 | match *self { | |
135 | SingleImports::None => unreachable!(), | |
136 | SingleImports::MaybeOne(_) => *self = SingleImports::None, | |
137 | SingleImports::AtLeastOne => {} | |
138 | } | |
139 | } | |
9cc50fc6 SL |
140 | } |
141 | ||
7453a54e | 142 | impl<'a> NameResolution<'a> { |
54a0048b SL |
143 | fn try_define(&mut self, binding: &'a NameBinding<'a>) -> Result<(), &'a NameBinding<'a>> { |
144 | if let Some(old_binding) = self.binding { | |
145 | if binding.defined_with(DefModifiers::GLOB_IMPORTED) { | |
146 | self.duplicate_globs.push(binding); | |
147 | } else if old_binding.defined_with(DefModifiers::GLOB_IMPORTED) { | |
148 | self.duplicate_globs.push(old_binding); | |
149 | self.binding = Some(binding); | |
150 | } else { | |
151 | return Err(old_binding); | |
152 | } | |
153 | } else { | |
154 | self.binding = Some(binding); | |
7453a54e | 155 | } |
c34b1796 | 156 | |
54a0048b SL |
157 | Ok(()) |
158 | } | |
159 | ||
160 | // Returns the binding for the name if it is known or None if it not known. | |
161 | fn binding(&self) -> Option<&'a NameBinding<'a>> { | |
162 | self.binding.and_then(|binding| match self.single_imports { | |
163 | SingleImports::None => Some(binding), | |
164 | _ if !binding.defined_with(DefModifiers::GLOB_IMPORTED) => Some(binding), | |
165 | _ => None, // The binding could be shadowed by a single import, so it is not known. | |
166 | }) | |
167 | } | |
168 | ||
169 | // Returns Some(the resolution of the name), or None if the resolution depends | |
170 | // on whether more globs can define the name. | |
171 | fn try_result(&self, ns: Namespace, allow_private_imports: bool) | |
172 | -> Option<ResolveResult<&'a NameBinding<'a>>> { | |
173 | match self.binding { | |
174 | Some(binding) if !binding.defined_with(DefModifiers::GLOB_IMPORTED) => | |
175 | return Some(Success(binding)), | |
176 | _ => {} // Items and single imports are not shadowable | |
177 | }; | |
178 | ||
179 | // Check if a single import can still define the name. | |
180 | match self.single_imports { | |
181 | SingleImports::None => {}, | |
182 | SingleImports::AtLeastOne => return Some(Indeterminate), | |
183 | SingleImports::MaybeOne(directive) => { | |
184 | // If (1) we don't allow private imports, (2) no public single import can define | |
185 | // the name, and (3) no public glob has defined the name, the resolution depends | |
186 | // on whether more globs can define the name. | |
187 | if !allow_private_imports && !directive.is_public && | |
188 | !self.binding.map(NameBinding::is_public).unwrap_or(false) { | |
189 | return None; | |
190 | } | |
191 | ||
192 | let target_module = match directive.target_module.get() { | |
193 | Some(target_module) => target_module, | |
194 | None => return Some(Indeterminate), | |
195 | }; | |
196 | let name = match directive.subclass { | |
197 | SingleImport { source, .. } => source, | |
198 | GlobImport => unreachable!(), | |
199 | }; | |
200 | match target_module.resolve_name(name, ns, false) { | |
201 | Failed(_) => {} | |
202 | _ => return Some(Indeterminate), | |
203 | } | |
7453a54e SL |
204 | } |
205 | } | |
c34b1796 | 206 | |
54a0048b | 207 | self.binding.map(Success) |
c34b1796 AL |
208 | } |
209 | ||
54a0048b SL |
210 | fn report_conflicts<F: FnMut(&NameBinding, &NameBinding)>(&self, mut report: F) { |
211 | let binding = match self.binding { | |
212 | Some(binding) => binding, | |
213 | None => return, | |
214 | }; | |
215 | ||
216 | for duplicate_glob in self.duplicate_globs.iter() { | |
217 | // FIXME #31337: We currently allow items to shadow glob-imported re-exports. | |
218 | if !binding.is_import() { | |
219 | if let NameBindingKind::Import { binding, .. } = duplicate_glob.kind { | |
220 | if binding.is_import() { continue } | |
221 | } | |
222 | } | |
223 | ||
224 | report(duplicate_glob, binding); | |
225 | } | |
226 | } | |
227 | } | |
228 | ||
229 | impl<'a> ::ModuleS<'a> { | |
230 | fn resolution(&self, name: Name, ns: Namespace) -> &'a RefCell<NameResolution<'a>> { | |
231 | *self.resolutions.borrow_mut().entry((name, ns)) | |
232 | .or_insert_with(|| self.arenas.alloc_name_resolution()) | |
233 | } | |
234 | ||
235 | pub fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool) | |
236 | -> ResolveResult<&'a NameBinding<'a>> { | |
237 | let resolution = self.resolution(name, ns); | |
238 | let resolution = match resolution.borrow_state() { | |
239 | ::std::cell::BorrowState::Unused => resolution.borrow_mut(), | |
240 | _ => return Failed(None), // This happens when there is a cycle of imports | |
7453a54e | 241 | }; |
c34b1796 | 242 | |
54a0048b SL |
243 | if let Some(result) = resolution.try_result(ns, allow_private_imports) { |
244 | // If the resolution doesn't depend on glob definability, check privacy and return. | |
245 | return result.and_then(|binding| { | |
246 | let allowed = allow_private_imports || !binding.is_import() || binding.is_public(); | |
247 | if allowed { Success(binding) } else { Failed(None) } | |
248 | }); | |
249 | } | |
250 | ||
251 | // Check if the globs are determined | |
252 | for directive in self.globs.borrow().iter() { | |
253 | if !allow_private_imports && !directive.is_public { continue } | |
254 | match directive.target_module.get() { | |
255 | None => return Indeterminate, | |
256 | Some(target_module) => match target_module.resolve_name(name, ns, false) { | |
257 | Indeterminate => return Indeterminate, | |
258 | _ => {} | |
259 | } | |
260 | } | |
261 | } | |
262 | ||
263 | Failed(None) | |
264 | } | |
265 | ||
266 | // Invariant: this may not be called until import resolution is complete. | |
267 | pub fn resolve_name_in_lexical_scope(&self, name: Name, ns: Namespace) | |
268 | -> Option<&'a NameBinding<'a>> { | |
269 | self.resolution(name, ns).borrow().binding | |
270 | .or_else(|| self.prelude.borrow().and_then(|prelude| { | |
271 | prelude.resolve_name(name, ns, false).success() | |
272 | })) | |
273 | } | |
274 | ||
275 | // Define the name or return the existing binding if there is a collision. | |
276 | pub fn try_define_child(&self, name: Name, ns: Namespace, binding: NameBinding<'a>) | |
277 | -> Result<(), &'a NameBinding<'a>> { | |
278 | self.update_resolution(name, ns, |resolution| { | |
279 | resolution.try_define(self.arenas.alloc_name_binding(binding)) | |
280 | }) | |
281 | } | |
282 | ||
283 | pub fn add_import_directive(&self, | |
284 | module_path: Vec<Name>, | |
285 | subclass: ImportDirectiveSubclass, | |
286 | span: Span, | |
287 | id: NodeId, | |
288 | is_public: bool, | |
289 | is_prelude: bool) { | |
290 | let directive = self.arenas.alloc_import_directive(ImportDirective { | |
291 | module_path: module_path, | |
292 | target_module: Cell::new(None), | |
293 | subclass: subclass, | |
294 | span: span, | |
295 | id: id, | |
296 | is_public: is_public, | |
297 | is_prelude: is_prelude, | |
298 | }); | |
299 | ||
300 | self.unresolved_imports.borrow_mut().push(directive); | |
301 | match directive.subclass { | |
302 | SingleImport { target, .. } => { | |
303 | for &ns in &[ValueNS, TypeNS] { | |
304 | self.resolution(target, ns).borrow_mut().single_imports | |
305 | .add_directive(directive); | |
306 | } | |
7453a54e | 307 | } |
54a0048b SL |
308 | // We don't add prelude imports to the globs since they only affect lexical scopes, |
309 | // which are not relevant to import resolution. | |
310 | GlobImport if directive.is_prelude => {} | |
311 | GlobImport => self.globs.borrow_mut().push(directive), | |
c34b1796 | 312 | } |
54a0048b SL |
313 | } |
314 | ||
315 | // Use `update` to mutate the resolution for the name. | |
316 | // If the resolution becomes a success, define it in the module's glob importers. | |
317 | fn update_resolution<T, F>(&self, name: Name, ns: Namespace, update: F) -> T | |
318 | where F: FnOnce(&mut NameResolution<'a>) -> T | |
319 | { | |
320 | // Ensure that `resolution` isn't borrowed during `define_in_glob_importers`, | |
321 | // where it might end up getting re-defined via a glob cycle. | |
322 | let (new_binding, t) = { | |
323 | let mut resolution = &mut *self.resolution(name, ns).borrow_mut(); | |
324 | let was_known = resolution.binding().is_some(); | |
325 | ||
326 | let t = update(resolution); | |
327 | ||
328 | if was_known { return t; } | |
329 | match resolution.binding() { | |
330 | Some(binding) => (binding, t), | |
331 | None => return t, | |
332 | } | |
333 | }; | |
c34b1796 | 334 | |
54a0048b SL |
335 | self.define_in_glob_importers(name, ns, new_binding); |
336 | t | |
337 | } | |
338 | ||
339 | fn define_in_glob_importers(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) { | |
340 | if !binding.defined_with(DefModifiers::PUBLIC | DefModifiers::IMPORTABLE) { return } | |
341 | for &(importer, directive) in self.glob_importers.borrow_mut().iter() { | |
342 | let _ = importer.try_define_child(name, ns, directive.import(binding, None)); | |
343 | } | |
c34b1796 AL |
344 | } |
345 | } | |
346 | ||
7453a54e SL |
347 | struct ImportResolvingError<'a> { |
348 | /// Module where the error happened | |
349 | source_module: Module<'a>, | |
54a0048b | 350 | import_directive: &'a ImportDirective<'a>, |
e9174d1e | 351 | span: Span, |
e9174d1e SL |
352 | help: String, |
353 | } | |
c34b1796 | 354 | |
92a42be0 SL |
355 | struct ImportResolver<'a, 'b: 'a, 'tcx: 'b> { |
356 | resolver: &'a mut Resolver<'b, 'tcx>, | |
c34b1796 AL |
357 | } |
358 | ||
359 | impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { | |
360 | // Import resolution | |
361 | // | |
362 | // This is a fixed-point algorithm. We resolve imports until our efforts | |
363 | // are stymied by an unresolved import; then we bail out of the current | |
364 | // module and continue. We terminate successfully once no more imports | |
365 | // remain or unsuccessfully when no forward progress in resolving imports | |
366 | // is made. | |
367 | ||
368 | /// Resolves all imports for the crate. This method performs the fixed- | |
369 | /// point iteration. | |
370 | fn resolve_imports(&mut self) { | |
371 | let mut i = 0; | |
372 | let mut prev_unresolved_imports = 0; | |
7453a54e SL |
373 | let mut errors = Vec::new(); |
374 | ||
c34b1796 AL |
375 | loop { |
376 | debug!("(resolving imports) iteration {}, {} imports left", | |
92a42be0 SL |
377 | i, |
378 | self.resolver.unresolved_imports); | |
c34b1796 | 379 | |
7453a54e | 380 | self.resolve_imports_for_module_subtree(self.resolver.graph_root, &mut errors); |
c34b1796 AL |
381 | |
382 | if self.resolver.unresolved_imports == 0 { | |
383 | debug!("(resolving imports) success"); | |
54a0048b | 384 | self.finalize_resolutions(self.resolver.graph_root, false); |
c34b1796 AL |
385 | break; |
386 | } | |
387 | ||
388 | if self.resolver.unresolved_imports == prev_unresolved_imports { | |
e9174d1e | 389 | // resolving failed |
54a0048b SL |
390 | // Report unresolved imports only if no hard error was already reported |
391 | // to avoid generating multiple errors on the same import. | |
392 | // Imports that are still indeterminate at this point are actually blocked | |
393 | // by errored imports, so there is no point reporting them. | |
394 | self.finalize_resolutions(self.resolver.graph_root, errors.len() == 0); | |
395 | for e in errors { | |
396 | self.import_resolving_error(e) | |
e9174d1e | 397 | } |
c34b1796 AL |
398 | break; |
399 | } | |
400 | ||
401 | i += 1; | |
402 | prev_unresolved_imports = self.resolver.unresolved_imports; | |
403 | } | |
404 | } | |
405 | ||
7453a54e SL |
406 | /// Resolves an `ImportResolvingError` into the correct enum discriminant |
407 | /// and passes that on to `resolve_error`. | |
408 | fn import_resolving_error(&self, e: ImportResolvingError<'b>) { | |
409 | // If it's a single failed import then create a "fake" import | |
410 | // resolution for it so that later resolve stages won't complain. | |
54a0048b SL |
411 | if let SingleImport { target, .. } = e.import_directive.subclass { |
412 | let dummy_binding = self.resolver.arenas.alloc_name_binding(NameBinding { | |
413 | modifiers: DefModifiers::GLOB_IMPORTED, | |
7453a54e SL |
414 | kind: NameBindingKind::Def(Def::Err), |
415 | span: None, | |
416 | }); | |
54a0048b | 417 | let dummy_binding = e.import_directive.import(dummy_binding, None); |
7453a54e | 418 | |
54a0048b | 419 | let _ = e.source_module.try_define_child(target, ValueNS, dummy_binding.clone()); |
7453a54e SL |
420 | let _ = e.source_module.try_define_child(target, TypeNS, dummy_binding); |
421 | } | |
422 | ||
423 | let path = import_path_to_string(&e.import_directive.module_path, | |
54a0048b | 424 | &e.import_directive.subclass); |
7453a54e SL |
425 | |
426 | resolve_error(self.resolver, | |
427 | e.span, | |
428 | ResolutionError::UnresolvedImport(Some((&path, &e.help)))); | |
429 | } | |
430 | ||
c34b1796 AL |
431 | /// Attempts to resolve imports for the given module and all of its |
432 | /// submodules. | |
92a42be0 | 433 | fn resolve_imports_for_module_subtree(&mut self, |
7453a54e SL |
434 | module_: Module<'b>, |
435 | errors: &mut Vec<ImportResolvingError<'b>>) { | |
c34b1796 | 436 | debug!("(resolving imports for module subtree) resolving {}", |
7453a54e | 437 | module_to_string(&module_)); |
9cc50fc6 | 438 | let orig_module = replace(&mut self.resolver.current_module, module_); |
54a0048b | 439 | self.resolve_imports_in_current_module(errors); |
c34b1796 AL |
440 | self.resolver.current_module = orig_module; |
441 | ||
7453a54e SL |
442 | for (_, child_module) in module_.module_children.borrow().iter() { |
443 | self.resolve_imports_for_module_subtree(child_module, errors); | |
c34b1796 | 444 | } |
c34b1796 AL |
445 | } |
446 | ||
447 | /// Attempts to resolve imports for the given module only. | |
54a0048b | 448 | fn resolve_imports_in_current_module(&mut self, errors: &mut Vec<ImportResolvingError<'b>>) { |
7453a54e | 449 | let mut imports = Vec::new(); |
54a0048b | 450 | let mut unresolved_imports = self.resolver.current_module.unresolved_imports.borrow_mut(); |
7453a54e SL |
451 | ::std::mem::swap(&mut imports, &mut unresolved_imports); |
452 | ||
453 | for import_directive in imports { | |
54a0048b | 454 | match self.resolve_import(&import_directive) { |
7453a54e | 455 | Failed(err) => { |
c34b1796 AL |
456 | let (span, help) = match err { |
457 | Some((span, msg)) => (span, format!(". {}", msg)), | |
92a42be0 | 458 | None => (import_directive.span, String::new()), |
c34b1796 | 459 | }; |
e9174d1e | 460 | errors.push(ImportResolvingError { |
54a0048b | 461 | source_module: self.resolver.current_module, |
7453a54e | 462 | import_directive: import_directive, |
92a42be0 | 463 | span: span, |
92a42be0 SL |
464 | help: help, |
465 | }); | |
e9174d1e | 466 | } |
7453a54e | 467 | Indeterminate => unresolved_imports.push(import_directive), |
54a0048b SL |
468 | Success(()) => { |
469 | // Decrement the count of unresolved imports. | |
470 | assert!(self.resolver.unresolved_imports >= 1); | |
471 | self.resolver.unresolved_imports -= 1; | |
472 | } | |
c34b1796 | 473 | } |
c34b1796 AL |
474 | } |
475 | } | |
476 | ||
477 | /// Attempts to resolve the given import. The return value indicates | |
478 | /// failure if we're certain the name does not exist, indeterminate if we | |
479 | /// don't know whether the name exists at the moment due to other | |
480 | /// currently-unresolved imports, or success if we know the name exists. | |
481 | /// If successful, the resolved bindings are written into the module. | |
54a0048b | 482 | fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResult<()> { |
c34b1796 | 483 | debug!("(resolving import for module) resolving import `{}::...` in `{}`", |
54a0048b SL |
484 | names_to_string(&directive.module_path), |
485 | module_to_string(self.resolver.current_module)); | |
486 | ||
487 | let target_module = match directive.target_module.get() { | |
488 | Some(module) => module, | |
489 | _ => match self.resolver.resolve_module_path(&directive.module_path, | |
490 | DontUseLexicalScope, | |
491 | directive.span) { | |
492 | Success(module) => module, | |
493 | Indeterminate => return Indeterminate, | |
494 | Failed(err) => return Failed(err), | |
495 | }, | |
c34b1796 AL |
496 | }; |
497 | ||
54a0048b SL |
498 | directive.target_module.set(Some(target_module)); |
499 | let (source, target, value_determined, type_determined) = match directive.subclass { | |
500 | SingleImport { source, target, ref value_determined, ref type_determined } => | |
501 | (source, target, value_determined, type_determined), | |
502 | GlobImport => return self.resolve_glob_import(target_module, directive), | |
503 | }; | |
c34b1796 | 504 | |
7453a54e SL |
505 | // We need to resolve both namespaces for this to succeed. |
506 | let value_result = | |
507 | self.resolver.resolve_name_in_module(target_module, source, ValueNS, false, true); | |
508 | let type_result = | |
509 | self.resolver.resolve_name_in_module(target_module, source, TypeNS, false, true); | |
510 | ||
54a0048b SL |
511 | let module_ = self.resolver.current_module; |
512 | for &(ns, result, determined) in &[(ValueNS, &value_result, value_determined), | |
513 | (TypeNS, &type_result, type_determined)] { | |
514 | if determined.get() { continue } | |
515 | if let Indeterminate = *result { continue } | |
516 | ||
517 | determined.set(true); | |
518 | if let Success(binding) = *result { | |
519 | if !binding.defined_with(DefModifiers::IMPORTABLE) { | |
520 | let msg = format!("`{}` is not directly importable", target); | |
521 | span_err!(self.resolver.session, directive.span, E0253, "{}", &msg); | |
522 | } | |
523 | ||
524 | let privacy_error = if !self.resolver.is_visible(binding, target_module) { | |
525 | Some(Box::new(PrivacyError(directive.span, source, binding))) | |
526 | } else { | |
527 | None | |
528 | }; | |
529 | ||
530 | let imported_binding = directive.import(binding, privacy_error); | |
531 | let conflict = module_.try_define_child(target, ns, imported_binding); | |
532 | if let Err(old_binding) = conflict { | |
533 | let binding = &directive.import(binding, None); | |
534 | self.resolver.report_conflict(module_, target, ns, binding, old_binding); | |
535 | } | |
536 | } else { | |
537 | module_.update_resolution(target, ns, |resolution| { | |
538 | resolution.single_imports.directive_failed(); | |
539 | }); | |
540 | } | |
7453a54e | 541 | } |
c34b1796 | 542 | |
7453a54e SL |
543 | match (&value_result, &type_result) { |
544 | (&Indeterminate, _) | (_, &Indeterminate) => return Indeterminate, | |
545 | (&Failed(_), &Failed(_)) => { | |
54a0048b SL |
546 | let resolutions = target_module.resolutions.borrow(); |
547 | let names = resolutions.iter().filter_map(|(&(ref name, _), resolution)| { | |
548 | match *resolution.borrow() { | |
549 | NameResolution { binding: Some(_), .. } => Some(name), | |
550 | NameResolution { single_imports: SingleImports::None, .. } => None, | |
551 | _ => Some(name), | |
552 | } | |
553 | }); | |
7453a54e SL |
554 | let lev_suggestion = match find_best_match_for_name(names, &source.as_str(), None) { |
555 | Some(name) => format!(". Did you mean to use `{}`?", name), | |
556 | None => "".to_owned(), | |
557 | }; | |
558 | let msg = format!("There is no `{}` in `{}`{}", | |
559 | source, | |
560 | module_to_string(target_module), lev_suggestion); | |
561 | return Failed(Some((directive.span, msg))); | |
562 | } | |
563 | _ => (), | |
564 | } | |
c34b1796 | 565 | |
7453a54e SL |
566 | match (&value_result, &type_result) { |
567 | (&Success(name_binding), _) if !name_binding.is_import() && | |
568 | directive.is_public && | |
569 | !name_binding.is_public() => { | |
570 | let msg = format!("`{}` is private, and cannot be reexported", source); | |
571 | let note_msg = format!("consider marking `{}` as `pub` in the imported module", | |
572 | source); | |
573 | struct_span_err!(self.resolver.session, directive.span, E0364, "{}", &msg) | |
574 | .span_note(directive.span, ¬e_msg) | |
575 | .emit(); | |
c34b1796 | 576 | } |
7453a54e | 577 | |
54a0048b SL |
578 | (_, &Success(name_binding)) if !name_binding.is_import() && |
579 | directive.is_public && | |
580 | !name_binding.is_public() => { | |
581 | if name_binding.is_extern_crate() { | |
582 | let msg = format!("extern crate `{}` is private, and cannot be reexported \ | |
583 | (error E0364), consider declaring with `pub`", | |
7453a54e SL |
584 | source); |
585 | self.resolver.session.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, | |
586 | directive.id, | |
587 | directive.span, | |
588 | msg); | |
54a0048b SL |
589 | } else { |
590 | let msg = format!("`{}` is private, and cannot be reexported", source); | |
591 | let note_msg = | |
592 | format!("consider declaring type or module `{}` with `pub`", source); | |
593 | struct_span_err!(self.resolver.session, directive.span, E0365, "{}", &msg) | |
594 | .span_note(directive.span, ¬e_msg) | |
595 | .emit(); | |
c34b1796 AL |
596 | } |
597 | } | |
c34b1796 | 598 | |
7453a54e | 599 | _ => {} |
c34b1796 AL |
600 | } |
601 | ||
54a0048b SL |
602 | // Report a privacy error here if all successful namespaces are privacy errors. |
603 | let mut privacy_error = None; | |
604 | for &ns in &[ValueNS, TypeNS] { | |
605 | privacy_error = match module_.resolve_name(target, ns, true) { | |
606 | Success(&NameBinding { | |
607 | kind: NameBindingKind::Import { ref privacy_error, .. }, .. | |
608 | }) => privacy_error.as_ref().map(|error| (**error).clone()), | |
609 | _ => continue, | |
610 | }; | |
611 | if privacy_error.is_none() { break } | |
c34b1796 | 612 | } |
54a0048b | 613 | privacy_error.map(|error| self.resolver.privacy_errors.push(error)); |
c34b1796 AL |
614 | |
615 | // Record what this import resolves to for later uses in documentation, | |
616 | // this may resolve to either a value or a type, but for documentation | |
617 | // purposes it's good enough to just favor one over the other. | |
54a0048b SL |
618 | let def = match type_result.success().and_then(NameBinding::def) { |
619 | Some(def) => def, | |
620 | None => value_result.success().and_then(NameBinding::def).unwrap(), | |
7453a54e | 621 | }; |
54a0048b SL |
622 | let path_resolution = PathResolution { base_def: def, depth: 0 }; |
623 | self.resolver.def_map.borrow_mut().insert(directive.id, path_resolution); | |
c34b1796 AL |
624 | |
625 | debug!("(resolving single import) successfully resolved import"); | |
7453a54e | 626 | return Success(()); |
c34b1796 AL |
627 | } |
628 | ||
629 | // Resolves a glob import. Note that this function cannot fail; it either | |
630 | // succeeds or bails out (as importing * from an empty module or a module | |
631 | // that exports nothing is valid). target_module is the module we are | |
632 | // actually importing, i.e., `foo` in `use foo::*`. | |
54a0048b | 633 | fn resolve_glob_import(&mut self, target_module: Module<'b>, directive: &'b ImportDirective<'b>) |
c34b1796 | 634 | -> ResolveResult<()> { |
54a0048b SL |
635 | if let Some(Def::Trait(_)) = target_module.def { |
636 | self.resolver.session.span_err(directive.span, "items in traits are not importable."); | |
e9174d1e SL |
637 | } |
638 | ||
54a0048b | 639 | let module_ = self.resolver.current_module; |
7453a54e SL |
640 | if module_.def_id() == target_module.def_id() { |
641 | // This means we are trying to glob import a module into itself, and it is a no-go | |
642 | let msg = "Cannot glob-import a module into itself.".into(); | |
643 | return Failed(Some((directive.span, msg))); | |
c34b1796 | 644 | } |
54a0048b | 645 | self.resolver.populate_module_if_necessary(target_module); |
c34b1796 | 646 | |
54a0048b SL |
647 | if directive.is_prelude { |
648 | *module_.prelude.borrow_mut() = Some(target_module); | |
649 | return Success(()); | |
650 | } | |
651 | ||
652 | // Add to target_module's glob_importers | |
653 | target_module.glob_importers.borrow_mut().push((module_, directive)); | |
654 | ||
655 | // Ensure that `resolutions` isn't borrowed during `try_define_child`, | |
656 | // since it might get updated via a glob cycle. | |
657 | let bindings = target_module.resolutions.borrow().iter().filter_map(|(name, resolution)| { | |
658 | resolution.borrow().binding().map(|binding| (*name, binding)) | |
659 | }).collect::<Vec<_>>(); | |
660 | for ((name, ns), binding) in bindings { | |
661 | if binding.defined_with(DefModifiers::IMPORTABLE | DefModifiers::PUBLIC) { | |
662 | let _ = module_.try_define_child(name, ns, directive.import(binding, None)); | |
7453a54e | 663 | } |
54a0048b | 664 | } |
c34b1796 | 665 | |
c34b1796 | 666 | // Record the destination of this import |
92a42be0 | 667 | if let Some(did) = target_module.def_id() { |
7453a54e | 668 | self.resolver.def_map.borrow_mut().insert(directive.id, |
92a42be0 | 669 | PathResolution { |
7453a54e | 670 | base_def: Def::Mod(did), |
92a42be0 SL |
671 | depth: 0, |
672 | }); | |
c34b1796 AL |
673 | } |
674 | ||
675 | debug!("(resolving glob import) successfully resolved import"); | |
7453a54e | 676 | return Success(()); |
c34b1796 AL |
677 | } |
678 | ||
54a0048b SL |
679 | // Miscellaneous post-processing, including recording reexports, recording shadowed traits, |
680 | // reporting conflicts, reporting the PRIVATE_IN_PUBLIC lint, and reporting unresolved imports. | |
681 | fn finalize_resolutions(&mut self, module: Module<'b>, report_unresolved_imports: bool) { | |
682 | // Since import resolution is finished, globs will not define any more names. | |
683 | *module.globs.borrow_mut() = Vec::new(); | |
684 | ||
685 | let mut reexports = Vec::new(); | |
686 | for (&(name, ns), resolution) in module.resolutions.borrow().iter() { | |
687 | let resolution = resolution.borrow(); | |
688 | resolution.report_conflicts(|b1, b2| { | |
689 | self.resolver.report_conflict(module, name, ns, b1, b2) | |
690 | }); | |
691 | ||
692 | let binding = match resolution.binding { | |
693 | Some(binding) => binding, | |
694 | None => continue, | |
695 | }; | |
696 | ||
697 | if binding.is_public() && (binding.is_import() || binding.is_extern_crate()) { | |
698 | if let Some(def) = binding.def() { | |
699 | reexports.push(Export { name: name, def_id: def.def_id() }); | |
700 | } | |
701 | } | |
702 | ||
703 | if let NameBindingKind::Import { binding: orig_binding, id, .. } = binding.kind { | |
704 | if ns == TypeNS && binding.is_public() && | |
705 | orig_binding.defined_with(DefModifiers::PRIVATE_VARIANT) { | |
706 | let msg = format!("variant `{}` is private, and cannot be reexported \ | |
707 | (error E0364), consider declaring its enum as `pub`", | |
708 | name); | |
709 | let lint = lint::builtin::PRIVATE_IN_PUBLIC; | |
710 | self.resolver.session.add_lint(lint, id, binding.span.unwrap(), msg); | |
711 | } | |
c34b1796 | 712 | } |
c34b1796 | 713 | } |
c34b1796 | 714 | |
54a0048b SL |
715 | if reexports.len() > 0 { |
716 | if let Some(def_id) = module.def_id() { | |
717 | let node_id = self.resolver.ast_map.as_local_node_id(def_id).unwrap(); | |
718 | self.resolver.export_map.insert(node_id, reexports); | |
719 | } | |
c34b1796 AL |
720 | } |
721 | ||
54a0048b SL |
722 | if report_unresolved_imports { |
723 | for import in module.unresolved_imports.borrow().iter() { | |
724 | resolve_error(self.resolver, import.span, ResolutionError::UnresolvedImport(None)); | |
725 | break; | |
726 | } | |
727 | } | |
728 | ||
729 | for (_, child) in module.module_children.borrow().iter() { | |
730 | self.finalize_resolutions(child, report_unresolved_imports); | |
c34b1796 AL |
731 | } |
732 | } | |
733 | } | |
734 | ||
54a0048b | 735 | fn import_path_to_string(names: &[Name], subclass: &ImportDirectiveSubclass) -> String { |
c34b1796 AL |
736 | if names.is_empty() { |
737 | import_directive_subclass_to_string(subclass) | |
738 | } else { | |
739 | (format!("{}::{}", | |
740 | names_to_string(names), | |
92a42be0 SL |
741 | import_directive_subclass_to_string(subclass))) |
742 | .to_string() | |
c34b1796 AL |
743 | } |
744 | } | |
745 | ||
54a0048b SL |
746 | fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass) -> String { |
747 | match *subclass { | |
748 | SingleImport { source, .. } => source.to_string(), | |
92a42be0 | 749 | GlobImport => "*".to_string(), |
c34b1796 AL |
750 | } |
751 | } | |
752 | ||
753 | pub fn resolve_imports(resolver: &mut Resolver) { | |
92a42be0 | 754 | let mut import_resolver = ImportResolver { resolver: resolver }; |
c34b1796 AL |
755 | import_resolver.resolve_imports(); |
756 | } |