use syntax::ext::base::SyntaxExtension;
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::base::MacroKind;
+use syntax::feature_gate::{emit_feature_err, GateIssue};
use syntax::symbol::{Symbol, keywords};
use syntax::util::lev_distance::find_best_match_for_name;
match self.kind {
NameBindingKind::Import {
directive: &ImportDirective {
- subclass: ImportDirectiveSubclass::ExternCrate(_), ..
+ subclass: ImportDirectiveSubclass::ExternCrate { .. }, ..
}, ..
} => true,
_ => false,
}
}
- fn is_renamed_extern_crate(&self) -> bool {
- if let NameBindingKind::Import { directive, ..} = self.kind {
- if let ImportDirectiveSubclass::ExternCrate(Some(_)) = directive.subclass {
- return true;
- }
- }
- false
- }
-
fn is_glob_import(&self) -> bool {
match self.kind {
NameBindingKind::Import { directive, .. } => directive.is_glob(),
}
}
+#[derive(Default, Clone)]
+pub struct ExternPreludeEntry<'a> {
+ extern_crate_item: Option<&'a NameBinding<'a>>,
+ pub introduced_by_item: bool,
+}
+
/// The main resolver class.
///
/// This is the visitor that walks the whole crate.
graph_root: Module<'a>,
prelude: Option<Module<'a>>,
- pub extern_prelude: FxHashSet<Name>,
+ pub extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>,
/// n.b. This is used only for better diagnostics, not name resolution itself.
has_self: FxHashSet<DefId>,
DefCollector::new(&mut definitions, Mark::root())
.collect_root(crate_name, session.local_crate_disambiguator());
- let mut extern_prelude: FxHashSet<Name> =
- session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
+ let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry> =
+ session.opts.externs.iter().map(|kv| (Ident::from_str(kv.0), Default::default()))
+ .collect();
if !attr::contains_name(&krate.attrs, "no_core") {
- extern_prelude.insert(Symbol::intern("core"));
+ extern_prelude.insert(Ident::from_str("core"), Default::default());
if !attr::contains_name(&krate.attrs, "no_std") {
- extern_prelude.insert(Symbol::intern("std"));
+ extern_prelude.insert(Ident::from_str("std"), Default::default());
if session.rust_2018() {
- extern_prelude.insert(Symbol::intern("meta"));
+ extern_prelude.insert(Ident::from_str("meta"), Default::default());
}
}
}
}
if !module.no_implicit_prelude {
- if ns == TypeNS && self.extern_prelude.contains(&ident.name) {
- let crate_id = if record_used {
- self.crate_loader.process_path_extern(ident.name, ident.span)
- } else if let Some(crate_id) =
- self.crate_loader.maybe_process_path_extern(ident.name, ident.span) {
- crate_id
- } else {
- return None;
- };
- let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
- self.populate_module_if_necessary(&crate_root);
-
- let binding = (crate_root, ty::Visibility::Public,
- ident.span, Mark::root()).to_name_binding(self.arenas);
- return Some(LexicalScopeBinding::Item(binding));
+ if ns == TypeNS {
+ if let Some(binding) = self.extern_prelude_get(ident, !record_used, false) {
+ return Some(LexicalScopeBinding::Item(binding));
+ }
}
if ns == TypeNS && is_known_tool(ident.name) {
let binding = (Def::ToolMod, ty::Visibility::Public,
if let NameBindingKind::Import { directive: d, .. } = binding.kind {
// Careful: we still want to rewrite paths from
// renamed extern crates.
- if let ImportDirectiveSubclass::ExternCrate(None) = d.subclass {
+ if let ImportDirectiveSubclass::ExternCrate { source: None, .. } = d.subclass {
return
}
}
} else {
// Items from the prelude
if !module.no_implicit_prelude {
- names.extend(self.extern_prelude.iter().cloned());
+ names.extend(self.extern_prelude.iter().map(|(ident, _)| ident.name));
if let Some(prelude) = self.prelude {
add_module_candidates(prelude, &mut names);
}
if self.session.rust_2018() {
let extern_prelude_names = self.extern_prelude.clone();
- for &name in extern_prelude_names.iter() {
- let ident = Ident::with_empty_ctxt(name);
- if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(name,
- ident.span)
- {
+ for (ident, _) in extern_prelude_names.into_iter() {
+ if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
+ ident.span) {
let crate_root = self.get_module(DefId {
krate: crate_id,
index: CRATE_DEF_INDEX,
};
let cm = self.session.source_map();
- let rename_msg = "You can use `as` to change the binding name of the import";
-
- if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span),
- binding.is_renamed_extern_crate()) {
+ let rename_msg = "you can use `as` to change the binding name of the import";
+
+ if let (
+ Ok(snippet),
+ NameBindingKind::Import { directive, ..},
+ _dummy @ false,
+ ) = (
+ cm.span_to_snippet(binding.span),
+ binding.kind.clone(),
+ binding.span.is_dummy(),
+ ) {
let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
format!("Other{}", name)
} else {
err.span_suggestion_with_applicability(
binding.span,
- rename_msg,
- if snippet.ends_with(';') {
- format!("{} as {};", &snippet[..snippet.len() - 1], suggested_name)
- } else {
- format!("{} as {}", snippet, suggested_name)
+ &rename_msg,
+ match (&directive.subclass, snippet.as_ref()) {
+ (ImportDirectiveSubclass::SingleImport { .. }, "self") =>
+ format!("self as {}", suggested_name),
+ (ImportDirectiveSubclass::SingleImport { source, .. }, _) =>
+ format!(
+ "{} as {}{}",
+ &snippet[..((source.span.hi().0 - binding.span.lo().0) as usize)],
+ suggested_name,
+ if snippet.ends_with(";") {
+ ";"
+ } else {
+ ""
+ }
+ ),
+ (ImportDirectiveSubclass::ExternCrate { source, target, .. }, _) =>
+ format!(
+ "extern crate {} as {};",
+ source.unwrap_or(target.name),
+ suggested_name,
+ ),
+ (_, _) => unreachable!(),
},
- Applicability::MachineApplicable,
+ Applicability::MaybeIncorrect,
);
} else {
err.span_label(binding.span, rename_msg);
err.emit();
self.name_already_seen.insert(name, span);
}
+
+ fn extern_prelude_get(&mut self, ident: Ident, speculative: bool, skip_feature_gate: bool)
+ -> Option<&'a NameBinding<'a>> {
+ self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| {
+ if let Some(binding) = entry.extern_crate_item {
+ if !speculative && !skip_feature_gate && entry.introduced_by_item &&
+ !self.session.features_untracked().extern_crate_item_prelude {
+ emit_feature_err(&self.session.parse_sess, "extern_crate_item_prelude",
+ ident.span, GateIssue::Language,
+ "use of extern prelude names introduced \
+ with `extern crate` items is unstable");
+ }
+ Some(binding)
+ } else {
+ let crate_id = if !speculative {
+ self.crate_loader.process_path_extern(ident.name, ident.span)
+ } else if let Some(crate_id) =
+ self.crate_loader.maybe_process_path_extern(ident.name, ident.span) {
+ crate_id
+ } else {
+ return None;
+ };
+ let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+ self.populate_module_if_necessary(&crate_root);
+ Some((crate_root, ty::Visibility::Public, ident.span, Mark::root())
+ .to_name_binding(self.arenas))
+ }
+ })
+ }
}
fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {