]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/lib.rs
Auto merge of #54601 - cuviper:prep-1.31, r=Mark-Simulacrum
[rust.git] / src / librustc_resolve / lib.rs
index a4f8f16cac2b227663ea4812cf6f2a23a19755c6..a68c89deea5b6a070c7be0e57c6f8cf9117ecc47 100644 (file)
@@ -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;
@@ -1381,6 +1382,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,
 
@@ -1710,6 +1714,7 @@ pub fn new(session: &'a Session,
 
             current_trait_ref: None,
             current_self_type: None,
+            current_self_item: None,
 
             primitive_type_table: PrimitiveTypeTable::new(),
 
@@ -2186,15 +2191,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);
-            }
+                }
+            });
         });
     }
 
@@ -2435,6 +2442,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
@@ -3004,6 +3020,10 @@ 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) {