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.
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.
11 use self::ImportDirectiveSubclass
::*;
13 use {AmbiguityError, Module, PerNS}
;
14 use Namespace
::{self, TypeNS, MacroNS}
;
15 use {NameBinding, NameBindingKind, PathResult, PrivacyError}
;
17 use {names_to_string, module_to_string}
;
18 use {resolve_error, ResolutionError}
;
21 use rustc
::lint
::builtin
::PRIVATE_IN_PUBLIC
;
22 use rustc
::hir
::def_id
::DefId
;
23 use rustc
::hir
::def
::*;
24 use rustc
::util
::nodemap
::FxHashSet
;
26 use syntax
::ast
::{Ident, NodeId}
;
27 use syntax
::ext
::base
::Determinacy
::{self, Determined, Undetermined}
;
28 use syntax
::ext
::hygiene
::Mark
;
29 use syntax
::parse
::token
;
30 use syntax
::symbol
::keywords
;
31 use syntax
::util
::lev_distance
::find_best_match_for_name
;
34 use std
::cell
::{Cell, RefCell}
;
37 /// Contains data for specific types of import directives.
38 #[derive(Clone, Debug)]
39 pub enum ImportDirectiveSubclass
<'a
> {
43 result
: PerNS
<Cell
<Result
<&'a NameBinding
<'a
>, Determinacy
>>>,
48 max_vis
: Cell
<ty
::Visibility
>, // The visibility of the greatest reexport.
49 // n.b. `max_vis` is only used in `finalize_import` to check for reexport errors.
55 /// One import directive.
56 #[derive(Debug,Clone)]
57 pub struct ImportDirective
<'a
> {
59 pub parent
: Module
<'a
>,
60 pub module_path
: Vec
<Ident
>,
61 pub imported_module
: Cell
<Option
<Module
<'a
>>>, // the resolution of `module_path`
62 pub subclass
: ImportDirectiveSubclass
<'a
>,
64 pub vis
: Cell
<ty
::Visibility
>,
69 impl<'a
> ImportDirective
<'a
> {
70 pub fn is_glob(&self) -> bool
{
71 match self.subclass { ImportDirectiveSubclass::GlobImport { .. }
=> true, _
=> false }
75 #[derive(Clone, Default)]
76 /// Records information about the resolution of a name in a namespace of a module.
77 pub struct NameResolution
<'a
> {
78 /// The single imports that define the name in the namespace.
79 single_imports
: SingleImports
<'a
>,
80 /// The least shadowable known binding for this name, or None if there are no known bindings.
81 pub binding
: Option
<&'a NameBinding
<'a
>>,
82 shadows_glob
: Option
<&'a NameBinding
<'a
>>,
85 #[derive(Clone, Debug)]
86 enum SingleImports
<'a
> {
87 /// No single imports can define the name in the namespace.
89 /// Only the given single import can define the name in the namespace.
90 MaybeOne(&'a ImportDirective
<'a
>),
91 /// At least one single import will define the name in the namespace.
95 impl<'a
> Default
for SingleImports
<'a
> {
96 /// Creates a `SingleImports<'a>` of None type.
97 fn default() -> Self {
102 impl<'a
> SingleImports
<'a
> {
103 fn add_directive(&mut self, directive
: &'a ImportDirective
<'a
>) {
105 SingleImports
::None
=> *self = SingleImports
::MaybeOne(directive
),
106 // If two single imports can define the name in the namespace, we can assume that at
107 // least one of them will define it since otherwise both would have to define only one
108 // namespace, leading to a duplicate error.
109 SingleImports
::MaybeOne(_
) => *self = SingleImports
::AtLeastOne
,
110 SingleImports
::AtLeastOne
=> {}
114 fn directive_failed(&mut self) {
116 SingleImports
::None
=> unreachable
!(),
117 SingleImports
::MaybeOne(_
) => *self = SingleImports
::None
,
118 SingleImports
::AtLeastOne
=> {}
123 impl<'a
> NameResolution
<'a
> {
124 // Returns the binding for the name if it is known or None if it not known.
125 fn binding(&self) -> Option
<&'a NameBinding
<'a
>> {
126 self.binding
.and_then(|binding
| match self.single_imports
{
127 SingleImports
::None
=> Some(binding
),
128 _
if !binding
.is_glob_import() => Some(binding
),
129 _
=> None
, // The binding could be shadowed by a single import, so it is not known.
134 impl<'a
> Resolver
<'a
> {
135 fn resolution(&self, module
: Module
<'a
>, ident
: Ident
, ns
: Namespace
)
136 -> &'a RefCell
<NameResolution
<'a
>> {
137 let ident
= ident
.unhygienize();
138 *module
.resolutions
.borrow_mut().entry((ident
, ns
))
139 .or_insert_with(|| self.arenas
.alloc_name_resolution())
142 /// Attempts to resolve `ident` in namespaces `ns` of `module`.
143 /// Invariant: if `record_used` is `Some`, import resolution must be complete.
144 pub fn resolve_ident_in_module(&mut self,
148 ignore_unresolved_invocations
: bool
,
149 record_used
: Option
<Span
>)
150 -> Result
<&'a NameBinding
<'a
>, Determinacy
> {
151 self.populate_module_if_necessary(module
);
153 let resolution
= self.resolution(module
, ident
, ns
)
155 .map_err(|_
| Determined
)?
; // This happens when there is a cycle of imports
157 if let Some(span
) = record_used
{
158 if let Some(binding
) = resolution
.binding
{
159 if let Some(shadowed_glob
) = resolution
.shadows_glob
{
160 let name
= ident
.name
;
161 // If we ignore unresolved invocations, we must forbid
162 // expanded shadowing to avoid time travel.
163 if ignore_unresolved_invocations
&&
164 binding
.expansion
!= Mark
::root() &&
165 ns
!= MacroNS
&& // In MacroNS, `try_define` always forbids this shadowing
166 binding
.def() != shadowed_glob
.def() {
167 self.ambiguity_errors
.push(AmbiguityError
{
168 span
: span
, name
: name
, lexical
: false, b1
: binding
, b2
: shadowed_glob
,
173 if self.record_use(ident
, ns
, binding
, span
) {
174 return Ok(self.dummy_binding
);
176 if !self.is_accessible(binding
.vis
) {
177 self.privacy_errors
.push(PrivacyError(span
, ident
.name
, binding
));
181 return resolution
.binding
.ok_or(Determined
);
184 let check_usable
= |this
: &mut Self, binding
: &'a NameBinding
<'a
>| {
185 // `extern crate` are always usable for backwards compatability, see issue #37020.
186 let usable
= this
.is_accessible(binding
.vis
) || binding
.is_extern_crate();
187 if usable { Ok(binding) }
else { Err(Determined) }
190 // Items and single imports are not shadowable.
191 if let Some(binding
) = resolution
.binding
{
192 if !binding
.is_glob_import() {
193 return check_usable(self, binding
);
197 // Check if a single import can still define the name.
198 match resolution
.single_imports
{
199 SingleImports
::AtLeastOne
=> return Err(Undetermined
),
200 SingleImports
::MaybeOne(directive
) if self.is_accessible(directive
.vis
.get()) => {
201 let module
= match directive
.imported_module
.get() {
202 Some(module
) => module
,
203 None
=> return Err(Undetermined
),
205 let ident
= match directive
.subclass
{
206 SingleImport { source, .. }
=> source
,
209 match self.resolve_ident_in_module(module
, ident
, ns
, false, None
) {
210 Err(Determined
) => {}
211 _
=> return Err(Undetermined
),
214 SingleImports
::MaybeOne(_
) | SingleImports
::None
=> {}
,
217 let no_unresolved_invocations
=
218 ignore_unresolved_invocations
|| module
.unresolved_invocations
.borrow().is_empty();
219 match resolution
.binding
{
220 // In `MacroNS`, expanded bindings do not shadow (enforced in `try_define`).
221 Some(binding
) if no_unresolved_invocations
|| ns
== MacroNS
=>
222 return check_usable(self, binding
),
223 None
if no_unresolved_invocations
=> {}
224 _
=> return Err(Undetermined
),
227 // Check if the globs are determined
228 for directive
in module
.globs
.borrow().iter() {
229 if self.is_accessible(directive
.vis
.get()) {
230 if let Some(module
) = directive
.imported_module
.get() {
231 let result
= self.resolve_ident_in_module(module
, ident
, ns
, false, None
);
232 if let Err(Undetermined
) = result
{
233 return Err(Undetermined
);
236 return Err(Undetermined
);
244 // Add an import directive to the current module.
245 pub fn add_import_directive(&mut self,
246 module_path
: Vec
<Ident
>,
247 subclass
: ImportDirectiveSubclass
<'a
>,
252 let current_module
= self.current_module
;
253 let directive
= self.arenas
.alloc_import_directive(ImportDirective
{
254 parent
: current_module
,
255 module_path
: module_path
,
256 imported_module
: Cell
::new(None
),
261 expansion
: expansion
,
262 used
: Cell
::new(false),
265 self.indeterminate_imports
.push(directive
);
266 match directive
.subclass
{
267 SingleImport { target, .. }
=> {
268 self.per_ns(|this
, ns
| {
269 let mut resolution
= this
.resolution(current_module
, target
, ns
).borrow_mut();
270 resolution
.single_imports
.add_directive(directive
);
273 // We don't add prelude imports to the globs since they only affect lexical scopes,
274 // which are not relevant to import resolution.
275 GlobImport { is_prelude: true, .. }
=> {}
276 GlobImport { .. }
=> self.current_module
.globs
.borrow_mut().push(directive
),
281 // Given a binding and an import directive that resolves to it,
282 // return the corresponding binding defined by the import directive.
283 pub fn import(&self, binding
: &'a NameBinding
<'a
>, directive
: &'a ImportDirective
<'a
>)
284 -> &'a NameBinding
<'a
> {
285 let vis
= if binding
.pseudo_vis().is_at_least(directive
.vis
.get(), self) ||
286 !directive
.is_glob() && binding
.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
292 if let GlobImport { ref max_vis, .. }
= directive
.subclass
{
293 if vis
== directive
.vis
.get() || vis
.is_at_least(max_vis
.get(), self) {
298 self.arenas
.alloc_name_binding(NameBinding
{
299 kind
: NameBindingKind
::Import
{
301 directive
: directive
,
302 used
: Cell
::new(false),
303 legacy_self_import
: false,
305 span
: directive
.span
,
307 expansion
: directive
.expansion
,
311 // Define the name or return the existing binding if there is a collision.
312 pub fn try_define(&mut self,
316 binding
: &'a NameBinding
<'a
>)
317 -> Result
<(), &'a NameBinding
<'a
>> {
318 self.update_resolution(module
, ident
, ns
, |this
, resolution
| {
319 if let Some(old_binding
) = resolution
.binding
{
320 if binding
.is_glob_import() {
321 if !old_binding
.is_glob_import() &&
322 !(ns
== MacroNS
&& old_binding
.expansion
!= Mark
::root()) {
323 resolution
.shadows_glob
= Some(binding
);
324 } else if binding
.def() != old_binding
.def() {
325 resolution
.binding
= Some(this
.ambiguity(old_binding
, binding
));
326 } else if !old_binding
.vis
.is_at_least(binding
.vis
, &*this
) {
327 // We are glob-importing the same item but with greater visibility.
328 resolution
.binding
= Some(binding
);
330 } else if old_binding
.is_glob_import() {
331 if ns
== MacroNS
&& binding
.expansion
!= Mark
::root() &&
332 binding
.def() != old_binding
.def() {
333 resolution
.binding
= Some(this
.ambiguity(binding
, old_binding
));
335 resolution
.binding
= Some(binding
);
336 resolution
.shadows_glob
= Some(old_binding
);
339 return Err(old_binding
);
342 resolution
.binding
= Some(binding
);
349 pub fn ambiguity(&self, b1
: &'a NameBinding
<'a
>, b2
: &'a NameBinding
<'a
>)
350 -> &'a NameBinding
<'a
> {
351 self.arenas
.alloc_name_binding(NameBinding
{
352 kind
: NameBindingKind
::Ambiguity { b1: b1, b2: b2, legacy: false }
,
353 vis
: if b1
.vis
.is_at_least(b2
.vis
, self) { b1.vis }
else { b2.vis }
,
355 expansion
: Mark
::root(),
359 // Use `f` to mutate the resolution of the name in the module.
360 // If the resolution becomes a success, define it in the module's glob importers.
361 fn update_resolution
<T
, F
>(&mut self, module
: Module
<'a
>, ident
: Ident
, ns
: Namespace
, f
: F
)
363 where F
: FnOnce(&mut Resolver
<'a
>, &mut NameResolution
<'a
>) -> T
365 // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
366 // during which the resolution might end up getting re-defined via a glob cycle.
368 let mut resolution
= &mut *self.resolution(module
, ident
, ns
).borrow_mut();
369 let old_binding
= resolution
.binding();
371 let t
= f(self, resolution
);
373 match resolution
.binding() {
374 _
if old_binding
.is_some() => return t
,
376 Some(binding
) => match old_binding
{
377 Some(old_binding
) if old_binding
as *const _
== binding
as *const _
=> return t
,
383 // Define `binding` in `module`s glob importers.
384 for directive
in module
.glob_importers
.borrow_mut().iter() {
385 if self.is_accessible_from(binding
.vis
, directive
.parent
) {
386 let imported_binding
= self.import(binding
, directive
);
387 let _
= self.try_define(directive
.parent
, ident
, ns
, imported_binding
);
394 // Define a "dummy" resolution containing a Def::Err as a placeholder for a
396 fn import_dummy_binding(&mut self, directive
: &'a ImportDirective
<'a
>) {
397 if let SingleImport { target, .. }
= directive
.subclass
{
398 let dummy_binding
= self.dummy_binding
;
399 let dummy_binding
= self.import(dummy_binding
, directive
);
400 self.per_ns(|this
, ns
| {
401 let _
= this
.try_define(directive
.parent
, target
, ns
, dummy_binding
);
407 pub struct ImportResolver
<'a
, 'b
: 'a
> {
408 pub resolver
: &'a
mut Resolver
<'b
>,
411 impl<'a
, 'b
: 'a
> ::std
::ops
::Deref
for ImportResolver
<'a
, 'b
> {
412 type Target
= Resolver
<'b
>;
413 fn deref(&self) -> &Resolver
<'b
> {
418 impl<'a
, 'b
: 'a
> ::std
::ops
::DerefMut
for ImportResolver
<'a
, 'b
> {
419 fn deref_mut(&mut self) -> &mut Resolver
<'b
> {
424 impl<'a
, 'b
: 'a
> ty
::DefIdTree
for &'a ImportResolver
<'a
, 'b
> {
425 fn parent(self, id
: DefId
) -> Option
<DefId
> {
426 self.resolver
.parent(id
)
430 impl<'a
, 'b
:'a
> ImportResolver
<'a
, 'b
> {
433 // This is a fixed-point algorithm. We resolve imports until our efforts
434 // are stymied by an unresolved import; then we bail out of the current
435 // module and continue. We terminate successfully once no more imports
436 // remain or unsuccessfully when no forward progress in resolving imports
439 /// Resolves all imports for the crate. This method performs the fixed-
441 pub fn resolve_imports(&mut self) {
442 let mut prev_num_indeterminates
= self.indeterminate_imports
.len() + 1;
443 while self.indeterminate_imports
.len() < prev_num_indeterminates
{
444 prev_num_indeterminates
= self.indeterminate_imports
.len();
445 for import
in mem
::replace(&mut self.indeterminate_imports
, Vec
::new()) {
446 match self.resolve_import(&import
) {
447 true => self.determined_imports
.push(import
),
448 false => self.indeterminate_imports
.push(import
),
454 pub fn finalize_imports(&mut self) {
455 for module
in self.arenas
.local_modules().iter() {
456 self.finalize_resolutions_in(module
);
459 let mut errors
= false;
460 for i
in 0 .. self.determined_imports
.len() {
461 let import
= self.determined_imports
[i
];
462 if let Some(err
) = self.finalize_import(import
) {
465 // If the error is a single failed import then create a "fake" import
466 // resolution for it so that later resolve stages won't complain.
467 self.import_dummy_binding(import
);
468 let path
= import_path_to_string(&import
.module_path
, &import
.subclass
);
469 let error
= ResolutionError
::UnresolvedImport(Some((&path
, &err
)));
470 resolve_error(self.resolver
, import
.span
, error
);
474 // Report unresolved imports only if no hard error was already reported
475 // to avoid generating multiple errors on the same import.
477 if let Some(import
) = self.indeterminate_imports
.iter().next() {
478 let error
= ResolutionError
::UnresolvedImport(None
);
479 resolve_error(self.resolver
, import
.span
, error
);
484 /// Attempts to resolve the given import, returning true if its resolution is determined.
485 /// If successful, the resolved bindings are written into the module.
486 fn resolve_import(&mut self, directive
: &'b ImportDirective
<'b
>) -> bool
{
487 debug
!("(resolving import for module) resolving import `{}::...` in `{}`",
488 names_to_string(&directive
.module_path
),
489 module_to_string(self.current_module
));
491 self.current_module
= directive
.parent
;
493 let module
= if let Some(module
) = directive
.imported_module
.get() {
496 let vis
= directive
.vis
.get();
497 // For better failure detection, pretend that the import will not define any names
498 // while resolving its module path.
499 directive
.vis
.set(ty
::Visibility
::Invisible
);
500 let result
= self.resolve_path(&directive
.module_path
, None
, None
);
501 directive
.vis
.set(vis
);
504 PathResult
::Module(module
) => module
,
505 PathResult
::Indeterminate
=> return false,
510 directive
.imported_module
.set(Some(module
));
511 let (source
, target
, result
, type_ns_only
) = match directive
.subclass
{
512 SingleImport { source, target, ref result, type_ns_only }
=>
513 (source
, target
, result
, type_ns_only
),
514 GlobImport { .. }
=> {
515 self.resolve_glob_import(directive
);
521 let mut indeterminate
= false;
522 self.per_ns(|this
, ns
| if !type_ns_only
|| ns
== TypeNS
{
523 if let Err(Undetermined
) = result
[ns
].get() {
524 result
[ns
].set(this
.resolve_ident_in_module(module
, source
, ns
, false, None
));
529 let parent
= directive
.parent
;
530 match result
[ns
].get() {
531 Err(Undetermined
) => indeterminate
= true,
533 this
.update_resolution(parent
, target
, ns
, |_
, resolution
| {
534 resolution
.single_imports
.directive_failed()
537 Ok(binding
) if !binding
.is_importable() => {
538 let msg
= format
!("`{}` is not directly importable", target
);
539 struct_span_err
!(this
.session
, directive
.span
, E0253
, "{}", &msg
)
540 .span_label(directive
.span
, &format
!("cannot be imported directly"))
542 // Do not import this illegal binding. Import a dummy binding and pretend
543 // everything is fine
544 this
.import_dummy_binding(directive
);
547 let imported_binding
= this
.import(binding
, directive
);
548 let conflict
= this
.try_define(parent
, target
, ns
, imported_binding
);
549 if let Err(old_binding
) = conflict
{
550 this
.report_conflict(parent
, target
, ns
, imported_binding
, old_binding
);
559 // If appropriate, returns an error to report.
560 fn finalize_import(&mut self, directive
: &'b ImportDirective
<'b
>) -> Option
<String
> {
561 self.current_module
= directive
.parent
;
563 let ImportDirective { ref module_path, span, .. }
= *directive
;
564 let module_result
= self.resolve_path(&module_path
, None
, Some(span
));
565 let module
= match module_result
{
566 PathResult
::Module(module
) => module
,
567 PathResult
::Failed(msg
, _
) => {
568 let (mut self_path
, mut self_result
) = (module_path
.clone(), None
);
569 if !self_path
.is_empty() && !token
::Ident(self_path
[0]).is_path_segment_keyword() {
570 self_path
[0].name
= keywords
::SelfValue
.name();
571 self_result
= Some(self.resolve_path(&self_path
, None
, None
));
573 return if let Some(PathResult
::Module(..)) = self_result
{
574 Some(format
!("Did you mean `{}`?", names_to_string(&self_path
)))
582 let (ident
, result
, type_ns_only
) = match directive
.subclass
{
583 SingleImport { source, ref result, type_ns_only, .. }
=> (source
, result
, type_ns_only
),
584 GlobImport { .. }
if module
.def_id() == directive
.parent
.def_id() => {
585 // Importing a module into itself is not allowed.
586 return Some("Cannot glob-import a module into itself.".to_string());
588 GlobImport { is_prelude, ref max_vis }
=> {
590 max_vis
.get() != ty
::Visibility
::Invisible
&& // Allow empty globs.
591 !max_vis
.get().is_at_least(directive
.vis
.get(), &*self) {
592 let msg
= "A non-empty glob must import something with the glob's visibility";
593 self.session
.span_err(directive
.span
, msg
);
600 let mut all_ns_err
= true;
601 let mut legacy_self_import
= None
;
602 self.per_ns(|this
, ns
| if !type_ns_only
|| ns
== TypeNS
{
603 if let Ok(binding
) = result
[ns
].get() {
605 if this
.record_use(ident
, ns
, binding
, directive
.span
) {
606 this
.resolution(module
, ident
, ns
).borrow_mut().binding
=
607 Some(this
.dummy_binding
);
610 } else if let Ok(binding
) = this
.resolve_ident_in_module(module
, ident
, ns
, false, None
) {
611 legacy_self_import
= Some(directive
);
612 let binding
= this
.arenas
.alloc_name_binding(NameBinding
{
613 kind
: NameBindingKind
::Import
{
615 directive
: directive
,
616 used
: Cell
::new(false),
617 legacy_self_import
: true,
621 let _
= this
.try_define(directive
.parent
, ident
, ns
, binding
);
625 if let Some(directive
) = legacy_self_import
{
626 self.warn_legacy_self_import(directive
);
629 let mut all_ns_failed
= true;
630 self.per_ns(|this
, ns
| if !type_ns_only
|| ns
== TypeNS
{
631 match this
.resolve_ident_in_module(module
, ident
, ns
, false, Some(span
)) {
632 Ok(_
) => all_ns_failed
= false,
637 return if all_ns_failed
{
638 let resolutions
= module
.resolutions
.borrow();
639 let names
= resolutions
.iter().filter_map(|(&(ref i
, _
), resolution
)| {
640 if *i
== ident { return None; }
// Never suggest the same name
641 match *resolution
.borrow() {
642 NameResolution { binding: Some(name_binding), .. }
=> {
643 match name_binding
.kind
{
644 NameBindingKind
::Import { binding, .. }
=> {
646 // Never suggest the name that has binding error
647 // i.e. the name that cannot be previously resolved
648 NameBindingKind
::Def(Def
::Err
) => return None
,
655 NameResolution { single_imports: SingleImports::None, .. }
=> None
,
660 match find_best_match_for_name(names
, &ident
.name
.as_str(), None
) {
661 Some(name
) => format
!(". Did you mean to use `{}`?", name
),
662 None
=> "".to_owned(),
664 let module_str
= module_to_string(module
);
665 let msg
= if &module_str
== "???" {
666 format
!("no `{}` in the root{}", ident
, lev_suggestion
)
668 format
!("no `{}` in `{}`{}", ident
, module_str
, lev_suggestion
)
672 // `resolve_ident_in_module` reported a privacy error.
673 self.import_dummy_binding(directive
);
678 let mut reexport_error
= None
;
679 let mut any_successful_reexport
= false;
680 self.per_ns(|this
, ns
| {
681 if let Ok(binding
) = result
[ns
].get() {
682 let vis
= directive
.vis
.get();
683 if !binding
.pseudo_vis().is_at_least(vis
, &*this
) {
684 reexport_error
= Some((ns
, binding
));
686 any_successful_reexport
= true;
691 // All namespaces must be re-exported with extra visibility for an error to occur.
692 if !any_successful_reexport
{
693 let (ns
, binding
) = reexport_error
.unwrap();
694 if ns
== TypeNS
&& binding
.is_extern_crate() {
695 let msg
= format
!("extern crate `{}` is private, and cannot be reexported \
696 (error E0364), consider declaring with `pub`",
698 self.session
.add_lint(PRIVATE_IN_PUBLIC
, directive
.id
, directive
.span
, msg
);
699 } else if ns
== TypeNS
{
700 struct_span_err
!(self.session
, directive
.span
, E0365
,
701 "`{}` is private, and cannot be reexported", ident
)
702 .span_label(directive
.span
, &format
!("reexport of private `{}`", ident
))
703 .note(&format
!("consider declaring type or module `{}` with `pub`", ident
))
706 let msg
= format
!("`{}` is private, and cannot be reexported", ident
);
708 format
!("consider marking `{}` as `pub` in the imported module", ident
);
709 struct_span_err
!(self.session
, directive
.span
, E0364
, "{}", &msg
)
710 .span_note(directive
.span
, ¬e_msg
)
715 // Record what this import resolves to for later uses in documentation,
716 // this may resolve to either a value or a type, but for documentation
717 // purposes it's good enough to just favor one over the other.
718 self.per_ns(|this
, ns
| if let Some(binding
) = result
[ns
].get().ok() {
719 this
.def_map
.entry(directive
.id
).or_insert(PathResolution
::new(binding
.def()));
722 debug
!("(resolving single import) successfully resolved import");
726 fn resolve_glob_import(&mut self, directive
: &'b ImportDirective
<'b
>) {
727 let module
= directive
.imported_module
.get().unwrap();
728 self.populate_module_if_necessary(module
);
730 if let Some(Def
::Trait(_
)) = module
.def() {
731 self.session
.span_err(directive
.span
, "items in traits are not importable.");
733 } else if module
.def_id() == directive
.parent
.def_id() {
735 } else if let GlobImport { is_prelude: true, .. }
= directive
.subclass
{
736 self.prelude
= Some(module
);
740 // Add to module's glob_importers
741 module
.glob_importers
.borrow_mut().push(directive
);
743 // Ensure that `resolutions` isn't borrowed during `try_define`,
744 // since it might get updated via a glob cycle.
745 let bindings
= module
.resolutions
.borrow().iter().filter_map(|(&ident
, resolution
)| {
746 resolution
.borrow().binding().map(|binding
| (ident
, binding
))
747 }).collect
::<Vec
<_
>>();
748 for ((ident
, ns
), binding
) in bindings
{
749 if binding
.pseudo_vis() == ty
::Visibility
::Public
|| self.is_accessible(binding
.vis
) {
750 let imported_binding
= self.import(binding
, directive
);
751 let _
= self.try_define(directive
.parent
, ident
, ns
, imported_binding
);
755 // Record the destination of this import
756 self.record_def(directive
.id
, PathResolution
::new(module
.def().unwrap()));
759 // Miscellaneous post-processing, including recording reexports, reporting conflicts,
760 // reporting the PRIVATE_IN_PUBLIC lint, and reporting unresolved imports.
761 fn finalize_resolutions_in(&mut self, module
: Module
<'b
>) {
762 // Since import resolution is finished, globs will not define any more names.
763 *module
.globs
.borrow_mut() = Vec
::new();
765 let mut reexports
= Vec
::new();
766 if module
as *const _
== self.graph_root
as *const _
{
767 let mut exported_macro_names
= FxHashSet();
768 for export
in mem
::replace(&mut self.macro_exports
, Vec
::new()).into_iter().rev() {
769 if exported_macro_names
.insert(export
.name
) {
770 reexports
.push(export
);
775 for (&(ident
, ns
), resolution
) in module
.resolutions
.borrow().iter() {
776 let resolution
= &mut *resolution
.borrow_mut();
777 let binding
= match resolution
.binding
{
778 Some(binding
) => binding
,
782 if binding
.vis
== ty
::Visibility
::Public
&&
783 (binding
.is_import() || binding
.is_extern_crate()) {
784 let def
= binding
.def();
786 if !def
.def_id().is_local() {
787 self.session
.cstore
.export_macros(def
.def_id().krate
);
789 reexports
.push(Export { name: ident.name, def: def }
);
794 NameBindingKind
::Import { binding: orig_binding, directive, .. }
=> {
795 if ns
== TypeNS
&& orig_binding
.is_variant() &&
796 !orig_binding
.vis
.is_at_least(binding
.vis
, &*self) {
797 let msg
= format
!("variant `{}` is private, and cannot be reexported \
798 (error E0364), consider declaring its enum as `pub`",
800 self.session
.add_lint(PRIVATE_IN_PUBLIC
, directive
.id
, binding
.span
, msg
);
803 NameBindingKind
::Ambiguity { b1, b2, .. }
804 if b1
.is_glob_import() && b2
.is_glob_import() => {
805 let (orig_b1
, orig_b2
) = match (&b1
.kind
, &b2
.kind
) {
806 (&NameBindingKind
::Import { binding: b1, .. }
,
807 &NameBindingKind
::Import { binding: b2, .. }
) => (b1
, b2
),
810 let (b1
, b2
) = match (orig_b1
.vis
, orig_b2
.vis
) {
811 (ty
::Visibility
::Public
, ty
::Visibility
::Public
) => continue,
812 (ty
::Visibility
::Public
, _
) => (b1
, b2
),
813 (_
, ty
::Visibility
::Public
) => (b2
, b1
),
816 resolution
.binding
= Some(self.arenas
.alloc_name_binding(NameBinding
{
817 kind
: NameBindingKind
::Ambiguity { b1: b1, b2: b2, legacy: true }
, ..*b1
824 if reexports
.len() > 0 {
825 if let Some(def_id
) = module
.def_id() {
826 let node_id
= self.definitions
.as_local_node_id(def_id
).unwrap();
827 self.export_map
.insert(node_id
, reexports
);
833 fn import_path_to_string(names
: &[Ident
], subclass
: &ImportDirectiveSubclass
) -> String
{
834 let global
= !names
.is_empty() && names
[0].name
== keywords
::CrateRoot
.name();
835 let names
= if global { &names[1..] }
else { names }
;
836 if names
.is_empty() {
837 import_directive_subclass_to_string(subclass
)
840 names_to_string(names
),
841 import_directive_subclass_to_string(subclass
)))
846 fn import_directive_subclass_to_string(subclass
: &ImportDirectiveSubclass
) -> String
{
848 SingleImport { source, .. }
=> source
.to_string(),
849 GlobImport { .. }
=> "*".to_string(),
850 ExternCrate
=> "<extern crate>".to_string(),
851 MacroUse
=> "#[macro_use]".to_string(),