]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_resolve/imports.rs
New upstream version 1.43.0+dfsg1
[rustc.git] / src / librustc_resolve / imports.rs
index 55ce51e0ff057508c783226910adebf394c653b1..485b86636a0bada0519a90e7a3e23bfb15bfd8d9 100644 (file)
@@ -1,7 +1,5 @@
 //! A bunch of methods and structures more or less related to resolving imports.
 
-use ImportDirectiveSubclass::*;
-
 use crate::diagnostics::Suggestion;
 use crate::Determinacy::{self, *};
 use crate::Namespace::{self, MacroNS, TypeNS};
@@ -15,6 +13,9 @@ use rustc::hir::exports::Export;
 use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS};
 use rustc::ty;
 use rustc::{bug, span_bug};
+use rustc_ast::ast::{Ident, Name, NodeId};
+use rustc_ast::unwrap_or;
+use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_errors::{pluralize, struct_span_err, Applicability};
@@ -25,9 +26,6 @@ use rustc_session::DiagnosticMessageId;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::kw;
 use rustc_span::{MultiSpan, Span};
-use syntax::ast::{Ident, Name, NodeId};
-use syntax::unwrap_or;
-use syntax::util::lev_distance::find_best_match_for_name;
 
 use log::*;
 
@@ -36,10 +34,10 @@ use std::{mem, ptr};
 
 type Res = def::Res<NodeId>;
 
-/// Contains data for specific types of import directives.
+/// Contains data for specific kinds of imports.
 #[derive(Clone, Debug)]
-pub enum ImportDirectiveSubclass<'a> {
-    SingleImport {
+pub enum ImportKind<'a> {
+    Single {
         /// `source` in `use prefix::source as target`.
         source: Ident,
         /// `target` in `use prefix::source as target`.
@@ -53,7 +51,7 @@ pub enum ImportDirectiveSubclass<'a> {
         /// Did this import result from a nested import? ie. `use foo::{bar, baz};`
         nested: bool,
     },
-    GlobImport {
+    Glob {
         is_prelude: bool,
         max_vis: Cell<ty::Visibility>, // The visibility of the greatest re-export.
                                        // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
@@ -65,19 +63,21 @@ pub enum ImportDirectiveSubclass<'a> {
     MacroUse,
 }
 
-/// One import directive.
+/// One import.
 #[derive(Debug, Clone)]
-crate struct ImportDirective<'a> {
-    /// The ID of the `extern crate`, `UseTree` etc that imported this `ImportDirective`.
+crate struct Import<'a> {
+    pub kind: ImportKind<'a>,
+
+    /// The ID of the `extern crate`, `UseTree` etc that imported this `Import`.
     ///
-    /// In the case where the `ImportDirective` was expanded from a "nested" use tree,
+    /// In the case where the `Import` was expanded from a "nested" use tree,
     /// this id is the ID of the leaf tree. For example:
     ///
     /// ```ignore (pacify the mercilous tidy)
     /// use foo::bar::{a, b}
     /// ```
     ///
-    /// If this is the import directive for `foo::bar::a`, we would have the ID of the `UseTree`
+    /// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree`
     /// for `a` in this field.
     pub id: NodeId,
 
@@ -107,22 +107,21 @@ crate struct ImportDirective<'a> {
     pub module_path: Vec<Segment>,
     /// The resolution of `module_path`.
     pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
-    pub subclass: ImportDirectiveSubclass<'a>,
     pub vis: Cell<ty::Visibility>,
     pub used: Cell<bool>,
 }
 
-impl<'a> ImportDirective<'a> {
+impl<'a> Import<'a> {
     pub fn is_glob(&self) -> bool {
-        match self.subclass {
-            ImportDirectiveSubclass::GlobImport { .. } => true,
+        match self.kind {
+            ImportKind::Glob { .. } => true,
             _ => false,
         }
     }
 
     pub fn is_nested(&self) -> bool {
-        match self.subclass {
-            ImportDirectiveSubclass::SingleImport { nested, .. } => nested,
+        match self.kind {
+            ImportKind::Single { nested, .. } => nested,
             _ => false,
         }
     }
@@ -136,8 +135,8 @@ impl<'a> ImportDirective<'a> {
 /// Records information about the resolution of a name in a namespace of a module.
 pub struct NameResolution<'a> {
     /// Single imports that may define the name in the namespace.
-    /// Import directives are arena-allocated, so it's ok to use pointers as keys.
-    single_imports: FxHashSet<PtrKey<'a, ImportDirective<'a>>>,
+    /// Imports are arena-allocated, so it's ok to use pointers as keys.
+    single_imports: FxHashSet<PtrKey<'a, Import<'a>>>,
     /// The least shadowable known binding for this name, or None if there are no known bindings.
     pub binding: Option<&'a NameBinding<'a>>,
     shadowed_glob: Option<&'a NameBinding<'a>>,
@@ -155,8 +154,8 @@ impl<'a> NameResolution<'a> {
         })
     }
 
-    crate fn add_single_import(&mut self, directive: &'a ImportDirective<'a>) {
-        self.single_imports.insert(PtrKey(directive));
+    crate fn add_single_import(&mut self, import: &'a Import<'a>) {
+        self.single_imports.insert(PtrKey(import));
     }
 }
 
@@ -313,9 +312,9 @@ impl<'a> Resolver<'a> {
                             }
                         }
 
-                        if !self.is_accessible_from(binding.vis, parent_scope.module) &&
+                        if !(self.is_accessible_from(binding.vis, parent_scope.module) ||
                        // Remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
-                       !(self.last_import_segment && binding.is_extern_crate())
+                       (self.last_import_segment && binding.is_extern_crate()))
                         {
                             self.privacy_errors.push(PrivacyError {
                                 ident,
@@ -348,8 +347,8 @@ impl<'a> Resolver<'a> {
                 single_import.imported_module.get(),
                 return Err((Undetermined, Weak::No))
             );
-            let ident = match single_import.subclass {
-                SingleImport { source, .. } => source,
+            let ident = match single_import.kind {
+                ImportKind::Single { source, .. } => source,
                 _ => unreachable!(),
             };
             match self.resolve_ident_in_module(
@@ -451,34 +450,34 @@ impl<'a> Resolver<'a> {
         Err((Determined, Weak::No))
     }
 
-    // Given a binding and an import directive that resolves to it,
-    // return the corresponding binding defined by the import directive.
+    // Given a binding and an import that resolves to it,
+    // return the corresponding binding defined by the import.
     crate fn import(
         &self,
         binding: &'a NameBinding<'a>,
-        directive: &'a ImportDirective<'a>,
+        import: &'a Import<'a>,
     ) -> &'a NameBinding<'a> {
-        let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
+        let vis = if binding.pseudo_vis().is_at_least(import.vis.get(), self) ||
                      // cf. `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
-                     !directive.is_glob() && binding.is_extern_crate()
+                     !import.is_glob() && binding.is_extern_crate()
         {
-            directive.vis.get()
+            import.vis.get()
         } else {
             binding.pseudo_vis()
         };
 
-        if let GlobImport { ref max_vis, .. } = directive.subclass {
-            if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) {
+        if let ImportKind::Glob { ref max_vis, .. } = import.kind {
+            if vis == import.vis.get() || vis.is_at_least(max_vis.get(), self) {
                 max_vis.set(vis)
             }
         }
 
         self.arenas.alloc_name_binding(NameBinding {
-            kind: NameBindingKind::Import { binding, directive, used: Cell::new(false) },
+            kind: NameBindingKind::Import { binding, import, used: Cell::new(false) },
             ambiguity: None,
-            span: directive.span,
+            span: import.span,
             vis,
-            expansion: directive.parent_scope.expansion,
+            expansion: import.parent_scope.expansion,
         })
     }
 
@@ -577,17 +576,17 @@ impl<'a> Resolver<'a> {
         };
 
         // Define `binding` in `module`s glob importers.
-        for directive in module.glob_importers.borrow_mut().iter() {
+        for import in module.glob_importers.borrow_mut().iter() {
             let mut ident = key.ident;
-            let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) {
+            let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) {
                 Some(Some(def)) => self.macro_def_scope(def),
-                Some(None) => directive.parent_scope.module,
+                Some(None) => import.parent_scope.module,
                 None => continue,
             };
             if self.is_accessible_from(binding.vis, scope) {
-                let imported_binding = self.import(binding, directive);
+                let imported_binding = self.import(binding, import);
                 let key = BindingKey { ident, ..key };
-                let _ = self.try_define(directive.parent_scope.module, key, imported_binding);
+                let _ = self.try_define(import.parent_scope.module, key, imported_binding);
             }
         }
 
@@ -596,13 +595,13 @@ impl<'a> Resolver<'a> {
 
     // Define a "dummy" resolution containing a Res::Err as a placeholder for a
     // failed resolution
-    fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) {
-        if let SingleImport { target, .. } = directive.subclass {
+    fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
+        if let ImportKind::Single { target, .. } = import.kind {
             let dummy_binding = self.dummy_binding;
-            let dummy_binding = self.import(dummy_binding, directive);
+            let dummy_binding = self.import(dummy_binding, import);
             self.per_ns(|this, ns| {
                 let key = this.new_key(target, ns);
-                let _ = this.try_define(directive.parent_scope.module, key, dummy_binding);
+                let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
                 // Consider erroneous imports used to avoid duplicate diagnostics.
                 this.record_use(target, ns, dummy_binding, false);
             });
@@ -671,7 +670,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             .chain(indeterminate_imports.into_iter().map(|i| (true, i)))
         {
             if let Some(err) = self.finalize_import(import) {
-                if let SingleImport { source, ref source_bindings, .. } = import.subclass {
+                if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
                     if source.name == kw::SelfLower {
                         // Silence `unresolved import` error if E0429 is already emitted
                         if let Err(Determined) = source_bindings.value_ns.get() {
@@ -695,7 +694,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 if seen_spans.insert(err.span) {
                     let path = import_path_to_string(
                         &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
-                        &import.subclass,
+                        &import.kind,
                         err.span,
                     );
                     errors.push((path, err));
@@ -706,7 +705,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 self.r.used_imports.insert((import.id, TypeNS));
                 let path = import_path_to_string(
                     &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
-                    &import.subclass,
+                    &import.kind,
                     import.span,
                 );
                 let err = UnresolvedImportError {
@@ -767,28 +766,28 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
 
     /// Attempts to resolve the given import, returning true if its resolution is determined.
     /// If successful, the resolved bindings are written into the module.
-    fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
+    fn resolve_import(&mut self, import: &'b Import<'b>) -> bool {
         debug!(
             "(resolving import for module) resolving import `{}::...` in `{}`",
-            Segment::names_to_string(&directive.module_path),
-            module_to_string(directive.parent_scope.module).unwrap_or_else(|| "???".to_string()),
+            Segment::names_to_string(&import.module_path),
+            module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()),
         );
 
-        let module = if let Some(module) = directive.imported_module.get() {
+        let module = if let Some(module) = import.imported_module.get() {
             module
         } else {
             // For better failure detection, pretend that the import will
             // not define any names while resolving its module path.
-            let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
+            let orig_vis = import.vis.replace(ty::Visibility::Invisible);
             let path_res = self.r.resolve_path(
-                &directive.module_path,
+                &import.module_path,
                 None,
-                &directive.parent_scope,
+                &import.parent_scope,
                 false,
-                directive.span,
-                directive.crate_lint(),
+                import.span,
+                import.crate_lint(),
             );
-            directive.vis.set(orig_vis);
+            import.vis.set(orig_vis);
 
             match path_res {
                 PathResult::Module(module) => module,
@@ -797,23 +796,22 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             }
         };
 
-        directive.imported_module.set(Some(module));
-        let (source, target, source_bindings, target_bindings, type_ns_only) =
-            match directive.subclass {
-                SingleImport {
-                    source,
-                    target,
-                    ref source_bindings,
-                    ref target_bindings,
-                    type_ns_only,
-                    ..
-                } => (source, target, source_bindings, target_bindings, type_ns_only),
-                GlobImport { .. } => {
-                    self.resolve_glob_import(directive);
-                    return true;
-                }
-                _ => unreachable!(),
-            };
+        import.imported_module.set(Some(module));
+        let (source, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
+            ImportKind::Single {
+                source,
+                target,
+                ref source_bindings,
+                ref target_bindings,
+                type_ns_only,
+                ..
+            } => (source, target, source_bindings, target_bindings, type_ns_only),
+            ImportKind::Glob { .. } => {
+                self.resolve_glob_import(import);
+                return true;
+            }
+            _ => unreachable!(),
+        };
 
         let mut indeterminate = false;
         self.r.per_ns(|this, ns| {
@@ -821,23 +819,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 if let Err(Undetermined) = source_bindings[ns].get() {
                     // For better failure detection, pretend that the import will
                     // not define any names while resolving its module path.
-                    let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
+                    let orig_vis = import.vis.replace(ty::Visibility::Invisible);
                     let binding = this.resolve_ident_in_module(
                         module,
                         source,
                         ns,
-                        &directive.parent_scope,
+                        &import.parent_scope,
                         false,
-                        directive.span,
+                        import.span,
                     );
-                    directive.vis.set(orig_vis);
+                    import.vis.set(orig_vis);
 
                     source_bindings[ns].set(binding);
                 } else {
                     return;
                 };
 
-                let parent = directive.parent_scope.module;
+                let parent = import.parent_scope.module;
                 match source_bindings[ns].get() {
                     Err(Undetermined) => indeterminate = true,
                     // Don't update the resolution, because it was never added.
@@ -845,20 +843,20 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                     Err(Determined) => {
                         let key = this.new_key(target, ns);
                         this.update_resolution(parent, key, |_, resolution| {
-                            resolution.single_imports.remove(&PtrKey(directive));
+                            resolution.single_imports.remove(&PtrKey(import));
                         });
                     }
                     Ok(binding) if !binding.is_importable() => {
                         let msg = format!("`{}` is not directly importable", target);
-                        struct_span_err!(this.session, directive.span, E0253, "{}", &msg)
-                            .span_label(directive.span, "cannot be imported directly")
+                        struct_span_err!(this.session, import.span, E0253, "{}", &msg)
+                            .span_label(import.span, "cannot be imported directly")
                             .emit();
                         // Do not import this illegal binding. Import a dummy binding and pretend
                         // everything is fine
-                        this.import_dummy_binding(directive);
+                        this.import_dummy_binding(import);
                     }
                     Ok(binding) => {
-                        let imported_binding = this.import(binding, directive);
+                        let imported_binding = this.import(binding, import);
                         target_bindings[ns].set(Some(imported_binding));
                         this.define(parent, target, ns, imported_binding);
                     }
@@ -873,38 +871,35 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
     ///
     /// Optionally returns an unresolved import error. This error is buffered and used to
     /// consolidate multiple unresolved import errors into a single diagnostic.
-    fn finalize_import(
-        &mut self,
-        directive: &'b ImportDirective<'b>,
-    ) -> Option<UnresolvedImportError> {
-        let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
+    fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImportError> {
+        let orig_vis = import.vis.replace(ty::Visibility::Invisible);
         let prev_ambiguity_errors_len = self.r.ambiguity_errors.len();
         let path_res = self.r.resolve_path(
-            &directive.module_path,
+            &import.module_path,
             None,
-            &directive.parent_scope,
+            &import.parent_scope,
             true,
-            directive.span,
-            directive.crate_lint(),
+            import.span,
+            import.crate_lint(),
         );
         let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
-        directive.vis.set(orig_vis);
+        import.vis.set(orig_vis);
         if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
             // Consider erroneous imports used to avoid duplicate diagnostics.
-            self.r.used_imports.insert((directive.id, TypeNS));
+            self.r.used_imports.insert((import.id, TypeNS));
         }
         let module = match path_res {
             PathResult::Module(module) => {
                 // Consistency checks, analogous to `finalize_macro_resolutions`.
-                if let Some(initial_module) = directive.imported_module.get() {
+                if let Some(initial_module) = import.imported_module.get() {
                     if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity {
-                        span_bug!(directive.span, "inconsistent resolution for an import");
+                        span_bug!(import.span, "inconsistent resolution for an import");
                     }
                 } else {
                     if self.r.privacy_errors.is_empty() {
                         let msg = "cannot determine resolution for the import";
                         let msg_note = "import resolution is stuck, try simplifying other imports";
-                        self.r.session.struct_span_err(directive.span, msg).note(msg_note).emit();
+                        self.r.session.struct_span_err(import.span, msg).note(msg_note).emit();
                     }
                 }
 
@@ -912,7 +907,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             }
             PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
                 if no_ambiguity {
-                    assert!(directive.imported_module.get().is_none());
+                    assert!(import.imported_module.get().is_none());
                     self.r
                         .report_error(span, ResolutionError::FailedToResolve { label, suggestion });
                 }
@@ -920,11 +915,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             }
             PathResult::Failed { is_error_from_last_segment: true, span, label, suggestion } => {
                 if no_ambiguity {
-                    assert!(directive.imported_module.get().is_none());
+                    assert!(import.imported_module.get().is_none());
                     let err = match self.make_path_suggestion(
                         span,
-                        directive.module_path.clone(),
-                        &directive.parent_scope,
+                        import.module_path.clone(),
+                        &import.parent_scope,
                     ) {
                         Some((suggestion, note)) => UnresolvedImportError {
                             span,
@@ -949,7 +944,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             }
             PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => {
                 if no_ambiguity {
-                    assert!(directive.imported_module.get().is_none());
+                    assert!(import.imported_module.get().is_none());
                 }
                 // The error was already reported earlier.
                 return None;
@@ -957,10 +952,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
         };
 
-        let (ident, target, source_bindings, target_bindings, type_ns_only) = match directive
-            .subclass
-        {
-            SingleImport {
+        let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
+            ImportKind::Single {
                 source,
                 target,
                 ref source_bindings,
@@ -968,25 +961,25 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 type_ns_only,
                 ..
             } => (source, target, source_bindings, target_bindings, type_ns_only),
-            GlobImport { is_prelude, ref max_vis } => {
-                if directive.module_path.len() <= 1 {
+            ImportKind::Glob { is_prelude, ref max_vis } => {
+                if import.module_path.len() <= 1 {
                     // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
                     // 2 segments, so the `resolve_path` above won't trigger it.
-                    let mut full_path = directive.module_path.clone();
+                    let mut full_path = import.module_path.clone();
                     full_path.push(Segment::from_ident(Ident::invalid()));
                     self.r.lint_if_path_starts_with_module(
-                        directive.crate_lint(),
+                        import.crate_lint(),
                         &full_path,
-                        directive.span,
+                        import.span,
                         None,
                     );
                 }
 
                 if let ModuleOrUniformRoot::Module(module) = module {
-                    if module.def_id() == directive.parent_scope.module.def_id() {
+                    if module.def_id() == import.parent_scope.module.def_id() {
                         // Importing a module into itself is not allowed.
                         return Some(UnresolvedImportError {
-                            span: directive.span,
+                            span: import.span,
                             label: Some(String::from("cannot glob-import a module into itself")),
                             note: Vec::new(),
                             suggestion: None,
@@ -995,15 +988,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 }
                 if !is_prelude &&
                    max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
-                   !max_vis.get().is_at_least(directive.vis.get(), &*self)
+                   !max_vis.get().is_at_least(import.vis.get(), &*self)
                 {
                     let msg = "glob import doesn't reexport anything because no candidate is public enough";
-                    self.r.lint_buffer.buffer_lint(
-                        UNUSED_IMPORTS,
-                        directive.id,
-                        directive.span,
-                        msg,
-                    );
+                    self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
                 }
                 return None;
             }
@@ -1013,7 +1001,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
         let mut all_ns_err = true;
         self.r.per_ns(|this, ns| {
             if !type_ns_only || ns == TypeNS {
-                let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
+                let orig_vis = import.vis.replace(ty::Visibility::Invisible);
                 let orig_blacklisted_binding =
                     mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get());
                 let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true);
@@ -1021,13 +1009,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                     module,
                     ident,
                     ns,
-                    &directive.parent_scope,
+                    &import.parent_scope,
                     true,
-                    directive.span,
+                    import.span,
                 );
                 this.last_import_segment = orig_last_import_segment;
                 this.blacklisted_binding = orig_blacklisted_binding;
-                directive.vis.set(orig_vis);
+                import.vis.set(orig_vis);
 
                 match binding {
                     Ok(binding) => {
@@ -1044,7 +1032,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                                         ident,
                                         ns,
                                         target_binding,
-                                        directive.module_path.is_empty(),
+                                        import.module_path.is_empty(),
                                     );
                                 }
                             }
@@ -1053,7 +1041,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                         let res = binding.res();
                         if let Ok(initial_res) = initial_res {
                             if res != initial_res && this.ambiguity_errors.is_empty() {
-                                span_bug!(directive.span, "inconsistent resolution for an import");
+                                span_bug!(import.span, "inconsistent resolution for an import");
                             }
                         } else {
                             if res != Res::Err
@@ -1064,7 +1052,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                                 let msg_note =
                                     "import resolution is stuck, try simplifying other imports";
                                 this.session
-                                    .struct_span_err(directive.span, msg)
+                                    .struct_span_err(import.span, msg)
                                     .note(msg_note)
                                     .emit();
                             }
@@ -1075,7 +1063,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                         // single import (see test `issue-55884-2.rs`). In theory single imports should
                         // always block globs, even if they are not yet resolved, so that this kind of
                         // self-inconsistent resolution never happens.
-                        // Reenable the assert when the issue is fixed.
+                        // Re-enable the assert when the issue is fixed.
                         // assert!(result[ns].get().is_err());
                     }
                 }
@@ -1090,9 +1078,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                         module,
                         ident,
                         ns,
-                        &directive.parent_scope,
+                        &import.parent_scope,
                         true,
-                        directive.span,
+                        import.span,
                     );
                     if binding.is_ok() {
                         all_ns_failed = false;
@@ -1143,7 +1131,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                     });
 
                 let (suggestion, note) =
-                    match self.check_for_module_export_macro(directive, module, ident) {
+                    match self.check_for_module_export_macro(import, module, ident) {
                         Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),
                         _ => (lev_suggestion, Vec::new()),
                     };
@@ -1169,14 +1157,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 };
 
                 Some(UnresolvedImportError {
-                    span: directive.span,
+                    span: import.span,
                     label: Some(label),
                     note,
                     suggestion,
                 })
             } else {
                 // `resolve_ident_in_module` reported a privacy error.
-                self.r.import_dummy_binding(directive);
+                self.r.import_dummy_binding(import);
                 None
             };
         }
@@ -1185,7 +1173,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
         let mut any_successful_reexport = false;
         self.r.per_ns(|this, ns| {
             if let Ok(binding) = source_bindings[ns].get() {
-                let vis = directive.vis.get();
+                let vis = import.vis.get();
                 if !binding.pseudo_vis().is_at_least(vis, &*this) {
                     reexport_error = Some((ns, binding));
                 } else {
@@ -1206,42 +1194,42 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 );
                 self.r.lint_buffer.buffer_lint(
                     PUB_USE_OF_PRIVATE_EXTERN_CRATE,
-                    directive.id,
-                    directive.span,
+                    import.id,
+                    import.span,
                     &msg,
                 );
             } else if ns == TypeNS {
                 struct_span_err!(
                     self.r.session,
-                    directive.span,
+                    import.span,
                     E0365,
                     "`{}` is private, and cannot be re-exported",
                     ident
                 )
-                .span_label(directive.span, format!("re-export of private `{}`", ident))
+                .span_label(import.span, format!("re-export of private `{}`", ident))
                 .note(&format!("consider declaring type or module `{}` with `pub`", ident))
                 .emit();
             } else {
                 let msg = format!("`{}` is private, and cannot be re-exported", ident);
                 let note_msg =
                     format!("consider marking `{}` as `pub` in the imported module", ident,);
-                struct_span_err!(self.r.session, directive.span, E0364, "{}", &msg)
-                    .span_note(directive.span, &note_msg)
+                struct_span_err!(self.r.session, import.span, E0364, "{}", &msg)
+                    .span_note(import.span, &note_msg)
                     .emit();
             }
         }
 
-        if directive.module_path.len() <= 1 {
+        if import.module_path.len() <= 1 {
             // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
             // 2 segments, so the `resolve_path` above won't trigger it.
-            let mut full_path = directive.module_path.clone();
+            let mut full_path = import.module_path.clone();
             full_path.push(Segment::from_ident(ident));
             self.r.per_ns(|this, ns| {
                 if let Ok(binding) = source_bindings[ns].get() {
                     this.lint_if_path_starts_with_module(
-                        directive.crate_lint(),
+                        import.crate_lint(),
                         &full_path,
-                        directive.span,
+                        import.span,
                         Some(binding),
                     );
                 }
@@ -1252,18 +1240,12 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
         self.r.per_ns(|this, ns| {
-            if let Some(binding) = source_bindings[ns].get().ok() {
-                this.import_res_map.entry(directive.id).or_default()[ns] = Some(binding.res());
+            if let Ok(binding) = source_bindings[ns].get() {
+                this.import_res_map.entry(import.id).or_default()[ns] = Some(binding.res());
             }
         });
 
-        self.check_for_redundant_imports(
-            ident,
-            directive,
-            source_bindings,
-            target_bindings,
-            target,
-        );
+        self.check_for_redundant_imports(ident, import, source_bindings, target_bindings, target);
 
         debug!("(resolving single import) successfully resolved import");
         None
@@ -1272,19 +1254,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
     fn check_for_redundant_imports(
         &mut self,
         ident: Ident,
-        directive: &'b ImportDirective<'b>,
+        import: &'b Import<'b>,
         source_bindings: &PerNS<Cell<Result<&'b NameBinding<'b>, Determinacy>>>,
         target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
         target: Ident,
     ) {
         // Skip if the import was produced by a macro.
-        if directive.parent_scope.expansion != ExpnId::root() {
+        if import.parent_scope.expansion != ExpnId::root() {
             return;
         }
 
         // Skip if we are inside a named module (in contrast to an anonymous
         // module defined by a block).
-        if let ModuleKind::Def(..) = directive.parent_scope.module.kind {
+        if let ModuleKind::Def(..) = import.parent_scope.module.kind {
             return;
         }
 
@@ -1293,7 +1275,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
         let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
 
         self.r.per_ns(|this, ns| {
-            if let Some(binding) = source_bindings[ns].get().ok() {
+            if let Ok(binding) = source_bindings[ns].get() {
                 if binding.res() == Res::Err {
                     return;
                 }
@@ -1304,10 +1286,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                 match this.early_resolve_ident_in_lexical_scope(
                     target,
                     ScopeSet::All(ns, false),
-                    &directive.parent_scope,
+                    &import.parent_scope,
                     false,
                     false,
-                    directive.span,
+                    import.span,
                 ) {
                     Ok(other_binding) => {
                         is_redundant[ns] = Some(
@@ -1329,35 +1311,35 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             redundant_spans.dedup();
             self.r.lint_buffer.buffer_lint_with_diagnostic(
                 UNUSED_IMPORTS,
-                directive.id,
-                directive.span,
+                import.id,
+                import.span,
                 &format!("the item `{}` is imported redundantly", ident),
                 BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident),
             );
         }
     }
 
-    fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
-        let module = match directive.imported_module.get().unwrap() {
+    fn resolve_glob_import(&mut self, import: &'b Import<'b>) {
+        let module = match import.imported_module.get().unwrap() {
             ModuleOrUniformRoot::Module(module) => module,
             _ => {
-                self.r.session.span_err(directive.span, "cannot glob-import all possible crates");
+                self.r.session.span_err(import.span, "cannot glob-import all possible crates");
                 return;
             }
         };
 
         if module.is_trait() {
-            self.r.session.span_err(directive.span, "items in traits are not importable.");
+            self.r.session.span_err(import.span, "items in traits are not importable.");
             return;
-        } else if module.def_id() == directive.parent_scope.module.def_id() {
+        } else if module.def_id() == import.parent_scope.module.def_id() {
             return;
-        } else if let GlobImport { is_prelude: true, .. } = directive.subclass {
+        } else if let ImportKind::Glob { is_prelude: true, .. } = import.kind {
             self.r.prelude = Some(module);
             return;
         }
 
         // Add to module's glob_importers
-        module.glob_importers.borrow_mut().push(directive);
+        module.glob_importers.borrow_mut().push(import);
 
         // Ensure that `resolutions` isn't borrowed during `try_define`,
         // since it might get updated via a glob cycle.
@@ -1371,19 +1353,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             })
             .collect::<Vec<_>>();
         for (mut key, binding) in bindings {
-            let scope = match key.ident.span.reverse_glob_adjust(module.expansion, directive.span) {
+            let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) {
                 Some(Some(def)) => self.r.macro_def_scope(def),
-                Some(None) => directive.parent_scope.module,
+                Some(None) => import.parent_scope.module,
                 None => continue,
             };
             if self.r.is_accessible_from(binding.pseudo_vis(), scope) {
-                let imported_binding = self.r.import(binding, directive);
-                let _ = self.r.try_define(directive.parent_scope.module, key, imported_binding);
+                let imported_binding = self.r.import(binding, import);
+                let _ = self.r.try_define(import.parent_scope.module, key, imported_binding);
             }
         }
 
         // Record the destination of this import
-        self.r.record_partial_res(directive.id, PartialRes::new(module.res().unwrap()));
+        self.r.record_partial_res(import.id, PartialRes::new(module.res().unwrap()));
     }
 
     // Miscellaneous post-processing, including recording re-exports,
@@ -1403,25 +1385,20 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             if is_good_import || binding.is_macro_def() {
                 let res = binding.res();
                 if res != Res::Err {
-                    if let Some(def_id) = res.opt_def_id() {
-                        if !def_id.is_local() {
-                            this.cstore().export_macros_untracked(def_id.krate);
-                        }
-                    }
                     reexports.push(Export { ident, res, span: binding.span, vis: binding.vis });
                 }
             }
 
-            if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
+            if let NameBindingKind::Import { binding: orig_binding, import, .. } = binding.kind {
                 if ns == TypeNS
                     && orig_binding.is_variant()
                     && !orig_binding.vis.is_at_least(binding.vis, &*this)
                 {
-                    let msg = match directive.subclass {
-                        ImportDirectiveSubclass::SingleImport { .. } => {
+                    let msg = match import.kind {
+                        ImportKind::Single { .. } => {
                             format!("variant `{}` is private and cannot be re-exported", ident)
                         }
-                        ImportDirectiveSubclass::GlobImport { .. } => {
+                        ImportKind::Glob { .. } => {
                             let msg = "enum is private and its variants \
                                            cannot be re-exported"
                                 .to_owned();
@@ -1437,18 +1414,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
                             }
                             msg
                         }
-                        ref s @ _ => bug!("unexpected import subclass {:?}", s),
+                        ref s => bug!("unexpected import kind {:?}", s),
                     };
                     let mut err = this.session.struct_span_err(binding.span, &msg);
 
-                    let imported_module = match directive.imported_module.get() {
+                    let imported_module = match import.imported_module.get() {
                         Some(ModuleOrUniformRoot::Module(module)) => module,
                         _ => bug!("module should exist"),
                     };
                     let parent_module = imported_module.parent.expect("parent should exist");
                     let resolutions = this.resolutions(parent_module).borrow();
-                    let enum_path_segment_index = directive.module_path.len() - 1;
-                    let enum_ident = directive.module_path[enum_path_segment_index].ident;
+                    let enum_path_segment_index = import.module_path.len() - 1;
+                    let enum_ident = import.module_path[enum_path_segment_index].ident;
 
                     let key = this.new_key(enum_ident, TypeNS);
                     let enum_resolution = resolutions.get(&key).expect("resolution should exist");
@@ -1478,7 +1455,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             }
         });
 
-        if reexports.len() > 0 {
+        if !reexports.is_empty() {
             if let Some(def_id) = module.def_id() {
                 self.r.export_map.insert(def_id, reexports);
             }
@@ -1486,11 +1463,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
     }
 }
 
-fn import_path_to_string(
-    names: &[Ident],
-    subclass: &ImportDirectiveSubclass<'_>,
-    span: Span,
-) -> String {
+fn import_path_to_string(names: &[Ident], import_kind: &ImportKind<'_>, span: Span) -> String {
     let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot);
     let global = !names.is_empty() && names[0].name == kw::PathRoot;
     if let Some(pos) = pos {
@@ -1499,22 +1472,22 @@ fn import_path_to_string(
     } else {
         let names = if global { &names[1..] } else { names };
         if names.is_empty() {
-            import_directive_subclass_to_string(subclass)
+            import_kind_to_string(import_kind)
         } else {
             format!(
                 "{}::{}",
                 names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>()),
-                import_directive_subclass_to_string(subclass),
+                import_kind_to_string(import_kind),
             )
         }
     }
 }
 
-fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass<'_>) -> String {
-    match *subclass {
-        SingleImport { source, .. } => source.to_string(),
-        GlobImport { .. } => "*".to_string(),
-        ExternCrate { .. } => "<extern crate>".to_string(),
-        MacroUse => "#[macro_use]".to_string(),
+fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {
+    match import_kind {
+        ImportKind::Single { source, .. } => source.to_string(),
+        ImportKind::Glob { .. } => "*".to_string(),
+        ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),
+        ImportKind::MacroUse => "#[macro_use]".to_string(),
     }
 }