]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/lib.rs
Rollup merge of #55328 - raphlinus:copysign_typo, r=joshtriplett
[rust.git] / src / librustc_resolve / lib.rs
index 0f96ee6a688f1c6b0518e562584b96209e9d110a..2c21067bd58c8881debec221bacd46ac150e3a76 100644 (file)
@@ -58,6 +58,7 @@
 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;
 
@@ -1234,7 +1235,7 @@ fn is_extern_crate(&self) -> bool {
         match self.kind {
             NameBindingKind::Import {
                 directive: &ImportDirective {
-                    subclass: ImportDirectiveSubclass::ExternCrate(_), ..
+                    subclass: ImportDirectiveSubclass::ExternCrate { .. }, ..
                 }, ..
             } => true,
             _ => false,
@@ -1248,15 +1249,6 @@ fn is_import(&self) -> bool {
         }
     }
 
-    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(),
@@ -1349,6 +1341,12 @@ fn intern(&mut self, string: &str, primitive_type: PrimTy) {
     }
 }
 
+#[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.
@@ -1361,7 +1359,7 @@ pub struct Resolver<'a, 'b: 'a> {
     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>,
@@ -1677,15 +1675,16 @@ pub fn new(session: &'a Session,
         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());
                 }
             }
         }
@@ -1972,21 +1971,10 @@ fn resolve_ident_in_lexical_scope(&mut self,
         }
 
         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,
@@ -3812,7 +3800,7 @@ fn lint_if_path_starts_with_module(
             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
                 }
             }
@@ -4027,7 +4015,7 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
                     } 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);
                             }
@@ -4468,11 +4456,9 @@ fn lookup_import_candidates<FilterFn>(&mut self,
 
         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,
@@ -4782,10 +4768,17 @@ fn report_conflict<'b>(&mut self,
             };
 
             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 {
@@ -4794,13 +4787,30 @@ fn report_conflict<'b>(&mut self,
 
                 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);
@@ -4810,6 +4820,35 @@ fn report_conflict<'b>(&mut self,
         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 {