]> git.proxmox.com Git - rustc.git/blob - src/librustc_resolve/resolve_imports.rs
fe21e5295911c4edfb29f0f2442a3c6b3916a7ab
[rustc.git] / src / librustc_resolve / resolve_imports.rs
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::Determinacy::*;
12 use self::ImportDirectiveSubclass::*;
13
14 use Module;
15 use Namespace::{self, TypeNS, ValueNS};
16 use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding};
17 use ResolveResult;
18 use ResolveResult::*;
19 use Resolver;
20 use UseLexicalScopeFlag::DontUseLexicalScope;
21 use {names_to_string, module_to_string};
22 use {resolve_error, ResolutionError};
23
24 use rustc::ty;
25 use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
26 use rustc::hir::def::*;
27
28 use syntax::ast::{NodeId, Name};
29 use syntax::util::lev_distance::find_best_match_for_name;
30 use syntax_pos::Span;
31
32 use std::cell::{Cell, RefCell};
33
34 impl<'a> Resolver<'a> {
35 pub fn resolve_imports(&mut self) {
36 ImportResolver { resolver: self }.resolve_imports();
37 }
38 }
39
40 #[derive(Copy, Clone, Debug)]
41 pub enum Determinacy {
42 Determined,
43 Undetermined,
44 }
45
46 /// Contains data for specific types of import directives.
47 #[derive(Clone, Debug)]
48 pub enum ImportDirectiveSubclass<'a> {
49 SingleImport {
50 target: Name,
51 source: Name,
52 value_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
53 type_result: Cell<Result<&'a NameBinding<'a>, Determinacy>>,
54 },
55 GlobImport {
56 is_prelude: bool,
57 max_vis: Cell<ty::Visibility>, // The visibility of the greatest reexport.
58 // n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
59 },
60 }
61
62 impl<'a> ImportDirectiveSubclass<'a> {
63 pub fn single(target: Name, source: Name) -> Self {
64 SingleImport {
65 target: target,
66 source: source,
67 type_result: Cell::new(Err(Undetermined)),
68 value_result: Cell::new(Err(Undetermined)),
69 }
70 }
71 }
72
73 /// One import directive.
74 #[derive(Debug,Clone)]
75 pub struct ImportDirective<'a> {
76 pub id: NodeId,
77 parent: Module<'a>,
78 module_path: Vec<Name>,
79 imported_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
80 subclass: ImportDirectiveSubclass<'a>,
81 span: Span,
82 vis: Cell<ty::Visibility>,
83 }
84
85 impl<'a> ImportDirective<'a> {
86 pub fn is_glob(&self) -> bool {
87 match self.subclass { ImportDirectiveSubclass::GlobImport { .. } => true, _ => false }
88 }
89 }
90
91 #[derive(Clone, Default)]
92 /// Records information about the resolution of a name in a namespace of a module.
93 pub struct NameResolution<'a> {
94 /// The single imports that define the name in the namespace.
95 single_imports: SingleImports<'a>,
96 /// The least shadowable known binding for this name, or None if there are no known bindings.
97 pub binding: Option<&'a NameBinding<'a>>,
98 duplicate_globs: Vec<&'a NameBinding<'a>>,
99 }
100
101 #[derive(Clone, Debug)]
102 enum SingleImports<'a> {
103 /// No single imports can define the name in the namespace.
104 None,
105 /// Only the given single import can define the name in the namespace.
106 MaybeOne(&'a ImportDirective<'a>),
107 /// At least one single import will define the name in the namespace.
108 AtLeastOne,
109 }
110
111 impl<'a> Default for SingleImports<'a> {
112 /// Creates a `SingleImports<'a>` of None type.
113 fn default() -> Self {
114 SingleImports::None
115 }
116 }
117
118 impl<'a> SingleImports<'a> {
119 fn add_directive(&mut self, directive: &'a ImportDirective<'a>) {
120 match *self {
121 SingleImports::None => *self = SingleImports::MaybeOne(directive),
122 // If two single imports can define the name in the namespace, we can assume that at
123 // least one of them will define it since otherwise both would have to define only one
124 // namespace, leading to a duplicate error.
125 SingleImports::MaybeOne(_) => *self = SingleImports::AtLeastOne,
126 SingleImports::AtLeastOne => {}
127 };
128 }
129
130 fn directive_failed(&mut self) {
131 match *self {
132 SingleImports::None => unreachable!(),
133 SingleImports::MaybeOne(_) => *self = SingleImports::None,
134 SingleImports::AtLeastOne => {}
135 }
136 }
137 }
138
139 impl<'a> NameResolution<'a> {
140 // Returns the binding for the name if it is known or None if it not known.
141 fn binding(&self) -> Option<&'a NameBinding<'a>> {
142 self.binding.and_then(|binding| match self.single_imports {
143 SingleImports::None => Some(binding),
144 _ if !binding.is_glob_import() => Some(binding),
145 _ => None, // The binding could be shadowed by a single import, so it is not known.
146 })
147 }
148 }
149
150 impl<'a> Resolver<'a> {
151 fn resolution(&self, module: Module<'a>, name: Name, ns: Namespace)
152 -> &'a RefCell<NameResolution<'a>> {
153 *module.resolutions.borrow_mut().entry((name, ns))
154 .or_insert_with(|| self.arenas.alloc_name_resolution())
155 }
156
157 /// Attempts to resolve the supplied name in the given module for the given namespace.
158 /// If successful, returns the binding corresponding to the name.
159 /// Invariant: if `record_used` is `Some`, import resolution must be complete.
160 pub fn resolve_name_in_module(&mut self,
161 module: Module<'a>,
162 name: Name,
163 ns: Namespace,
164 allow_private_imports: bool,
165 record_used: Option<Span>)
166 -> ResolveResult<&'a NameBinding<'a>> {
167 self.populate_module_if_necessary(module);
168
169 let resolution = self.resolution(module, name, ns);
170 let resolution = match resolution.borrow_state() {
171 ::std::cell::BorrowState::Unused => resolution.borrow_mut(),
172 _ => return Failed(None), // This happens when there is a cycle of imports
173 };
174
175 let new_import_semantics = self.new_import_semantics;
176 let is_disallowed_private_import = |binding: &NameBinding| {
177 !new_import_semantics && !allow_private_imports && // disallowed
178 binding.vis != ty::Visibility::Public && binding.is_import() // non-`pub` import
179 };
180
181 if let Some(span) = record_used {
182 if let Some(binding) = resolution.binding {
183 if is_disallowed_private_import(binding) {
184 return Failed(None);
185 }
186 if self.record_use(name, ns, binding, span) {
187 return Success(self.dummy_binding);
188 }
189 if !self.is_accessible(binding.vis) {
190 self.privacy_errors.push(PrivacyError(span, name, binding));
191 }
192 }
193
194 return resolution.binding.map(Success).unwrap_or(Failed(None));
195 }
196
197 // If the resolution doesn't depend on glob definability, check privacy and return.
198 if let Some(result) = self.try_result(&resolution, ns) {
199 return result.and_then(|binding| {
200 if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) ||
201 binding.is_extern_crate() { // c.f. issue #37020
202 Success(binding)
203 } else {
204 Failed(None)
205 }
206 });
207 }
208
209 // Check if the globs are determined
210 for directive in module.globs.borrow().iter() {
211 if self.is_accessible(directive.vis.get()) {
212 if let Some(module) = directive.imported_module.get() {
213 let result = self.resolve_name_in_module(module, name, ns, true, None);
214 if let Indeterminate = result {
215 return Indeterminate;
216 }
217 } else {
218 return Indeterminate;
219 }
220 }
221 }
222
223 Failed(None)
224 }
225
226 // Returns Some(the resolution of the name), or None if the resolution depends
227 // on whether more globs can define the name.
228 fn try_result(&mut self, resolution: &NameResolution<'a>, ns: Namespace)
229 -> Option<ResolveResult<&'a NameBinding<'a>>> {
230 match resolution.binding {
231 Some(binding) if !binding.is_glob_import() =>
232 return Some(Success(binding)), // Items and single imports are not shadowable.
233 _ => {}
234 };
235
236 // Check if a single import can still define the name.
237 match resolution.single_imports {
238 SingleImports::AtLeastOne => return Some(Indeterminate),
239 SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => {
240 let module = match directive.imported_module.get() {
241 Some(module) => module,
242 None => return Some(Indeterminate),
243 };
244 let name = match directive.subclass {
245 SingleImport { source, .. } => source,
246 GlobImport { .. } => unreachable!(),
247 };
248 match self.resolve_name_in_module(module, name, ns, true, None) {
249 Failed(_) => {}
250 _ => return Some(Indeterminate),
251 }
252 }
253 SingleImports::MaybeOne(_) | SingleImports::None => {},
254 }
255
256 resolution.binding.map(Success)
257 }
258
259 // Add an import directive to the current module.
260 pub fn add_import_directive(&mut self,
261 module_path: Vec<Name>,
262 subclass: ImportDirectiveSubclass<'a>,
263 span: Span,
264 id: NodeId,
265 vis: ty::Visibility) {
266 let current_module = self.current_module;
267 let directive = self.arenas.alloc_import_directive(ImportDirective {
268 parent: current_module,
269 module_path: module_path,
270 imported_module: Cell::new(None),
271 subclass: subclass,
272 span: span,
273 id: id,
274 vis: Cell::new(vis),
275 });
276
277 self.indeterminate_imports.push(directive);
278 match directive.subclass {
279 SingleImport { target, .. } => {
280 for &ns in &[ValueNS, TypeNS] {
281 let mut resolution = self.resolution(current_module, target, ns).borrow_mut();
282 resolution.single_imports.add_directive(directive);
283 }
284 }
285 // We don't add prelude imports to the globs since they only affect lexical scopes,
286 // which are not relevant to import resolution.
287 GlobImport { is_prelude: true, .. } => {}
288 GlobImport { .. } => self.current_module.globs.borrow_mut().push(directive),
289 }
290 }
291
292 // Given a binding and an import directive that resolves to it,
293 // return the corresponding binding defined by the import directive.
294 fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
295 -> NameBinding<'a> {
296 let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
297 !directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
298 directive.vis.get()
299 } else {
300 binding.pseudo_vis()
301 };
302
303 if let GlobImport { ref max_vis, .. } = directive.subclass {
304 if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) {
305 max_vis.set(vis)
306 }
307 }
308
309 NameBinding {
310 kind: NameBindingKind::Import {
311 binding: binding,
312 directive: directive,
313 used: Cell::new(false),
314 },
315 span: directive.span,
316 vis: vis,
317 }
318 }
319
320 // Define the name or return the existing binding if there is a collision.
321 pub fn try_define<T>(&mut self, module: Module<'a>, name: Name, ns: Namespace, binding: T)
322 -> Result<(), &'a NameBinding<'a>>
323 where T: ToNameBinding<'a>
324 {
325 let binding = self.arenas.alloc_name_binding(binding.to_name_binding());
326 self.update_resolution(module, name, ns, |this, resolution| {
327 if let Some(old_binding) = resolution.binding {
328 if binding.is_glob_import() {
329 if !this.new_import_semantics || !old_binding.is_glob_import() {
330 resolution.duplicate_globs.push(binding);
331 } else if binding.def() != old_binding.def() {
332 resolution.binding = Some(this.arenas.alloc_name_binding(NameBinding {
333 kind: NameBindingKind::Ambiguity {
334 b1: old_binding,
335 b2: binding,
336 },
337 vis: if old_binding.vis.is_at_least(binding.vis, this) {
338 old_binding.vis
339 } else {
340 binding.vis
341 },
342 span: old_binding.span,
343 }));
344 } else if !old_binding.vis.is_at_least(binding.vis, this) {
345 // We are glob-importing the same item but with greater visibility.
346 resolution.binding = Some(binding);
347 }
348 } else if old_binding.is_glob_import() {
349 resolution.duplicate_globs.push(old_binding);
350 resolution.binding = Some(binding);
351 } else {
352 return Err(old_binding);
353 }
354 } else {
355 resolution.binding = Some(binding);
356 }
357
358 Ok(())
359 })
360 }
361
362 // Use `f` to mutate the resolution of the name in the module.
363 // If the resolution becomes a success, define it in the module's glob importers.
364 fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namespace, f: F) -> T
365 where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T
366 {
367 // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
368 // during which the resolution might end up getting re-defined via a glob cycle.
369 let (binding, t) = {
370 let mut resolution = &mut *self.resolution(module, name, ns).borrow_mut();
371 let old_binding = resolution.binding();
372
373 let t = f(self, resolution);
374
375 match resolution.binding() {
376 _ if !self.new_import_semantics && old_binding.is_some() => return t,
377 None => return t,
378 Some(binding) => match old_binding {
379 Some(old_binding) if old_binding as *const _ == binding as *const _ => return t,
380 _ => (binding, t),
381 }
382 }
383 };
384
385 // Define `binding` in `module`s glob importers.
386 for directive in module.glob_importers.borrow_mut().iter() {
387 if match self.new_import_semantics {
388 true => self.is_accessible_from(binding.vis, directive.parent),
389 false => binding.vis == ty::Visibility::Public,
390 } {
391 let imported_binding = self.import(binding, directive);
392 let _ = self.try_define(directive.parent, name, ns, imported_binding);
393 }
394 }
395
396 t
397 }
398 }
399
400 struct ImportResolver<'a, 'b: 'a> {
401 resolver: &'a mut Resolver<'b>,
402 }
403
404 impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> {
405 type Target = Resolver<'b>;
406 fn deref(&self) -> &Resolver<'b> {
407 self.resolver
408 }
409 }
410
411 impl<'a, 'b: 'a> ::std::ops::DerefMut for ImportResolver<'a, 'b> {
412 fn deref_mut(&mut self) -> &mut Resolver<'b> {
413 self.resolver
414 }
415 }
416
417 impl<'a, 'b: 'a> ty::NodeIdTree for ImportResolver<'a, 'b> {
418 fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
419 self.resolver.is_descendant_of(node, ancestor)
420 }
421 }
422
423 impl<'a, 'b:'a> ImportResolver<'a, 'b> {
424 // Import resolution
425 //
426 // This is a fixed-point algorithm. We resolve imports until our efforts
427 // are stymied by an unresolved import; then we bail out of the current
428 // module and continue. We terminate successfully once no more imports
429 // remain or unsuccessfully when no forward progress in resolving imports
430 // is made.
431
432 /// Resolves all imports for the crate. This method performs the fixed-
433 /// point iteration.
434 fn resolve_imports(&mut self) {
435 let mut i = 0;
436 let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
437
438 while self.indeterminate_imports.len() < prev_num_indeterminates {
439 prev_num_indeterminates = self.indeterminate_imports.len();
440 debug!("(resolving imports) iteration {}, {} imports left", i, prev_num_indeterminates);
441
442 let mut imports = Vec::new();
443 ::std::mem::swap(&mut imports, &mut self.indeterminate_imports);
444
445 for import in imports {
446 match self.resolve_import(&import) {
447 Failed(_) => self.determined_imports.push(import),
448 Indeterminate => self.indeterminate_imports.push(import),
449 Success(()) => self.determined_imports.push(import),
450 }
451 }
452
453 i += 1;
454 }
455
456 for module in self.arenas.local_modules().iter() {
457 self.finalize_resolutions_in(module);
458 }
459
460 let mut errors = false;
461 for i in 0 .. self.determined_imports.len() {
462 let import = self.determined_imports[i];
463 if let Failed(err) = self.finalize_import(import) {
464 errors = true;
465 let (span, help) = match err {
466 Some((span, msg)) => (span, msg),
467 None => continue,
468 };
469
470 // If the error is a single failed import then create a "fake" import
471 // resolution for it so that later resolve stages won't complain.
472 self.import_dummy_binding(import);
473 let path = import_path_to_string(&import.module_path, &import.subclass);
474 let error = ResolutionError::UnresolvedImport(Some((&path, &help)));
475 resolve_error(self.resolver, span, error);
476 }
477 }
478
479 // Report unresolved imports only if no hard error was already reported
480 // to avoid generating multiple errors on the same import.
481 if !errors {
482 if let Some(import) = self.indeterminate_imports.iter().next() {
483 let error = ResolutionError::UnresolvedImport(None);
484 resolve_error(self.resolver, import.span, error);
485 }
486 }
487 }
488
489 // Define a "dummy" resolution containing a Def::Err as a placeholder for a
490 // failed resolution
491 fn import_dummy_binding(&mut self, directive: &'b ImportDirective<'b>) {
492 if let SingleImport { target, .. } = directive.subclass {
493 let dummy_binding = self.dummy_binding;
494 let dummy_binding = self.import(dummy_binding, directive);
495 let _ = self.try_define(directive.parent, target, ValueNS, dummy_binding.clone());
496 let _ = self.try_define(directive.parent, target, TypeNS, dummy_binding);
497 }
498 }
499
500 /// Attempts to resolve the given import. The return value indicates
501 /// failure if we're certain the name does not exist, indeterminate if we
502 /// don't know whether the name exists at the moment due to other
503 /// currently-unresolved imports, or success if we know the name exists.
504 /// If successful, the resolved bindings are written into the module.
505 fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResult<()> {
506 debug!("(resolving import for module) resolving import `{}::...` in `{}`",
507 names_to_string(&directive.module_path),
508 module_to_string(self.current_module));
509
510 self.current_module = directive.parent;
511
512 let module = if let Some(module) = directive.imported_module.get() {
513 module
514 } else {
515 let vis = directive.vis.get();
516 // For better failure detection, pretend that the import will not define any names
517 // while resolving its module path.
518 directive.vis.set(ty::Visibility::PrivateExternal);
519 let result =
520 self.resolve_module_path(&directive.module_path, DontUseLexicalScope, None);
521 directive.vis.set(vis);
522
523 match result {
524 Success(module) => module,
525 Indeterminate => return Indeterminate,
526 Failed(err) => return Failed(err),
527 }
528 };
529
530 directive.imported_module.set(Some(module));
531 let (source, target, value_result, type_result) = match directive.subclass {
532 SingleImport { source, target, ref value_result, ref type_result } =>
533 (source, target, value_result, type_result),
534 GlobImport { .. } => {
535 self.resolve_glob_import(directive);
536 return Success(());
537 }
538 };
539
540 let mut indeterminate = false;
541 for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
542 if let Err(Undetermined) = result.get() {
543 result.set({
544 match self.resolve_name_in_module(module, source, ns, false, None) {
545 Success(binding) => Ok(binding),
546 Indeterminate => Err(Undetermined),
547 Failed(_) => Err(Determined),
548 }
549 });
550 } else {
551 continue
552 };
553
554 match result.get() {
555 Err(Undetermined) => indeterminate = true,
556 Err(Determined) => {
557 self.update_resolution(directive.parent, target, ns, |_, resolution| {
558 resolution.single_imports.directive_failed()
559 });
560 }
561 Ok(binding) if !binding.is_importable() => {
562 let msg = format!("`{}` is not directly importable", target);
563 struct_span_err!(self.session, directive.span, E0253, "{}", &msg)
564 .span_label(directive.span, &format!("cannot be imported directly"))
565 .emit();
566 // Do not import this illegal binding. Import a dummy binding and pretend
567 // everything is fine
568 self.import_dummy_binding(directive);
569 return Success(());
570 }
571 Ok(binding) => {
572 let imported_binding = self.import(binding, directive);
573 let conflict = self.try_define(directive.parent, target, ns, imported_binding);
574 if let Err(old_binding) = conflict {
575 let binding = &self.import(binding, directive);
576 self.report_conflict(directive.parent, target, ns, binding, old_binding);
577 }
578 }
579 }
580 }
581
582 if indeterminate { Indeterminate } else { Success(()) }
583 }
584
585 fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResult<()> {
586 self.current_module = directive.parent;
587
588 let ImportDirective { ref module_path, span, .. } = *directive;
589 let module_result = self.resolve_module_path(&module_path, DontUseLexicalScope, Some(span));
590 let module = match module_result {
591 Success(module) => module,
592 Indeterminate => return Indeterminate,
593 Failed(err) => {
594 let self_module = self.module_map[&self.current_module.normal_ancestor_id.unwrap()];
595
596 let resolve_from_self_result = self.resolve_module_path_from_root(
597 &self_module, &module_path, 0, Some(span));
598
599 return if let Success(_) = resolve_from_self_result {
600 let msg = format!("Did you mean `self::{}`?", &names_to_string(module_path));
601 Failed(Some((span, msg)))
602 } else {
603 Failed(err)
604 };
605 },
606 };
607
608 let (name, value_result, type_result) = match directive.subclass {
609 SingleImport { source, ref value_result, ref type_result, .. } =>
610 (source, value_result.get(), type_result.get()),
611 GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
612 // Importing a module into itself is not allowed.
613 let msg = "Cannot glob-import a module into itself.".into();
614 return Failed(Some((directive.span, msg)));
615 }
616 GlobImport { is_prelude, ref max_vis } => {
617 if !is_prelude &&
618 max_vis.get() != ty::Visibility::PrivateExternal && // Allow empty globs.
619 !max_vis.get().is_at_least(directive.vis.get(), self) {
620 let msg = "A non-empty glob must import something with the glob's visibility";
621 self.session.span_err(directive.span, msg);
622 }
623 return Success(());
624 }
625 };
626
627 for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
628 if let Ok(binding) = result {
629 if self.record_use(name, ns, binding, directive.span) {
630 self.resolution(module, name, ns).borrow_mut().binding =
631 Some(self.dummy_binding);
632 }
633 }
634 }
635
636 if value_result.is_err() && type_result.is_err() {
637 let (value_result, type_result);
638 value_result = self.resolve_name_in_module(module, name, ValueNS, false, Some(span));
639 type_result = self.resolve_name_in_module(module, name, TypeNS, false, Some(span));
640
641 return if let (Failed(_), Failed(_)) = (value_result, type_result) {
642 let resolutions = module.resolutions.borrow();
643 let names = resolutions.iter().filter_map(|(&(ref n, _), resolution)| {
644 if *n == name { return None; } // Never suggest the same name
645 match *resolution.borrow() {
646 NameResolution { binding: Some(_), .. } => Some(n),
647 NameResolution { single_imports: SingleImports::None, .. } => None,
648 _ => Some(n),
649 }
650 });
651 let lev_suggestion = match find_best_match_for_name(names, &name.as_str(), None) {
652 Some(name) => format!(". Did you mean to use `{}`?", name),
653 None => "".to_owned(),
654 };
655 let module_str = module_to_string(module);
656 let msg = if &module_str == "???" {
657 format!("no `{}` in the root{}", name, lev_suggestion)
658 } else {
659 format!("no `{}` in `{}`{}", name, module_str, lev_suggestion)
660 };
661 Failed(Some((directive.span, msg)))
662 } else {
663 // `resolve_name_in_module` reported a privacy error.
664 self.import_dummy_binding(directive);
665 Success(())
666 }
667 }
668
669 let session = self.session;
670 let reexport_error = || {
671 let msg = format!("`{}` is private, and cannot be reexported", name);
672 let note_msg =
673 format!("consider marking `{}` as `pub` in the imported module", name);
674 struct_span_err!(session, directive.span, E0364, "{}", &msg)
675 .span_note(directive.span, &note_msg)
676 .emit();
677 };
678
679 let extern_crate_lint = || {
680 let msg = format!("extern crate `{}` is private, and cannot be reexported \
681 (error E0364), consider declaring with `pub`",
682 name);
683 session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
684 };
685
686 match (value_result, type_result) {
687 // With `#![feature(item_like_imports)]`, all namespaces
688 // must be re-exported with extra visibility for an error to occur.
689 (Ok(value_binding), Ok(type_binding)) if self.new_import_semantics => {
690 let vis = directive.vis.get();
691 if !value_binding.pseudo_vis().is_at_least(vis, self) &&
692 !type_binding.pseudo_vis().is_at_least(vis, self) {
693 reexport_error();
694 } else if type_binding.is_extern_crate() &&
695 !type_binding.vis.is_at_least(vis, self) {
696 extern_crate_lint();
697 }
698 }
699
700 (Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
701 reexport_error();
702 }
703
704 (_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis.get(), self) => {
705 if binding.is_extern_crate() {
706 extern_crate_lint();
707 } else {
708 struct_span_err!(self.session, directive.span, E0365,
709 "`{}` is private, and cannot be reexported", name)
710 .span_label(directive.span, &format!("reexport of private `{}`", name))
711 .note(&format!("consider declaring type or module `{}` with `pub`", name))
712 .emit();
713 }
714 }
715
716 _ => {}
717 }
718
719 // Record what this import resolves to for later uses in documentation,
720 // this may resolve to either a value or a type, but for documentation
721 // purposes it's good enough to just favor one over the other.
722 let def = match type_result.ok().map(NameBinding::def) {
723 Some(def) => def,
724 None => value_result.ok().map(NameBinding::def).unwrap(),
725 };
726 let path_resolution = PathResolution::new(def);
727 self.def_map.insert(directive.id, path_resolution);
728
729 debug!("(resolving single import) successfully resolved import");
730 return Success(());
731 }
732
733 fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
734 let module = directive.imported_module.get().unwrap();
735 self.populate_module_if_necessary(module);
736
737 if let Some(Def::Trait(_)) = module.def() {
738 self.session.span_err(directive.span, "items in traits are not importable.");
739 return;
740 } else if module.def_id() == directive.parent.def_id() {
741 return;
742 } else if let GlobImport { is_prelude: true, .. } = directive.subclass {
743 self.prelude = Some(module);
744 return;
745 }
746
747 // Add to module's glob_importers
748 module.glob_importers.borrow_mut().push(directive);
749
750 // Ensure that `resolutions` isn't borrowed during `try_define`,
751 // since it might get updated via a glob cycle.
752 let bindings = module.resolutions.borrow().iter().filter_map(|(name, resolution)| {
753 resolution.borrow().binding().map(|binding| (*name, binding))
754 }).collect::<Vec<_>>();
755 for ((name, ns), binding) in bindings {
756 if binding.pseudo_vis() == ty::Visibility::Public ||
757 self.new_import_semantics && self.is_accessible(binding.vis) {
758 let imported_binding = self.import(binding, directive);
759 let _ = self.try_define(directive.parent, name, ns, imported_binding);
760 }
761 }
762
763 // Record the destination of this import
764 if let Some(did) = module.def_id() {
765 let resolution = PathResolution::new(Def::Mod(did));
766 self.def_map.insert(directive.id, resolution);
767 }
768 }
769
770 // Miscellaneous post-processing, including recording reexports, reporting conflicts,
771 // reporting the PRIVATE_IN_PUBLIC lint, and reporting unresolved imports.
772 fn finalize_resolutions_in(&mut self, module: Module<'b>) {
773 // Since import resolution is finished, globs will not define any more names.
774 *module.globs.borrow_mut() = Vec::new();
775
776 let mut reexports = Vec::new();
777 for (&(name, ns), resolution) in module.resolutions.borrow().iter() {
778 let resolution = resolution.borrow();
779 let binding = match resolution.binding {
780 Some(binding) => binding,
781 None => continue,
782 };
783
784 // Report conflicts
785 if !self.new_import_semantics {
786 for duplicate_glob in resolution.duplicate_globs.iter() {
787 // FIXME #31337: We currently allow items to shadow glob-imported re-exports.
788 if !binding.is_import() {
789 if let NameBindingKind::Import { binding, .. } = duplicate_glob.kind {
790 if binding.is_import() { continue }
791 }
792 }
793
794 self.report_conflict(module, name, ns, duplicate_glob, binding);
795 }
796 }
797
798 if binding.vis == ty::Visibility::Public &&
799 (binding.is_import() || binding.is_extern_crate()) {
800 let def = binding.def();
801 if def != Def::Err {
802 reexports.push(Export { name: name, def_id: def.def_id() });
803 }
804 }
805
806 if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
807 if ns == TypeNS && orig_binding.is_variant() &&
808 !orig_binding.vis.is_at_least(binding.vis, self) {
809 let msg = format!("variant `{}` is private, and cannot be reexported \
810 (error E0364), consider declaring its enum as `pub`",
811 name);
812 self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, binding.span, msg);
813 }
814 }
815 }
816
817 if reexports.len() > 0 {
818 if let Some(def_id) = module.def_id() {
819 let node_id = self.definitions.as_local_node_id(def_id).unwrap();
820 self.export_map.insert(node_id, reexports);
821 }
822 }
823 }
824 }
825
826 fn import_path_to_string(names: &[Name], subclass: &ImportDirectiveSubclass) -> String {
827 if names.is_empty() {
828 import_directive_subclass_to_string(subclass)
829 } else {
830 (format!("{}::{}",
831 names_to_string(names),
832 import_directive_subclass_to_string(subclass)))
833 .to_string()
834 }
835 }
836
837 fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass) -> String {
838 match *subclass {
839 SingleImport { source, .. } => source.to_string(),
840 GlobImport { .. } => "*".to_string(),
841 }
842 }