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::Determinacy
::*;
12 use self::ImportDirectiveSubclass
::*;
15 use Namespace
::{self, TypeNS, ValueNS}
;
16 use {NameBinding, NameBindingKind, PrivacyError, ToNameBinding}
;
20 use UseLexicalScopeFlag
::DontUseLexicalScope
;
21 use {names_to_string, module_to_string}
;
22 use {resolve_error, ResolutionError}
;
25 use rustc
::lint
::builtin
::PRIVATE_IN_PUBLIC
;
26 use rustc
::hir
::def
::*;
28 use syntax
::ast
::{NodeId, Name}
;
29 use syntax
::util
::lev_distance
::find_best_match_for_name
;
32 use std
::cell
::{Cell, RefCell}
;
34 impl<'a
> Resolver
<'a
> {
35 pub fn resolve_imports(&mut self) {
36 ImportResolver { resolver: self }
.resolve_imports();
40 #[derive(Copy, Clone, Debug)]
41 pub enum Determinacy
{
46 /// Contains data for specific types of import directives.
47 #[derive(Clone, Debug)]
48 pub enum ImportDirectiveSubclass
<'a
> {
52 value_result
: Cell
<Result
<&'a NameBinding
<'a
>, Determinacy
>>,
53 type_result
: Cell
<Result
<&'a NameBinding
<'a
>, Determinacy
>>,
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.
62 impl<'a
> ImportDirectiveSubclass
<'a
> {
63 pub fn single(target
: Name
, source
: Name
) -> Self {
67 type_result
: Cell
::new(Err(Undetermined
)),
68 value_result
: Cell
::new(Err(Undetermined
)),
73 /// One import directive.
74 #[derive(Debug,Clone)]
75 pub struct ImportDirective
<'a
> {
78 module_path
: Vec
<Name
>,
79 imported_module
: Cell
<Option
<Module
<'a
>>>, // the resolution of `module_path`
80 subclass
: ImportDirectiveSubclass
<'a
>,
82 vis
: Cell
<ty
::Visibility
>,
85 impl<'a
> ImportDirective
<'a
> {
86 pub fn is_glob(&self) -> bool
{
87 match self.subclass { ImportDirectiveSubclass::GlobImport { .. }
=> true, _
=> false }
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
>>,
101 #[derive(Clone, Debug)]
102 enum SingleImports
<'a
> {
103 /// No single imports can define the name in the namespace.
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.
111 impl<'a
> Default
for SingleImports
<'a
> {
112 /// Creates a `SingleImports<'a>` of None type.
113 fn default() -> Self {
118 impl<'a
> SingleImports
<'a
> {
119 fn add_directive(&mut self, directive
: &'a ImportDirective
<'a
>) {
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
=> {}
130 fn directive_failed(&mut self) {
132 SingleImports
::None
=> unreachable
!(),
133 SingleImports
::MaybeOne(_
) => *self = SingleImports
::None
,
134 SingleImports
::AtLeastOne
=> {}
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.
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())
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,
164 allow_private_imports
: bool
,
165 record_used
: Option
<Span
>)
166 -> ResolveResult
<&'a NameBinding
<'a
>> {
167 self.populate_module_if_necessary(module
);
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
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
181 if let Some(span
) = record_used
{
182 if let Some(binding
) = resolution
.binding
{
183 if is_disallowed_private_import(binding
) {
186 if self.record_use(name
, ns
, binding
, span
) {
187 return Success(self.dummy_binding
);
189 if !self.is_accessible(binding
.vis
) {
190 self.privacy_errors
.push(PrivacyError(span
, name
, binding
));
194 return resolution
.binding
.map(Success
).unwrap_or(Failed(None
));
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
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
;
218 return Indeterminate
;
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.
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
),
244 let name
= match directive
.subclass
{
245 SingleImport { source, .. }
=> source
,
246 GlobImport { .. }
=> unreachable
!(),
248 match self.resolve_name_in_module(module
, name
, ns
, true, None
) {
250 _
=> return Some(Indeterminate
),
253 SingleImports
::MaybeOne(_
) | SingleImports
::None
=> {}
,
256 resolution
.binding
.map(Success
)
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
>,
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
),
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
);
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
),
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
>)
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`
303 if let GlobImport { ref max_vis, .. }
= directive
.subclass
{
304 if vis
== directive
.vis
.get() || vis
.is_at_least(max_vis
.get(), self) {
310 kind
: NameBindingKind
::Import
{
312 directive
: directive
,
313 used
: Cell
::new(false),
315 span
: directive
.span
,
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
>
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
{
337 vis
: if old_binding
.vis
.is_at_least(binding
.vis
, this
) {
342 span
: old_binding
.span
,
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
);
348 } else if old_binding
.is_glob_import() {
349 resolution
.duplicate_globs
.push(old_binding
);
350 resolution
.binding
= Some(binding
);
352 return Err(old_binding
);
355 resolution
.binding
= Some(binding
);
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
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.
370 let mut resolution
= &mut *self.resolution(module
, name
, ns
).borrow_mut();
371 let old_binding
= resolution
.binding();
373 let t
= f(self, resolution
);
375 match resolution
.binding() {
376 _
if !self.new_import_semantics
&& old_binding
.is_some() => return t
,
378 Some(binding
) => match old_binding
{
379 Some(old_binding
) if old_binding
as *const _
== binding
as *const _
=> return t
,
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
,
391 let imported_binding
= self.import(binding
, directive
);
392 let _
= self.try_define(directive
.parent
, name
, ns
, imported_binding
);
400 struct ImportResolver
<'a
, 'b
: 'a
> {
401 resolver
: &'a
mut Resolver
<'b
>,
404 impl<'a
, 'b
: 'a
> ::std
::ops
::Deref
for ImportResolver
<'a
, 'b
> {
405 type Target
= Resolver
<'b
>;
406 fn deref(&self) -> &Resolver
<'b
> {
411 impl<'a
, 'b
: 'a
> ::std
::ops
::DerefMut
for ImportResolver
<'a
, 'b
> {
412 fn deref_mut(&mut self) -> &mut Resolver
<'b
> {
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
)
423 impl<'a
, 'b
:'a
> ImportResolver
<'a
, 'b
> {
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
432 /// Resolves all imports for the crate. This method performs the fixed-
434 fn resolve_imports(&mut self) {
436 let mut prev_num_indeterminates
= self.indeterminate_imports
.len() + 1;
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
);
442 let mut imports
= Vec
::new();
443 ::std
::mem
::swap(&mut imports
, &mut self.indeterminate_imports
);
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
),
456 for module
in self.arenas
.local_modules().iter() {
457 self.finalize_resolutions_in(module
);
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
) {
465 let (span
, help
) = match err
{
466 Some((span
, msg
)) => (span
, msg
),
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
);
479 // Report unresolved imports only if no hard error was already reported
480 // to avoid generating multiple errors on the same import.
482 if let Some(import
) = self.indeterminate_imports
.iter().next() {
483 let error
= ResolutionError
::UnresolvedImport(None
);
484 resolve_error(self.resolver
, import
.span
, error
);
489 // Define a "dummy" resolution containing a Def::Err as a placeholder for a
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
);
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
));
510 self.current_module
= directive
.parent
;
512 let module
= if let Some(module
) = directive
.imported_module
.get() {
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
);
520 self.resolve_module_path(&directive
.module_path
, DontUseLexicalScope
, None
);
521 directive
.vis
.set(vis
);
524 Success(module
) => module
,
525 Indeterminate
=> return Indeterminate
,
526 Failed(err
) => return Failed(err
),
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
);
540 let mut indeterminate
= false;
541 for &(ns
, result
) in &[(ValueNS
, value_result
), (TypeNS
, type_result
)] {
542 if let Err(Undetermined
) = result
.get() {
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
),
555 Err(Undetermined
) => indeterminate
= true,
557 self.update_resolution(directive
.parent
, target
, ns
, |_
, resolution
| {
558 resolution
.single_imports
.directive_failed()
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"))
566 // Do not import this illegal binding. Import a dummy binding and pretend
567 // everything is fine
568 self.import_dummy_binding(directive
);
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
);
582 if indeterminate { Indeterminate }
else { Success(()) }
585 fn finalize_import(&mut self, directive
: &'b ImportDirective
<'b
>) -> ResolveResult
<()> {
586 self.current_module
= directive
.parent
;
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
,
594 let self_module
= self.module_map
[&self.current_module
.normal_ancestor_id
.unwrap()];
596 let resolve_from_self_result
= self.resolve_module_path_from_root(
597 &self_module
, &module_path
, 0, Some(span
));
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
)))
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
)));
616 GlobImport { is_prelude, ref max_vis }
=> {
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
);
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
);
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
));
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
,
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(),
655 let module_str
= module_to_string(module
);
656 let msg
= if &module_str
== "???" {
657 format
!("no `{}` in the root{}", name
, lev_suggestion
)
659 format
!("no `{}` in `{}`{}", name
, module_str
, lev_suggestion
)
661 Failed(Some((directive
.span
, msg
)))
663 // `resolve_name_in_module` reported a privacy error.
664 self.import_dummy_binding(directive
);
669 let session
= self.session
;
670 let reexport_error
= || {
671 let msg
= format
!("`{}` is private, and cannot be reexported", name
);
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
, ¬e_msg
)
679 let extern_crate_lint
= || {
680 let msg
= format
!("extern crate `{}` is private, and cannot be reexported \
681 (error E0364), consider declaring with `pub`",
683 session
.add_lint(PRIVATE_IN_PUBLIC
, directive
.id
, directive
.span
, msg
);
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) {
694 } else if type_binding
.is_extern_crate() &&
695 !type_binding
.vis
.is_at_least(vis
, self) {
700 (Ok(binding
), _
) if !binding
.pseudo_vis().is_at_least(directive
.vis
.get(), self) => {
704 (_
, Ok(binding
)) if !binding
.pseudo_vis().is_at_least(directive
.vis
.get(), self) => {
705 if binding
.is_extern_crate() {
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
))
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
) {
724 None
=> value_result
.ok().map(NameBinding
::def
).unwrap(),
726 let path_resolution
= PathResolution
::new(def
);
727 self.def_map
.insert(directive
.id
, path_resolution
);
729 debug
!("(resolving single import) successfully resolved import");
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
);
737 if let Some(Def
::Trait(_
)) = module
.def() {
738 self.session
.span_err(directive
.span
, "items in traits are not importable.");
740 } else if module
.def_id() == directive
.parent
.def_id() {
742 } else if let GlobImport { is_prelude: true, .. }
= directive
.subclass
{
743 self.prelude
= Some(module
);
747 // Add to module's glob_importers
748 module
.glob_importers
.borrow_mut().push(directive
);
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
);
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
);
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();
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
,
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 }
794 self.report_conflict(module
, name
, ns
, duplicate_glob
, binding
);
798 if binding
.vis
== ty
::Visibility
::Public
&&
799 (binding
.is_import() || binding
.is_extern_crate()) {
800 let def
= binding
.def();
802 reexports
.push(Export { name: name, def_id: def.def_id() }
);
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`",
812 self.session
.add_lint(PRIVATE_IN_PUBLIC
, directive
.id
, binding
.span
, msg
);
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
);
826 fn import_path_to_string(names
: &[Name
], subclass
: &ImportDirectiveSubclass
) -> String
{
827 if names
.is_empty() {
828 import_directive_subclass_to_string(subclass
)
831 names_to_string(names
),
832 import_directive_subclass_to_string(subclass
)))
837 fn import_directive_subclass_to_string(subclass
: &ImportDirectiveSubclass
) -> String
{
839 SingleImport { source, .. }
=> source
.to_string(),
840 GlobImport { .. }
=> "*".to_string(),