]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/lib.rs
Rollup merge of #54308 - dsciarra:issue-22692, r=estebank
[rust.git] / src / librustc_resolve / lib.rs
index 343ef067a6ce86aac59e251bb1e3dd7d58dd8ec8..15bf837b526b1b2e8fdc436346f2884cbbff5e0c 100644 (file)
@@ -13,7 +13,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(crate_visibility_modifier)]
-#![cfg_attr(not(stage0), feature(nll))]
+#![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 
@@ -42,8 +42,9 @@
 use rustc::hir::def::*;
 use rustc::hir::def::Namespace::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
-use rustc::ty;
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
+use rustc::session::config::nightly_options;
+use rustc::ty;
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
 
 use rustc_metadata::creader::CrateLoader;
@@ -65,7 +66,6 @@
 use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
 use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
 use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
-use syntax::feature_gate::{feature_err, GateIssue};
 use syntax::ptr::P;
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
@@ -1351,7 +1351,6 @@ pub struct Resolver<'a, 'b: 'a> {
     graph_root: Module<'a>,
 
     prelude: Option<Module<'a>>,
-    extern_prelude: FxHashSet<Name>,
 
     /// n.b. This is used only for better diagnostics, not name resolution itself.
     has_self: FxHashSet<DefId>,
@@ -1382,6 +1381,9 @@ pub struct Resolver<'a, 'b: 'a> {
     /// The current self type if inside an impl (used for better errors).
     current_self_type: Option<Ty>,
 
+    /// The current self item if inside an ADT (used for better errors).
+    current_self_item: Option<NodeId>,
+
     /// The idents for the primitive types.
     primitive_type_table: PrimitiveTypeTable,
 
@@ -1466,9 +1468,6 @@ pub struct Resolver<'a, 'b: 'a> {
     current_type_ascription: Vec<Span>,
 
     injected_crate: Option<Module<'a>>,
-
-    /// Only supposed to be used by rustdoc, otherwise should be false.
-    pub ignore_extern_prelude_feature: bool,
 }
 
 /// Nothing really interesting here, it just provides memory for the rest of the crate.
@@ -1667,17 +1666,6 @@ 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();
-
-        // HACK(eddyb) this ignore the `no_{core,std}` attributes.
-        // FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`.
-        // if !attr::contains_name(&krate.attrs, "no_core") {
-        // if !attr::contains_name(&krate.attrs, "no_std") {
-        extern_prelude.insert(Symbol::intern("core"));
-        extern_prelude.insert(Symbol::intern("std"));
-        extern_prelude.insert(Symbol::intern("meta"));
-
         let mut invocations = FxHashMap();
         invocations.insert(Mark::root(),
                            arenas.alloc_invocation_data(InvocationData::root(graph_root)));
@@ -1696,7 +1684,6 @@ pub fn new(session: &'a Session,
             // AST.
             graph_root,
             prelude: None,
-            extern_prelude,
 
             has_self: FxHashSet(),
             field_names: FxHashMap(),
@@ -1714,6 +1701,7 @@ pub fn new(session: &'a Session,
 
             current_trait_ref: None,
             current_self_type: None,
+            current_self_item: None,
 
             primitive_type_table: PrimitiveTypeTable::new(),
 
@@ -1766,7 +1754,6 @@ pub fn new(session: &'a Session,
             unused_macros: FxHashSet(),
             current_type_ascription: Vec::new(),
             injected_crate: None,
-            ignore_extern_prelude_feature: false,
         }
     }
 
@@ -1968,14 +1955,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
 
         if !module.no_implicit_prelude {
             // `record_used` means that we don't try to load crates during speculative resolution
-            if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) {
-                if !self.session.features_untracked().extern_prelude &&
-                   !self.ignore_extern_prelude_feature {
-                    feature_err(&self.session.parse_sess, "extern_prelude",
-                                ident.span, GateIssue::Language,
-                                "access to extern crates through prelude is experimental").emit();
-                }
-
+            if record_used && ns == TypeNS && self.session.extern_prelude.contains(&ident.name) {
                 let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
                 let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                 self.populate_module_if_necessary(&crate_root);
@@ -2198,15 +2178,17 @@ fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R>
     }
 
     fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
-        self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
-            let item_def_id = this.definitions.local_def_id(item.id);
-            if this.session.features_untracked().self_in_typedefs {
-                this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
+        self.with_current_self_item(item, |this| {
+            this.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
+                let item_def_id = this.definitions.local_def_id(item.id);
+                if this.session.features_untracked().self_in_typedefs {
+                    this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
+                        visit::walk_item(this, item);
+                    });
+                } else {
                     visit::walk_item(this, item);
-                });
-            } else {
-                visit::walk_item(this, item);
-            }
+                }
+            });
         });
     }
 
@@ -2447,6 +2429,15 @@ fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T
         result
     }
 
+    fn with_current_self_item<T, F>(&mut self, self_item: &Item, f: F) -> T
+        where F: FnOnce(&mut Resolver) -> T
+    {
+        let previous_value = replace(&mut self.current_self_item, Some(self_item.id));
+        let result = f(self);
+        self.current_self_item = previous_value;
+        result
+    }
+
     /// This is called to resolve a trait reference from an `impl` (i.e. `impl Trait for Foo`)
     fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
         where F: FnOnce(&mut Resolver, Option<DefId>) -> T
@@ -3016,12 +3007,17 @@ fn smart_resolve_path_fragment(&mut self,
                     "traits and impls"
                 };
                 err.span_label(span, format!("`Self` is only available in {}", available_in));
+                if this.current_self_item.is_some() && nightly_options::is_nightly_build() {
+                    err.help("add #![feature(self_in_typedefs)] to the crate attributes \
+                              to enable");
+                }
                 return (err, Vec::new());
             }
             if is_self_value(path, ns) {
                 __diagnostic_used!(E0424);
                 err.code(DiagnosticId::Error("E0424".into()));
-                err.span_label(span, format!("`self` value is only available in \
+                err.span_label(span, format!("`self` value is a keyword \
+                                               only available in \
                                                methods with `self` parameter"));
                 return (err, Vec::new());
             }
@@ -3064,7 +3060,8 @@ fn smart_resolve_path_fragment(&mut self,
                                 Applicability::MachineApplicable,
                             );
                             if !self_is_available {
-                                err.span_label(span, format!("`self` value is only available in \
+                                err.span_label(span, format!("`self` value is a keyword \
+                                                               only available in \
                                                                methods with `self` parameter"));
                             }
                         }
@@ -3150,11 +3147,11 @@ fn smart_resolve_path_fragment(&mut self,
                             // parser issue where a struct literal is being used on an expression
                             // where a brace being opened means a block is being started. Look
                             // ahead for the next text to see if `span` is followed by a `{`.
-                            let cm = this.session.source_map();
+                            let sm = this.session.source_map();
                             let mut sp = span;
                             loop {
-                                sp = cm.next_point(sp);
-                                match cm.span_to_snippet(sp) {
+                                sp = sm.next_point(sp);
+                                match sm.span_to_snippet(sp) {
                                     Ok(ref snippet) => {
                                         if snippet.chars().any(|c| { !c.is_whitespace() }) {
                                             break;
@@ -3163,20 +3160,51 @@ fn smart_resolve_path_fragment(&mut self,
                                     _ => break,
                                 }
                             }
-                            let followed_by_brace = match cm.span_to_snippet(sp) {
+                            let followed_by_brace = match sm.span_to_snippet(sp) {
                                 Ok(ref snippet) if snippet == "{" => true,
                                 _ => false,
                             };
-                            if let (PathSource::Expr(None), true) = (source, followed_by_brace) {
-                                err.span_label(
-                                    span,
-                                    format!("did you mean `({} {{ /* fields */ }})`?", path_str),
-                                );
-                            } else {
-                                err.span_label(
-                                    span,
-                                    format!("did you mean `{} {{ /* fields */ }}`?", path_str),
-                                );
+                            match source {
+                                PathSource::Expr(Some(parent)) => {
+                                    match parent.node {
+                                        ExprKind::MethodCall(ref path_assignment, _)  => {
+                                            err.span_suggestion_with_applicability(
+                                                sm.start_point(parent.span)
+                                                  .to(path_assignment.ident.span),
+                                                "use `::` to access an associated function",
+                                                format!("{}::{}",
+                                                        path_str,
+                                                        path_assignment.ident),
+                                                Applicability::MaybeIncorrect
+                                            );
+                                            return (err, candidates);
+                                        },
+                                        _ => {
+                                            err.span_label(
+                                                span,
+                                                format!("did you mean `{} {{ /* fields */ }}`?",
+                                                        path_str),
+                                            );
+                                            return (err, candidates);
+                                        },
+                                    }
+                                },
+                                PathSource::Expr(None) if followed_by_brace == true => {
+                                    err.span_label(
+                                        span,
+                                        format!("did you mean `({} {{ /* fields */ }})`?",
+                                                path_str),
+                                    );
+                                    return (err, candidates);
+                                },
+                                _ => {
+                                    err.span_label(
+                                        span,
+                                        format!("did you mean `{} {{ /* fields */ }}`?",
+                                                path_str),
+                                    );
+                                    return (err, candidates);
+                                },
                             }
                         }
                         return (err, candidates);
@@ -3576,7 +3604,6 @@ fn resolve_path_with_parent_scope(
                     }
                     if name == keywords::Extern.name() ||
                        name == keywords::CrateRoot.name() &&
-                       self.session.features_untracked().extern_absolute_paths &&
                        self.session.rust_2018() {
                         module = Some(ModuleOrUniformRoot::UniformRoot(name));
                         continue;
@@ -3715,12 +3742,6 @@ fn lint_if_path_starts_with_module(
             return
         }
 
-        // In the 2015 edition there's no use in emitting lints unless the
-        // crate's already enabled the feature that we're going to suggest
-        if !self.session.features_untracked().crate_in_paths {
-            return
-        }
-
         let (diag_id, diag_span) = match crate_lint {
             CrateLint::No => return,
             CrateLint::SimplePath(id) => (id, path_span),
@@ -3972,7 +3993,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.session.extern_prelude.iter().cloned());
                             if let Some(prelude) = self.prelude {
                                 add_module_candidates(prelude, &mut names);
                             }
@@ -4417,9 +4438,8 @@ fn lookup_import_candidates<FilterFn>(&mut self,
             )
         );
 
-        if self.session.features_untracked().extern_prelude {
-            let extern_prelude_names = self.extern_prelude.clone();
-            for &name in extern_prelude_names.iter() {
+        if self.session.rust_2018() {
+            for &name in &self.session.extern_prelude {
                 let ident = Ident::with_empty_ctxt(name);
                 match self.crate_loader.maybe_process_path_extern(name, ident.span) {
                     Some(crate_id) => {