]>
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}; | |
92a42be0 | 16 | use {NameBindings, NameBinding}; |
c34b1796 AL |
17 | use NamespaceResult::{BoundResult, UnboundResult, UnknownResult}; |
18 | use NamespaceResult; | |
19 | use NameSearchType; | |
20 | use ResolveResult; | |
21 | use Resolver; | |
22 | use UseLexicalScopeFlag; | |
23 | use {names_to_string, module_to_string}; | |
c1a9b12d | 24 | use {resolve_error, ResolutionError}; |
c34b1796 AL |
25 | |
26 | use build_reduced_graph; | |
27 | ||
28 | use rustc::middle::def::*; | |
e9174d1e | 29 | use rustc::middle::def_id::DefId; |
c34b1796 AL |
30 | use rustc::middle::privacy::*; |
31 | ||
e9174d1e | 32 | use syntax::ast::{NodeId, Name}; |
c34b1796 | 33 | use syntax::attr::AttrMetaMethods; |
c34b1796 AL |
34 | use syntax::codemap::Span; |
35 | ||
36 | use std::mem::replace; | |
37 | use std::rc::Rc; | |
38 | ||
39 | ||
40 | /// Contains data for specific types of import directives. | |
41 | #[derive(Copy, Clone,Debug)] | |
42 | pub enum ImportDirectiveSubclass { | |
43 | SingleImport(Name /* target */, Name /* source */), | |
92a42be0 | 44 | GlobImport, |
c34b1796 AL |
45 | } |
46 | ||
47 | /// Whether an import can be shadowed by another import. | |
48 | #[derive(Debug,PartialEq,Clone,Copy)] | |
49 | pub enum Shadowable { | |
50 | Always, | |
92a42be0 | 51 | Never, |
c34b1796 AL |
52 | } |
53 | ||
54 | /// One import directive. | |
55 | #[derive(Debug)] | |
56 | pub struct ImportDirective { | |
57 | pub module_path: Vec<Name>, | |
58 | pub subclass: ImportDirectiveSubclass, | |
59 | pub span: Span, | |
60 | pub id: NodeId, | |
61 | pub is_public: bool, // see note in ImportResolution about how to use this | |
62 | pub shadowable: Shadowable, | |
63 | } | |
64 | ||
65 | impl ImportDirective { | |
92a42be0 SL |
66 | pub fn new(module_path: Vec<Name>, |
67 | subclass: ImportDirectiveSubclass, | |
68 | span: Span, | |
69 | id: NodeId, | |
70 | is_public: bool, | |
71 | shadowable: Shadowable) | |
72 | -> ImportDirective { | |
c34b1796 AL |
73 | ImportDirective { |
74 | module_path: module_path, | |
75 | subclass: subclass, | |
76 | span: span, | |
77 | id: id, | |
78 | is_public: is_public, | |
79 | shadowable: shadowable, | |
80 | } | |
81 | } | |
82 | } | |
83 | ||
84 | /// The item that an import resolves to. | |
85 | #[derive(Clone,Debug)] | |
86 | pub struct Target { | |
87 | pub target_module: Rc<Module>, | |
92a42be0 | 88 | pub binding: NameBinding, |
c34b1796 AL |
89 | pub shadowable: Shadowable, |
90 | } | |
91 | ||
92 | impl Target { | |
93 | pub fn new(target_module: Rc<Module>, | |
92a42be0 SL |
94 | binding: NameBinding, |
95 | shadowable: Shadowable) | |
96 | -> Target { | |
c34b1796 AL |
97 | Target { |
98 | target_module: target_module, | |
92a42be0 | 99 | binding: binding, |
c34b1796 AL |
100 | shadowable: shadowable, |
101 | } | |
102 | } | |
103 | } | |
104 | ||
105 | /// An ImportResolution represents a particular `use` directive. | |
106 | #[derive(Debug)] | |
107 | pub struct ImportResolution { | |
108 | /// Whether this resolution came from a `use` or a `pub use`. Note that this | |
109 | /// should *not* be used whenever resolution is being performed. Privacy | |
110 | /// testing occurs during a later phase of compilation. | |
111 | pub is_public: bool, | |
112 | ||
113 | // The number of outstanding references to this name. When this reaches | |
114 | // zero, outside modules can count on the targets being correct. Before | |
115 | // then, all bets are off; future imports could override this name. | |
116 | // Note that this is usually either 0 or 1 - shadowing is forbidden the only | |
117 | // way outstanding_references is > 1 in a legal program is if the name is | |
118 | // used in both namespaces. | |
119 | pub outstanding_references: usize, | |
120 | ||
121 | /// The value that this `use` directive names, if there is one. | |
122 | pub value_target: Option<Target>, | |
123 | /// The source node of the `use` directive leading to the value target | |
124 | /// being non-none | |
125 | pub value_id: NodeId, | |
126 | ||
127 | /// The type that this `use` directive names, if there is one. | |
128 | pub type_target: Option<Target>, | |
129 | /// The source node of the `use` directive leading to the type target | |
130 | /// being non-none | |
131 | pub type_id: NodeId, | |
132 | } | |
133 | ||
134 | impl ImportResolution { | |
135 | pub fn new(id: NodeId, is_public: bool) -> ImportResolution { | |
136 | ImportResolution { | |
137 | type_id: id, | |
138 | value_id: id, | |
139 | outstanding_references: 0, | |
140 | value_target: None, | |
141 | type_target: None, | |
142 | is_public: is_public, | |
143 | } | |
144 | } | |
145 | ||
92a42be0 | 146 | pub fn target_for_namespace(&self, namespace: Namespace) -> Option<Target> { |
c34b1796 | 147 | match namespace { |
92a42be0 | 148 | TypeNS => self.type_target.clone(), |
c34b1796 AL |
149 | ValueNS => self.value_target.clone(), |
150 | } | |
151 | } | |
152 | ||
153 | pub fn id(&self, namespace: Namespace) -> NodeId { | |
154 | match namespace { | |
92a42be0 | 155 | TypeNS => self.type_id, |
c34b1796 AL |
156 | ValueNS => self.value_id, |
157 | } | |
158 | } | |
159 | ||
160 | pub fn shadowable(&self, namespace: Namespace) -> Shadowable { | |
161 | let target = self.target_for_namespace(namespace); | |
162 | if target.is_none() { | |
163 | return Shadowable::Always; | |
164 | } | |
165 | ||
166 | target.unwrap().shadowable | |
167 | } | |
168 | ||
92a42be0 | 169 | pub fn set_target_and_id(&mut self, namespace: Namespace, target: Option<Target>, id: NodeId) { |
c34b1796 | 170 | match namespace { |
92a42be0 | 171 | TypeNS => { |
c34b1796 AL |
172 | self.type_target = target; |
173 | self.type_id = id; | |
174 | } | |
175 | ValueNS => { | |
176 | self.value_target = target; | |
177 | self.value_id = id; | |
178 | } | |
179 | } | |
180 | } | |
181 | } | |
182 | ||
e9174d1e SL |
183 | struct ImportResolvingError { |
184 | span: Span, | |
185 | path: String, | |
186 | help: String, | |
187 | } | |
c34b1796 | 188 | |
92a42be0 SL |
189 | struct ImportResolver<'a, 'b: 'a, 'tcx: 'b> { |
190 | resolver: &'a mut Resolver<'b, 'tcx>, | |
c34b1796 AL |
191 | } |
192 | ||
193 | impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { | |
194 | // Import resolution | |
195 | // | |
196 | // This is a fixed-point algorithm. We resolve imports until our efforts | |
197 | // are stymied by an unresolved import; then we bail out of the current | |
198 | // module and continue. We terminate successfully once no more imports | |
199 | // remain or unsuccessfully when no forward progress in resolving imports | |
200 | // is made. | |
201 | ||
202 | /// Resolves all imports for the crate. This method performs the fixed- | |
203 | /// point iteration. | |
204 | fn resolve_imports(&mut self) { | |
205 | let mut i = 0; | |
206 | let mut prev_unresolved_imports = 0; | |
207 | loop { | |
208 | debug!("(resolving imports) iteration {}, {} imports left", | |
92a42be0 SL |
209 | i, |
210 | self.resolver.unresolved_imports); | |
c34b1796 | 211 | |
92a42be0 | 212 | let module_root = self.resolver.graph_root.clone(); |
e9174d1e | 213 | let errors = self.resolve_imports_for_module_subtree(module_root.clone()); |
c34b1796 AL |
214 | |
215 | if self.resolver.unresolved_imports == 0 { | |
216 | debug!("(resolving imports) success"); | |
217 | break; | |
218 | } | |
219 | ||
220 | if self.resolver.unresolved_imports == prev_unresolved_imports { | |
e9174d1e SL |
221 | // resolving failed |
222 | if errors.len() > 0 { | |
223 | for e in errors { | |
224 | resolve_error(self.resolver, | |
225 | e.span, | |
226 | ResolutionError::UnresolvedImport(Some((&e.path, &e.help)))); | |
227 | } | |
228 | } else { | |
229 | // Report unresolved imports only if no hard error was already reported | |
230 | // to avoid generating multiple errors on the same import. | |
231 | // Imports that are still indeterminate at this point are actually blocked | |
232 | // by errored imports, so there is no point reporting them. | |
233 | self.resolver.report_unresolved_imports(module_root); | |
234 | } | |
c34b1796 AL |
235 | break; |
236 | } | |
237 | ||
238 | i += 1; | |
239 | prev_unresolved_imports = self.resolver.unresolved_imports; | |
240 | } | |
241 | } | |
242 | ||
243 | /// Attempts to resolve imports for the given module and all of its | |
244 | /// submodules. | |
92a42be0 SL |
245 | fn resolve_imports_for_module_subtree(&mut self, |
246 | module_: Rc<Module>) | |
e9174d1e SL |
247 | -> Vec<ImportResolvingError> { |
248 | let mut errors = Vec::new(); | |
c34b1796 AL |
249 | debug!("(resolving imports for module subtree) resolving {}", |
250 | module_to_string(&*module_)); | |
251 | let orig_module = replace(&mut self.resolver.current_module, module_.clone()); | |
e9174d1e | 252 | errors.extend(self.resolve_imports_for_module(module_.clone())); |
c34b1796 AL |
253 | self.resolver.current_module = orig_module; |
254 | ||
255 | build_reduced_graph::populate_module_if_necessary(self.resolver, &module_); | |
62682a34 | 256 | for (_, child_node) in module_.children.borrow().iter() { |
92a42be0 | 257 | match child_node.type_ns.module() { |
c34b1796 AL |
258 | None => { |
259 | // Nothing to do. | |
260 | } | |
261 | Some(child_module) => { | |
e9174d1e | 262 | errors.extend(self.resolve_imports_for_module_subtree(child_module)); |
c34b1796 AL |
263 | } |
264 | } | |
265 | } | |
266 | ||
62682a34 | 267 | for (_, child_module) in module_.anonymous_children.borrow().iter() { |
e9174d1e | 268 | errors.extend(self.resolve_imports_for_module_subtree(child_module.clone())); |
c34b1796 | 269 | } |
e9174d1e SL |
270 | |
271 | errors | |
c34b1796 AL |
272 | } |
273 | ||
274 | /// Attempts to resolve imports for the given module only. | |
e9174d1e SL |
275 | fn resolve_imports_for_module(&mut self, module: Rc<Module>) -> Vec<ImportResolvingError> { |
276 | let mut errors = Vec::new(); | |
277 | ||
c34b1796 | 278 | if module.all_imports_resolved() { |
92a42be0 | 279 | debug!("(resolving imports for module) all imports resolved for {}", |
c34b1796 | 280 | module_to_string(&*module)); |
e9174d1e | 281 | return errors; |
c34b1796 AL |
282 | } |
283 | ||
e9174d1e | 284 | let mut imports = module.imports.borrow_mut(); |
c34b1796 | 285 | let import_count = imports.len(); |
e9174d1e SL |
286 | let mut indeterminate_imports = Vec::new(); |
287 | while module.resolved_import_count.get() + indeterminate_imports.len() < import_count { | |
c34b1796 | 288 | let import_index = module.resolved_import_count.get(); |
92a42be0 | 289 | match self.resolve_import_for_module(module.clone(), &imports[import_index]) { |
c34b1796 | 290 | ResolveResult::Failed(err) => { |
e9174d1e | 291 | let import_directive = &imports[import_index]; |
c34b1796 AL |
292 | let (span, help) = match err { |
293 | Some((span, msg)) => (span, format!(". {}", msg)), | |
92a42be0 | 294 | None => (import_directive.span, String::new()), |
c34b1796 | 295 | }; |
e9174d1e | 296 | errors.push(ImportResolvingError { |
92a42be0 SL |
297 | span: span, |
298 | path: import_path_to_string(&import_directive.module_path, | |
299 | import_directive.subclass), | |
300 | help: help, | |
301 | }); | |
e9174d1e SL |
302 | } |
303 | ResolveResult::Indeterminate => {} | |
304 | ResolveResult::Success(()) => { | |
305 | // count success | |
306 | module.resolved_import_count | |
307 | .set(module.resolved_import_count.get() + 1); | |
308 | continue; | |
c34b1796 | 309 | } |
c34b1796 | 310 | } |
e9174d1e SL |
311 | // This resolution was not successful, keep it for later |
312 | indeterminate_imports.push(imports.swap_remove(import_index)); | |
c34b1796 | 313 | |
c34b1796 | 314 | } |
e9174d1e SL |
315 | |
316 | imports.extend(indeterminate_imports); | |
317 | ||
318 | errors | |
c34b1796 AL |
319 | } |
320 | ||
321 | /// Attempts to resolve the given import. The return value indicates | |
322 | /// failure if we're certain the name does not exist, indeterminate if we | |
323 | /// don't know whether the name exists at the moment due to other | |
324 | /// currently-unresolved imports, or success if we know the name exists. | |
325 | /// If successful, the resolved bindings are written into the module. | |
326 | fn resolve_import_for_module(&mut self, | |
327 | module_: Rc<Module>, | |
328 | import_directive: &ImportDirective) | |
329 | -> ResolveResult<()> { | |
330 | let mut resolution_result = ResolveResult::Failed(None); | |
331 | let module_path = &import_directive.module_path; | |
332 | ||
333 | debug!("(resolving import for module) resolving import `{}::...` in `{}`", | |
334 | names_to_string(&module_path[..]), | |
335 | module_to_string(&*module_)); | |
336 | ||
337 | // First, resolve the module path for the directive, if necessary. | |
9346a6ac | 338 | let container = if module_path.is_empty() { |
c34b1796 | 339 | // Use the crate root. |
92a42be0 | 340 | Some((self.resolver.graph_root.clone(), LastMod(AllPublic))) |
c34b1796 AL |
341 | } else { |
342 | match self.resolver.resolve_module_path(module_.clone(), | |
343 | &module_path[..], | |
344 | UseLexicalScopeFlag::DontUseLexicalScope, | |
345 | import_directive.span, | |
346 | NameSearchType::ImportSearch) { | |
347 | ResolveResult::Failed(err) => { | |
348 | resolution_result = ResolveResult::Failed(err); | |
349 | None | |
92a42be0 | 350 | } |
c34b1796 AL |
351 | ResolveResult::Indeterminate => { |
352 | resolution_result = ResolveResult::Indeterminate; | |
353 | None | |
354 | } | |
355 | ResolveResult::Success(container) => Some(container), | |
356 | } | |
357 | }; | |
358 | ||
359 | match container { | |
360 | None => {} | |
361 | Some((containing_module, lp)) => { | |
362 | // We found the module that the target is contained | |
363 | // within. Attempt to resolve the import within it. | |
364 | ||
365 | match import_directive.subclass { | |
366 | SingleImport(target, source) => { | |
92a42be0 SL |
367 | resolution_result = self.resolve_single_import(&module_, |
368 | containing_module, | |
369 | target, | |
370 | source, | |
371 | import_directive, | |
372 | lp); | |
c34b1796 AL |
373 | } |
374 | GlobImport => { | |
92a42be0 SL |
375 | resolution_result = self.resolve_glob_import(&module_, |
376 | containing_module, | |
377 | import_directive, | |
378 | lp); | |
c34b1796 AL |
379 | } |
380 | } | |
381 | } | |
382 | } | |
383 | ||
384 | // Decrement the count of unresolved imports. | |
385 | match resolution_result { | |
386 | ResolveResult::Success(()) => { | |
387 | assert!(self.resolver.unresolved_imports >= 1); | |
388 | self.resolver.unresolved_imports -= 1; | |
389 | } | |
390 | _ => { | |
391 | // Nothing to do here; just return the error. | |
392 | } | |
393 | } | |
394 | ||
395 | // Decrement the count of unresolved globs if necessary. But only if | |
e9174d1e SL |
396 | // the resolution result is a success -- other cases will |
397 | // be handled by the main loop. | |
c34b1796 | 398 | |
e9174d1e | 399 | if resolution_result.success() { |
c34b1796 AL |
400 | match import_directive.subclass { |
401 | GlobImport => { | |
e9174d1e SL |
402 | module_.dec_glob_count(); |
403 | if import_directive.is_public { | |
404 | module_.dec_pub_glob_count(); | |
405 | } | |
c34b1796 AL |
406 | } |
407 | SingleImport(..) => { | |
408 | // Ignore. | |
409 | } | |
410 | } | |
e9174d1e SL |
411 | if import_directive.is_public { |
412 | module_.dec_pub_count(); | |
413 | } | |
c34b1796 AL |
414 | } |
415 | ||
416 | return resolution_result; | |
417 | } | |
418 | ||
419 | fn resolve_single_import(&mut self, | |
420 | module_: &Module, | |
421 | target_module: Rc<Module>, | |
422 | target: Name, | |
423 | source: Name, | |
424 | directive: &ImportDirective, | |
425 | lp: LastPrivate) | |
426 | -> ResolveResult<()> { | |
92a42be0 SL |
427 | debug!("(resolving single import) resolving `{}` = `{}::{}` from `{}` id {}, last \ |
428 | private {:?}", | |
c1a9b12d | 429 | target, |
c34b1796 | 430 | module_to_string(&*target_module), |
c1a9b12d | 431 | source, |
c34b1796 AL |
432 | module_to_string(module_), |
433 | directive.id, | |
434 | lp); | |
435 | ||
436 | let lp = match lp { | |
437 | LastMod(lp) => lp, | |
438 | LastImport {..} => { | |
92a42be0 SL |
439 | self.resolver |
440 | .session | |
441 | .span_bug(directive.span, "not expecting Import here, must be LastMod") | |
c34b1796 AL |
442 | } |
443 | }; | |
444 | ||
445 | // We need to resolve both namespaces for this to succeed. | |
446 | // | |
447 | ||
448 | let mut value_result = UnknownResult; | |
449 | let mut type_result = UnknownResult; | |
450 | ||
451 | // Search for direct children of the containing module. | |
452 | build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module); | |
453 | ||
454 | match target_module.children.borrow().get(&source) { | |
455 | None => { | |
456 | // Continue. | |
457 | } | |
458 | Some(ref child_name_bindings) => { | |
459 | // pub_err makes sure we don't give the same error twice. | |
460 | let mut pub_err = false; | |
92a42be0 | 461 | if child_name_bindings.value_ns.defined() { |
c34b1796 AL |
462 | debug!("(resolving single import) found value binding"); |
463 | value_result = BoundResult(target_module.clone(), | |
92a42be0 SL |
464 | child_name_bindings.value_ns.clone()); |
465 | if directive.is_public && !child_name_bindings.value_ns.is_public() { | |
466 | let msg = format!("`{}` is private, and cannot be reexported", source); | |
467 | let note_msg = format!("Consider marking `{}` as `pub` in the imported \ | |
468 | module", | |
469 | source); | |
c34b1796 | 470 | span_err!(self.resolver.session, directive.span, E0364, "{}", &msg); |
c1a9b12d | 471 | self.resolver.session.span_note(directive.span, ¬e_msg); |
c34b1796 AL |
472 | pub_err = true; |
473 | } | |
474 | } | |
92a42be0 | 475 | if child_name_bindings.type_ns.defined() { |
c34b1796 AL |
476 | debug!("(resolving single import) found type binding"); |
477 | type_result = BoundResult(target_module.clone(), | |
92a42be0 SL |
478 | child_name_bindings.type_ns.clone()); |
479 | if !pub_err && directive.is_public && | |
480 | !child_name_bindings.type_ns.is_public() { | |
481 | let msg = format!("`{}` is private, and cannot be reexported", source); | |
c1a9b12d SL |
482 | let note_msg = format!("Consider declaring module `{}` as a `pub mod`", |
483 | source); | |
c34b1796 | 484 | span_err!(self.resolver.session, directive.span, E0365, "{}", &msg); |
c1a9b12d | 485 | self.resolver.session.span_note(directive.span, ¬e_msg); |
c34b1796 AL |
486 | } |
487 | } | |
488 | } | |
489 | } | |
490 | ||
491 | // Unless we managed to find a result in both namespaces (unlikely), | |
492 | // search imports as well. | |
493 | let mut value_used_reexport = false; | |
494 | let mut type_used_reexport = false; | |
495 | match (value_result.clone(), type_result.clone()) { | |
496 | (BoundResult(..), BoundResult(..)) => {} // Continue. | |
497 | _ => { | |
498 | // If there is an unresolved glob at this point in the | |
499 | // containing module, bail out. We don't know enough to be | |
500 | // able to resolve this import. | |
501 | ||
e9174d1e | 502 | if target_module.pub_glob_count.get() > 0 { |
92a42be0 | 503 | debug!("(resolving single import) unresolved pub glob; bailing out"); |
c34b1796 AL |
504 | return ResolveResult::Indeterminate; |
505 | } | |
506 | ||
507 | // Now search the exported imports within the containing module. | |
508 | match target_module.import_resolutions.borrow().get(&source) { | |
509 | None => { | |
510 | debug!("(resolving single import) no import"); | |
511 | // The containing module definitely doesn't have an | |
512 | // exported import with the name in question. We can | |
513 | // therefore accurately report that the names are | |
514 | // unbound. | |
515 | ||
516 | if value_result.is_unknown() { | |
517 | value_result = UnboundResult; | |
518 | } | |
519 | if type_result.is_unknown() { | |
520 | type_result = UnboundResult; | |
521 | } | |
522 | } | |
92a42be0 | 523 | Some(import_resolution) if import_resolution.outstanding_references == 0 => { |
c34b1796 AL |
524 | |
525 | fn get_binding(this: &mut Resolver, | |
526 | import_resolution: &ImportResolution, | |
527 | namespace: Namespace, | |
b039eaaf | 528 | source: Name) |
92a42be0 | 529 | -> NamespaceResult { |
c34b1796 AL |
530 | |
531 | // Import resolutions must be declared with "pub" | |
532 | // in order to be exported. | |
533 | if !import_resolution.is_public { | |
534 | return UnboundResult; | |
535 | } | |
536 | ||
537 | match import_resolution.target_for_namespace(namespace) { | |
538 | None => { | |
539 | return UnboundResult; | |
540 | } | |
541 | Some(Target { | |
542 | target_module, | |
92a42be0 | 543 | binding, |
c34b1796 AL |
544 | shadowable: _ |
545 | }) => { | |
92a42be0 SL |
546 | debug!("(resolving single import) found import in ns {:?}", |
547 | namespace); | |
c34b1796 AL |
548 | let id = import_resolution.id(namespace); |
549 | // track used imports and extern crates as well | |
550 | this.used_imports.insert((id, namespace)); | |
b039eaaf | 551 | this.record_import_use(id, source); |
92a42be0 | 552 | match target_module.def_id() { |
c34b1796 AL |
553 | Some(DefId{krate: kid, ..}) => { |
554 | this.used_crates.insert(kid); | |
92a42be0 | 555 | } |
c34b1796 AL |
556 | _ => {} |
557 | } | |
92a42be0 | 558 | return BoundResult(target_module, binding); |
c34b1796 AL |
559 | } |
560 | } | |
561 | } | |
562 | ||
563 | // The name is an import which has been fully | |
564 | // resolved. We can, therefore, just follow it. | |
565 | if value_result.is_unknown() { | |
566 | value_result = get_binding(self.resolver, | |
567 | import_resolution, | |
568 | ValueNS, | |
b039eaaf | 569 | source); |
c34b1796 AL |
570 | value_used_reexport = import_resolution.is_public; |
571 | } | |
572 | if type_result.is_unknown() { | |
573 | type_result = get_binding(self.resolver, | |
574 | import_resolution, | |
575 | TypeNS, | |
b039eaaf | 576 | source); |
c34b1796 AL |
577 | type_used_reexport = import_resolution.is_public; |
578 | } | |
579 | ||
580 | } | |
581 | Some(_) => { | |
582 | // If target_module is the same module whose import we are resolving | |
583 | // and there it has an unresolved import with the same name as `source`, | |
584 | // then the user is actually trying to import an item that is declared | |
585 | // in the same scope | |
586 | // | |
587 | // e.g | |
588 | // use self::submodule; | |
589 | // pub mod submodule; | |
590 | // | |
591 | // In this case we continue as if we resolved the import and let the | |
592 | // check_for_conflicts_between_imports_and_items call below handle | |
593 | // the conflict | |
92a42be0 SL |
594 | match (module_.def_id(), target_module.def_id()) { |
595 | (Some(id1), Some(id2)) if id1 == id2 => { | |
c34b1796 AL |
596 | if value_result.is_unknown() { |
597 | value_result = UnboundResult; | |
598 | } | |
599 | if type_result.is_unknown() { | |
600 | type_result = UnboundResult; | |
601 | } | |
602 | } | |
92a42be0 | 603 | _ => { |
c34b1796 | 604 | // The import is unresolved. Bail out. |
92a42be0 | 605 | debug!("(resolving single import) unresolved import; bailing out"); |
c34b1796 AL |
606 | return ResolveResult::Indeterminate; |
607 | } | |
608 | } | |
609 | } | |
610 | } | |
611 | } | |
612 | } | |
613 | ||
614 | let mut value_used_public = false; | |
615 | let mut type_used_public = false; | |
616 | ||
617 | // If we didn't find a result in the type namespace, search the | |
618 | // external modules. | |
619 | match type_result { | |
620 | BoundResult(..) => {} | |
621 | _ => { | |
622 | match target_module.external_module_children.borrow_mut().get(&source).cloned() { | |
623 | None => {} // Continue. | |
624 | Some(module) => { | |
625 | debug!("(resolving single import) found external module"); | |
626 | // track the module as used. | |
92a42be0 | 627 | match module.def_id() { |
c34b1796 AL |
628 | Some(DefId{krate: kid, ..}) => { |
629 | self.resolver.used_crates.insert(kid); | |
630 | } | |
631 | _ => {} | |
632 | } | |
92a42be0 SL |
633 | let name_binding = NameBinding::create_from_module(module); |
634 | type_result = BoundResult(target_module.clone(), name_binding); | |
c34b1796 AL |
635 | type_used_public = true; |
636 | } | |
637 | } | |
638 | } | |
639 | } | |
640 | ||
641 | // We've successfully resolved the import. Write the results in. | |
642 | let mut import_resolutions = module_.import_resolutions.borrow_mut(); | |
643 | let import_resolution = import_resolutions.get_mut(&target).unwrap(); | |
644 | ||
645 | { | |
646 | let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| { | |
647 | let namespace_name = match namespace { | |
648 | TypeNS => "type", | |
649 | ValueNS => "value", | |
650 | }; | |
651 | ||
652 | match *result { | |
92a42be0 | 653 | BoundResult(ref target_module, ref name_binding) => { |
c34b1796 AL |
654 | debug!("(resolving single import) found {:?} target: {:?}", |
655 | namespace_name, | |
92a42be0 SL |
656 | name_binding.def()); |
657 | self.check_for_conflicting_import(&import_resolution, | |
658 | directive.span, | |
659 | target, | |
660 | namespace); | |
661 | ||
662 | self.check_that_import_is_importable(&name_binding, | |
663 | directive.span, | |
664 | target); | |
c34b1796 AL |
665 | |
666 | let target = Some(Target::new(target_module.clone(), | |
92a42be0 | 667 | name_binding.clone(), |
c34b1796 AL |
668 | directive.shadowable)); |
669 | import_resolution.set_target_and_id(namespace, target, directive.id); | |
670 | import_resolution.is_public = directive.is_public; | |
92a42be0 SL |
671 | *used_public = name_binding.is_public(); |
672 | } | |
673 | UnboundResult => { | |
674 | // Continue. | |
c34b1796 | 675 | } |
c34b1796 AL |
676 | UnknownResult => { |
677 | panic!("{:?} result should be known at this point", namespace_name); | |
678 | } | |
679 | } | |
680 | }; | |
681 | check_and_write_import(ValueNS, &value_result, &mut value_used_public); | |
682 | check_and_write_import(TypeNS, &type_result, &mut type_used_public); | |
683 | } | |
684 | ||
92a42be0 SL |
685 | self.check_for_conflicts_between_imports_and_items(module_, |
686 | import_resolution, | |
687 | directive.span, | |
688 | target); | |
c34b1796 AL |
689 | |
690 | if value_result.is_unbound() && type_result.is_unbound() { | |
691 | let msg = format!("There is no `{}` in `{}`", | |
c1a9b12d | 692 | source, |
c34b1796 AL |
693 | module_to_string(&target_module)); |
694 | return ResolveResult::Failed(Some((directive.span, msg))); | |
695 | } | |
696 | let value_used_public = value_used_reexport || value_used_public; | |
697 | let type_used_public = type_used_reexport || type_used_public; | |
698 | ||
699 | assert!(import_resolution.outstanding_references >= 1); | |
700 | import_resolution.outstanding_references -= 1; | |
701 | ||
702 | // Record what this import resolves to for later uses in documentation, | |
703 | // this may resolve to either a value or a type, but for documentation | |
704 | // purposes it's good enough to just favor one over the other. | |
705 | let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| { | |
92a42be0 SL |
706 | let def = target.binding.def().unwrap(); |
707 | (def, | |
708 | if value_used_public { | |
709 | lp | |
710 | } else { | |
711 | DependsOn(def.def_id()) | |
712 | }) | |
c34b1796 AL |
713 | }); |
714 | let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| { | |
92a42be0 SL |
715 | let def = target.binding.def().unwrap(); |
716 | (def, | |
717 | if type_used_public { | |
718 | lp | |
719 | } else { | |
720 | DependsOn(def.def_id()) | |
721 | }) | |
c34b1796 AL |
722 | }); |
723 | ||
724 | let import_lp = LastImport { | |
725 | value_priv: value_def_and_priv.map(|(_, p)| p), | |
726 | value_used: Used, | |
727 | type_priv: type_def_and_priv.map(|(_, p)| p), | |
92a42be0 | 728 | type_used: Used, |
c34b1796 AL |
729 | }; |
730 | ||
731 | if let Some((def, _)) = value_def_and_priv { | |
92a42be0 SL |
732 | self.resolver.def_map.borrow_mut().insert(directive.id, |
733 | PathResolution { | |
734 | base_def: def, | |
735 | last_private: import_lp, | |
736 | depth: 0, | |
737 | }); | |
c34b1796 AL |
738 | } |
739 | if let Some((def, _)) = type_def_and_priv { | |
92a42be0 SL |
740 | self.resolver.def_map.borrow_mut().insert(directive.id, |
741 | PathResolution { | |
742 | base_def: def, | |
743 | last_private: import_lp, | |
744 | depth: 0, | |
745 | }); | |
c34b1796 AL |
746 | } |
747 | ||
748 | debug!("(resolving single import) successfully resolved import"); | |
749 | return ResolveResult::Success(()); | |
750 | } | |
751 | ||
752 | // Resolves a glob import. Note that this function cannot fail; it either | |
753 | // succeeds or bails out (as importing * from an empty module or a module | |
754 | // that exports nothing is valid). target_module is the module we are | |
755 | // actually importing, i.e., `foo` in `use foo::*`. | |
756 | fn resolve_glob_import(&mut self, | |
757 | module_: &Module, | |
758 | target_module: Rc<Module>, | |
759 | import_directive: &ImportDirective, | |
760 | lp: LastPrivate) | |
761 | -> ResolveResult<()> { | |
762 | let id = import_directive.id; | |
763 | let is_public = import_directive.is_public; | |
764 | ||
765 | // This function works in a highly imperative manner; it eagerly adds | |
766 | // everything it can to the list of import resolutions of the module | |
767 | // node. | |
768 | debug!("(resolving glob import) resolving glob import {}", id); | |
769 | ||
770 | // We must bail out if the node has unresolved imports of any kind | |
771 | // (including globs). | |
e9174d1e | 772 | if (*target_module).pub_count.get() > 0 { |
92a42be0 | 773 | debug!("(resolving glob import) target module has unresolved pub imports; bailing out"); |
c34b1796 AL |
774 | return ResolveResult::Indeterminate; |
775 | } | |
776 | ||
c34b1796 AL |
777 | // Add all resolved imports from the containing module. |
778 | let import_resolutions = target_module.import_resolutions.borrow(); | |
e9174d1e SL |
779 | |
780 | if module_.import_resolutions.borrow_state() != ::std::cell::BorrowState::Unused { | |
781 | // In this case, target_module == module_ | |
782 | // This means we are trying to glob import a module into itself, | |
783 | // and it is a no-go | |
784 | debug!("(resolving glob imports) target module is current module; giving up"); | |
92a42be0 SL |
785 | return ResolveResult::Failed(Some((import_directive.span, |
786 | "Cannot glob-import a module into itself.".into()))); | |
e9174d1e SL |
787 | } |
788 | ||
b039eaaf | 789 | for (name, target_import_resolution) in import_resolutions.iter() { |
92a42be0 | 790 | debug!("(resolving glob import) writing module resolution {} into `{}`", |
b039eaaf | 791 | *name, |
c34b1796 AL |
792 | module_to_string(module_)); |
793 | ||
794 | if !target_import_resolution.is_public { | |
795 | debug!("(resolving glob import) nevermind, just kidding"); | |
92a42be0 | 796 | continue; |
c34b1796 AL |
797 | } |
798 | ||
799 | // Here we merge two import resolutions. | |
800 | let mut import_resolutions = module_.import_resolutions.borrow_mut(); | |
b039eaaf | 801 | match import_resolutions.get_mut(name) { |
c34b1796 AL |
802 | Some(dest_import_resolution) => { |
803 | // Merge the two import resolutions at a finer-grained | |
804 | // level. | |
805 | ||
806 | match target_import_resolution.value_target { | |
807 | None => { | |
808 | // Continue. | |
809 | } | |
810 | Some(ref value_target) => { | |
d9579d0f | 811 | self.check_for_conflicting_import(&dest_import_resolution, |
c34b1796 | 812 | import_directive.span, |
b039eaaf | 813 | *name, |
c34b1796 AL |
814 | ValueNS); |
815 | dest_import_resolution.value_target = Some(value_target.clone()); | |
816 | } | |
817 | } | |
818 | match target_import_resolution.type_target { | |
819 | None => { | |
820 | // Continue. | |
821 | } | |
822 | Some(ref type_target) => { | |
d9579d0f | 823 | self.check_for_conflicting_import(&dest_import_resolution, |
c34b1796 | 824 | import_directive.span, |
b039eaaf | 825 | *name, |
c34b1796 AL |
826 | TypeNS); |
827 | dest_import_resolution.type_target = Some(type_target.clone()); | |
828 | } | |
829 | } | |
830 | dest_import_resolution.is_public = is_public; | |
831 | continue; | |
832 | } | |
833 | None => {} | |
834 | } | |
835 | ||
836 | // Simple: just copy the old import resolution. | |
837 | let mut new_import_resolution = ImportResolution::new(id, is_public); | |
92a42be0 SL |
838 | new_import_resolution.value_target = target_import_resolution.value_target.clone(); |
839 | new_import_resolution.type_target = target_import_resolution.type_target.clone(); | |
c34b1796 | 840 | |
b039eaaf | 841 | import_resolutions.insert(*name, new_import_resolution); |
c34b1796 AL |
842 | } |
843 | ||
844 | // Add all children from the containing module. | |
845 | build_reduced_graph::populate_module_if_necessary(self.resolver, &target_module); | |
846 | ||
62682a34 | 847 | for (&name, name_bindings) in target_module.children.borrow().iter() { |
c34b1796 AL |
848 | self.merge_import_resolution(module_, |
849 | target_module.clone(), | |
850 | import_directive, | |
851 | name, | |
852 | name_bindings.clone()); | |
853 | ||
854 | } | |
855 | ||
c34b1796 | 856 | // Record the destination of this import |
92a42be0 SL |
857 | if let Some(did) = target_module.def_id() { |
858 | self.resolver.def_map.borrow_mut().insert(id, | |
859 | PathResolution { | |
860 | base_def: DefMod(did), | |
861 | last_private: lp, | |
862 | depth: 0, | |
863 | }); | |
c34b1796 AL |
864 | } |
865 | ||
866 | debug!("(resolving glob import) successfully resolved import"); | |
867 | return ResolveResult::Success(()); | |
868 | } | |
869 | ||
870 | fn merge_import_resolution(&mut self, | |
871 | module_: &Module, | |
872 | containing_module: Rc<Module>, | |
873 | import_directive: &ImportDirective, | |
874 | name: Name, | |
92a42be0 | 875 | name_bindings: NameBindings) { |
c34b1796 AL |
876 | let id = import_directive.id; |
877 | let is_public = import_directive.is_public; | |
878 | ||
879 | let mut import_resolutions = module_.import_resolutions.borrow_mut(); | |
880 | let dest_import_resolution = import_resolutions.entry(name) | |
92a42be0 SL |
881 | .or_insert_with(|| { |
882 | ImportResolution::new(id, is_public) | |
883 | }); | |
c34b1796 | 884 | |
92a42be0 | 885 | debug!("(resolving glob import) writing resolution `{}` in `{}` to `{}`", |
c1a9b12d | 886 | name, |
c34b1796 AL |
887 | module_to_string(&*containing_module), |
888 | module_to_string(module_)); | |
889 | ||
890 | // Merge the child item into the import resolution. | |
891 | { | |
892 | let mut merge_child_item = |namespace| { | |
d9579d0f AL |
893 | let modifier = DefModifiers::IMPORTABLE | DefModifiers::PUBLIC; |
894 | ||
92a42be0 | 895 | if name_bindings[namespace].defined_with(modifier) { |
c34b1796 AL |
896 | let namespace_name = match namespace { |
897 | TypeNS => "type", | |
898 | ValueNS => "value", | |
899 | }; | |
900 | debug!("(resolving glob import) ... for {} target", namespace_name); | |
901 | if dest_import_resolution.shadowable(namespace) == Shadowable::Never { | |
92a42be0 SL |
902 | let msg = format!("a {} named `{}` has already been imported in this \ |
903 | module", | |
c34b1796 | 904 | namespace_name, |
c1a9b12d | 905 | name); |
92a42be0 SL |
906 | span_err!(self.resolver.session, |
907 | import_directive.span, | |
908 | E0251, | |
909 | "{}", | |
910 | msg); | |
c34b1796 AL |
911 | } else { |
912 | let target = Target::new(containing_module.clone(), | |
92a42be0 | 913 | name_bindings[namespace].clone(), |
c34b1796 | 914 | import_directive.shadowable); |
92a42be0 | 915 | dest_import_resolution.set_target_and_id(namespace, Some(target), id); |
c34b1796 AL |
916 | } |
917 | } | |
918 | }; | |
919 | merge_child_item(ValueNS); | |
920 | merge_child_item(TypeNS); | |
921 | } | |
922 | ||
923 | dest_import_resolution.is_public = is_public; | |
924 | ||
92a42be0 SL |
925 | self.check_for_conflicts_between_imports_and_items(module_, |
926 | dest_import_resolution, | |
927 | import_directive.span, | |
928 | name); | |
c34b1796 AL |
929 | } |
930 | ||
931 | /// Checks that imported names and items don't have the same name. | |
932 | fn check_for_conflicting_import(&mut self, | |
d9579d0f | 933 | import_resolution: &ImportResolution, |
c34b1796 AL |
934 | import_span: Span, |
935 | name: Name, | |
936 | namespace: Namespace) { | |
d9579d0f | 937 | let target = import_resolution.target_for_namespace(namespace); |
c34b1796 | 938 | debug!("check_for_conflicting_import: {}; target exists: {}", |
c1a9b12d | 939 | name, |
c34b1796 AL |
940 | target.is_some()); |
941 | ||
d9579d0f | 942 | match target { |
c34b1796 | 943 | Some(ref target) if target.shadowable != Shadowable::Always => { |
d9579d0f | 944 | let ns_word = match namespace { |
62682a34 | 945 | TypeNS => { |
92a42be0 SL |
946 | match target.binding.module() { |
947 | Some(ref module) if module.is_normal() => "module", | |
948 | Some(ref module) if module.is_trait() => "trait", | |
949 | _ => "type", | |
950 | } | |
951 | } | |
d9579d0f AL |
952 | ValueNS => "value", |
953 | }; | |
92a42be0 SL |
954 | span_err!(self.resolver.session, |
955 | import_span, | |
956 | E0252, | |
957 | "a {} named `{}` has already been imported in this module", | |
958 | ns_word, | |
959 | name); | |
d9579d0f AL |
960 | let use_id = import_resolution.id(namespace); |
961 | let item = self.resolver.ast_map.expect_item(use_id); | |
962 | // item is syntax::ast::Item; | |
92a42be0 SL |
963 | span_note!(self.resolver.session, |
964 | item.span, | |
965 | "previous import of `{}` here", | |
966 | name); | |
c34b1796 AL |
967 | } |
968 | Some(_) | None => {} | |
969 | } | |
970 | } | |
971 | ||
972 | /// Checks that an import is actually importable | |
973 | fn check_that_import_is_importable(&mut self, | |
92a42be0 | 974 | name_binding: &NameBinding, |
c34b1796 | 975 | import_span: Span, |
92a42be0 SL |
976 | name: Name) { |
977 | if !name_binding.defined_with(DefModifiers::IMPORTABLE) { | |
978 | let msg = format!("`{}` is not directly importable", name); | |
c34b1796 AL |
979 | span_err!(self.resolver.session, import_span, E0253, "{}", &msg[..]); |
980 | } | |
981 | } | |
982 | ||
983 | /// Checks that imported names and items don't have the same name. | |
984 | fn check_for_conflicts_between_imports_and_items(&mut self, | |
985 | module: &Module, | |
92a42be0 | 986 | import_resolution: &ImportResolution, |
c34b1796 AL |
987 | import_span: Span, |
988 | name: Name) { | |
989 | // First, check for conflicts between imports and `extern crate`s. | |
990 | if module.external_module_children | |
991 | .borrow() | |
992 | .contains_key(&name) { | |
993 | match import_resolution.type_target { | |
994 | Some(ref target) if target.shadowable != Shadowable::Always => { | |
92a42be0 | 995 | let msg = format!("import `{0}` conflicts with imported crate in this module \ |
c34b1796 | 996 | (maybe you meant `use {0}::*`?)", |
c1a9b12d | 997 | name); |
c34b1796 AL |
998 | span_err!(self.resolver.session, import_span, E0254, "{}", &msg[..]); |
999 | } | |
1000 | Some(_) | None => {} | |
1001 | } | |
1002 | } | |
1003 | ||
1004 | // Check for item conflicts. | |
1005 | let children = module.children.borrow(); | |
1006 | let name_bindings = match children.get(&name) { | |
1007 | None => { | |
1008 | // There can't be any conflicts. | |
92a42be0 | 1009 | return; |
c34b1796 AL |
1010 | } |
1011 | Some(ref name_bindings) => (*name_bindings).clone(), | |
1012 | }; | |
1013 | ||
1014 | match import_resolution.value_target { | |
1015 | Some(ref target) if target.shadowable != Shadowable::Always => { | |
92a42be0 SL |
1016 | if let Some(ref value) = *name_bindings.value_ns.borrow() { |
1017 | span_err!(self.resolver.session, | |
1018 | import_span, | |
1019 | E0255, | |
c34b1796 | 1020 | "import `{}` conflicts with value in this module", |
c1a9b12d | 1021 | name); |
92a42be0 | 1022 | if let Some(span) = value.span { |
c34b1796 AL |
1023 | self.resolver.session.span_note(span, "conflicting value here"); |
1024 | } | |
1025 | } | |
1026 | } | |
1027 | Some(_) | None => {} | |
1028 | } | |
1029 | ||
1030 | match import_resolution.type_target { | |
1031 | Some(ref target) if target.shadowable != Shadowable::Always => { | |
92a42be0 SL |
1032 | if let Some(ref ty) = *name_bindings.type_ns.borrow() { |
1033 | let (what, note) = match ty.module() { | |
1034 | Some(ref module) if module.is_normal() => | |
1035 | ("existing submodule", "note conflicting module here"), | |
1036 | Some(ref module) if module.is_trait() => | |
1037 | ("trait in this module", "note conflicting trait here"), | |
1038 | _ => ("type in this module", "note conflicting type here"), | |
c34b1796 | 1039 | }; |
92a42be0 SL |
1040 | span_err!(self.resolver.session, |
1041 | import_span, | |
1042 | E0256, | |
c34b1796 | 1043 | "import `{}` conflicts with {}", |
92a42be0 SL |
1044 | name, |
1045 | what); | |
1046 | if let Some(span) = ty.span { | |
c34b1796 AL |
1047 | self.resolver.session.span_note(span, note); |
1048 | } | |
1049 | } | |
1050 | } | |
1051 | Some(_) | None => {} | |
1052 | } | |
1053 | } | |
1054 | } | |
1055 | ||
92a42be0 | 1056 | fn import_path_to_string(names: &[Name], subclass: ImportDirectiveSubclass) -> String { |
c34b1796 AL |
1057 | if names.is_empty() { |
1058 | import_directive_subclass_to_string(subclass) | |
1059 | } else { | |
1060 | (format!("{}::{}", | |
1061 | names_to_string(names), | |
92a42be0 SL |
1062 | import_directive_subclass_to_string(subclass))) |
1063 | .to_string() | |
c34b1796 AL |
1064 | } |
1065 | } | |
1066 | ||
1067 | fn import_directive_subclass_to_string(subclass: ImportDirectiveSubclass) -> String { | |
1068 | match subclass { | |
c1a9b12d | 1069 | SingleImport(_, source) => source.to_string(), |
92a42be0 | 1070 | GlobImport => "*".to_string(), |
c34b1796 AL |
1071 | } |
1072 | } | |
1073 | ||
1074 | pub fn resolve_imports(resolver: &mut Resolver) { | |
92a42be0 | 1075 | let mut import_resolver = ImportResolver { resolver: resolver }; |
c34b1796 AL |
1076 | import_resolver.resolve_imports(); |
1077 | } |