]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/resolve_imports.rs
rustc: use DefKind instead of Def, where possible.
[rust.git] / src / librustc_resolve / resolve_imports.rs
index 2c98c66c62e375bed09c6389dc7661270a9191f6..7dbc75364401cf94d1385b1e3e6313a300e38ff7 100644 (file)
@@ -21,7 +21,7 @@
     UNUSED_IMPORTS,
 };
 use rustc::hir::def_id::{CrateNum, DefId};
-use rustc::hir::def::*;
+use rustc::hir::def::{self, DefKind, PathResolution, Export};
 use rustc::session::DiagnosticMessageId;
 use rustc::util::nodemap::FxHashSet;
 use rustc::{bug, span_bug};
@@ -39,6 +39,8 @@
 use std::cell::{Cell, RefCell};
 use std::{mem, ptr};
 
+type Def = def::Def<NodeId>;
+
 /// Contains data for specific types of import directives.
 #[derive(Clone, Debug)]
 pub enum ImportDirectiveSubclass<'a> {
@@ -145,7 +147,7 @@ pub struct NameResolution<'a> {
 
 impl<'a> NameResolution<'a> {
     // Returns the binding for the name if it is known or None if it not known.
-    fn binding(&self) -> Option<&'a NameBinding<'a>> {
+    pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> {
         self.binding.and_then(|binding| {
             if !binding.is_glob_import() ||
                self.single_imports.is_empty() { Some(binding) } else { None }
@@ -625,6 +627,8 @@ fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) {
             let dummy_binding = self.import(dummy_binding, directive);
             self.per_ns(|this, ns| {
                 let _ = this.try_define(directive.parent_scope.module, target, ns, dummy_binding);
+                // Consider erroneous imports used to avoid duplicate diagnostics.
+                this.record_use(target, ns, dummy_binding, false);
             });
         }
     }
@@ -636,7 +640,7 @@ fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) {
 struct UnresolvedImportError {
     span: Span,
     label: Option<String>,
-    note: Option<String>,
+    note: Vec<String>,
     suggestion: Option<Suggestion>,
 }
 
@@ -756,8 +760,8 @@ fn throw_unresolved_import_error(
         /// Upper limit on the number of `span_label` messages.
         const MAX_LABEL_COUNT: usize = 10;
 
-        let (span, msg, note) = if errors.is_empty() {
-            (span.unwrap(), "unresolved import".to_string(), None)
+        let (span, msg) = if errors.is_empty() {
+            (span.unwrap(), "unresolved import".to_string())
         } else {
             let span = MultiSpan::from_spans(
                 errors
@@ -766,11 +770,6 @@ fn throw_unresolved_import_error(
                     .collect(),
             );
 
-            let note = errors
-                .iter()
-                .filter_map(|(_, err)| err.note.as_ref())
-                .last();
-
             let paths = errors
                 .iter()
                 .map(|(path, _)| format!("`{}`", path))
@@ -782,13 +781,15 @@ fn throw_unresolved_import_error(
                 paths.join(", "),
             );
 
-            (span, msg, note)
+            (span, msg)
         };
 
         let mut diag = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg);
 
-        if let Some(note) = &note {
-            diag.note(note);
+        if let Some((_, UnresolvedImportError { note, .. })) = errors.iter().last() {
+            for message in note {
+                diag.note(&message);
+            }
         }
 
         for (_, err) in errors.into_iter().take(MAX_LABEL_COUNT) {
@@ -796,8 +797,8 @@ fn throw_unresolved_import_error(
                 diag.span_label(err.span, label);
             }
 
-            if let Some((span, msg, suggestion, applicability)) = err.suggestion {
-                diag.span_suggestion(span, &msg, suggestion, applicability);
+            if let Some((suggestions, msg, applicability)) = err.suggestion {
+                diag.multipart_suggestion(&msg, suggestions, applicability);
             }
         }
 
@@ -950,9 +951,8 @@ fn finalize_import(
                                 label: None,
                                 note,
                                 suggestion: Some((
-                                    span,
+                                    vec![(span, Segment::names_to_string(&suggestion))],
                                     String::from("a similar path exists"),
-                                    Segment::names_to_string(&suggestion),
                                     Applicability::MaybeIncorrect,
                                 )),
                             }
@@ -961,7 +961,7 @@ fn finalize_import(
                             UnresolvedImportError {
                                 span,
                                 label: Some(label),
-                                note: None,
+                                note: Vec::new(),
                                 suggestion,
                             }
                         }
@@ -1006,7 +1006,7 @@ fn finalize_import(
                         return Some(UnresolvedImportError {
                             span: directive.span,
                             label: Some(String::from("cannot glob-import a module into itself")),
-                            note: None,
+                            note: Vec::new(),
                             suggestion: None,
                         });
                     }
@@ -1114,15 +1114,19 @@ fn finalize_import(
                     }
                 });
 
-                let lev_suggestion =
-                    find_best_match_for_name(names, &ident.as_str(), None).map(|suggestion| {
-                        (
-                            ident.span,
-                            String::from("a similar name exists in the module"),
-                            suggestion.to_string(),
-                            Applicability::MaybeIncorrect,
-                        )
-                    });
+                let lev_suggestion = find_best_match_for_name(names, &ident.as_str(), None)
+                   .map(|suggestion|
+                        (vec![(ident.span, suggestion.to_string())],
+                         String::from("a similar name exists in the module"),
+                         Applicability::MaybeIncorrect)
+                    );
+
+                let (suggestion, note) = match self.check_for_module_export_macro(
+                    directive, module, ident,
+                ) {
+                    Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),
+                    _ => (lev_suggestion, Vec::new()),
+                };
 
                 let label = match module {
                     ModuleOrUniformRoot::Module(module) => {
@@ -1143,11 +1147,12 @@ fn finalize_import(
                         }
                     }
                 };
+
                 Some(UnresolvedImportError {
                     span: directive.span,
                     label: Some(label),
-                    note: None,
-                    suggestion: lev_suggestion,
+                    note,
+                    suggestion,
                 })
             } else {
                 // `resolve_ident_in_module` reported a privacy error.
@@ -1219,7 +1224,7 @@ fn finalize_import(
         // purposes it's good enough to just favor one over the other.
         self.per_ns(|this, ns| if let Some(binding) = source_bindings[ns].get().ok() {
             let mut def = binding.def();
-            if let Def::Macro(def_id, _) = def {
+            if let Def::Def(DefKind::Macro(_), def_id) = def {
                 // `DefId`s from the "built-in macro crate" should not leak from resolve because
                 // later stages are not ready to deal with them and produce lots of ICEs. Replace
                 // them with `Def::Err` until some saner scheme is implemented for built-in macros.
@@ -1259,7 +1264,7 @@ fn check_for_redundant_imports(
 
         // 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(..) = directive.parent_scope.module.kind {
             return;
         }
 
@@ -1311,6 +1316,7 @@ fn check_for_redundant_imports(
             is_redundant.present_items().all(|is_redundant| is_redundant)
         {
             let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
+            redundant_spans.sort();
             redundant_spans.dedup();
             self.session.buffer_lint_with_diagnostic(
                 UNUSED_IMPORTS,