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};
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> {
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 }
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);
});
}
}
struct UnresolvedImportError {
span: Span,
label: Option<String>,
- note: Option<String>,
+ note: Vec<String>,
suggestion: Option<Suggestion>,
}
/// 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
.collect(),
);
- let note = errors
- .iter()
- .filter_map(|(_, err)| err.note.as_ref())
- .last();
-
let paths = errors
.iter()
.map(|(path, _)| format!("`{}`", path))
paths.join(", "),
);
- (span, msg, note)
+ (span, msg)
};
let mut diag = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg);
- if let Some(note) = ¬e {
- 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) {
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);
}
}
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,
)),
}
UnresolvedImportError {
span,
label: Some(label),
- note: None,
+ note: Vec::new(),
suggestion,
}
}
return Some(UnresolvedImportError {
span: directive.span,
label: Some(String::from("cannot glob-import a module into itself")),
- note: None,
+ note: Vec::new(),
suggestion: None,
});
}
}
});
- 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) => {
}
}
};
+
Some(UnresolvedImportError {
span: directive.span,
label: Some(label),
- note: None,
- suggestion: lev_suggestion,
+ note,
+ suggestion,
})
} else {
// `resolve_ident_in_module` reported a privacy error.
// 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.
// 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;
}
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,