about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-11-19 17:05:29 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-11-21 00:21:24 +0300
commit90f5cfdfbd3c9e39f897fd2271c7b1c7fdaae58e (patch)
tree377d63555a472a48dfe9229d8da3c472bb591c5d
parent2e9b89ddc50f0409290a9f906cae8817c2473f9e (diff)
downloadrust-90f5cfdfbd3c9e39f897fd2271c7b1c7fdaae58e.tar.gz
rust-90f5cfdfbd3c9e39f897fd2271c7b1c7fdaae58e.zip
Report special messages for path segment keywords in wrong positions
-rw-r--r--src/librustc_resolve/lib.rs36
-rw-r--r--src/librustc_resolve/resolve_imports.rs10
-rw-r--r--src/test/compile-fail/dollar-crate-is-keyword-2.rs4
-rw-r--r--src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs2
-rw-r--r--src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs2
-rw-r--r--src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs2
-rw-r--r--src/test/compile-fail/super-at-top-level.rs3
-rw-r--r--src/test/compile-fail/use-super-global-path.rs6
8 files changed, 47 insertions, 18 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 5cf09d0d89a..42c31a6e47e 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2865,12 +2865,13 @@ impl<'a> Resolver<'a> {
             debug!("resolve_path ident {} {:?}", i, ident);
             let is_last = i == path.len() - 1;
             let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
+            let name = ident.node.name;
 
-            if i == 0 && ns == TypeNS && ident.node.name == keywords::SelfValue.name() {
+            if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
                 let mut ctxt = ident.node.ctxt.modern();
                 module = Some(self.resolve_self(&mut ctxt, self.current_module));
                 continue
-            } else if allow_super && ns == TypeNS && ident.node.name == keywords::Super.name() {
+            } else if allow_super && ns == TypeNS && name == keywords::Super.name() {
                 let mut ctxt = ident.node.ctxt.modern();
                 let self_module = match i {
                     0 => self.resolve_self(&mut ctxt, self.current_module),
@@ -2887,19 +2888,42 @@ impl<'a> Resolver<'a> {
             allow_super = false;
 
             if ns == TypeNS {
-                if (i == 0 && ident.node.name == keywords::CrateRoot.name()) ||
-                   (i == 1 && ident.node.name == keywords::Crate.name() &&
+                if (i == 0 && name == keywords::CrateRoot.name()) ||
+                   (i == 1 && name == keywords::Crate.name() &&
                               path[0].node.name == keywords::CrateRoot.name()) {
                     // `::a::b` or `::crate::a::b`
                     module = Some(self.resolve_crate_root(ident.node.ctxt.modern()));
                     continue
-                } else if i == 0 && ident.node.name == keywords::DollarCrate.name() {
+                } else if i == 0 && name == keywords::DollarCrate.name() {
                     // `$crate::a::b`
                     module = Some(self.resolve_crate_root(ident.node.ctxt));
                     continue
                 }
             }
 
+            // Report special messages for path segment keywords in wrong positions.
+            if name == keywords::CrateRoot.name() && i != 0 ||
+               name == keywords::DollarCrate.name() && i != 0 ||
+               name == keywords::SelfValue.name() && i != 0 ||
+               name == keywords::SelfType.name() && i != 0 ||
+               name == keywords::Super.name() && i != 0 ||
+               name == keywords::Crate.name() && i != 1 &&
+                    path[0].node.name != keywords::CrateRoot.name() {
+                let name_str = if name == keywords::CrateRoot.name() {
+                    format!("crate root")
+                } else {
+                    format!("`{}`", name)
+                };
+                let msg = if i == 1 && path[0].node.name == keywords::CrateRoot.name() {
+                    format!("global paths cannot start with {}", name_str)
+                } else if i == 0 && name == keywords::Crate.name() {
+                    format!("{} can only be used in absolute paths", name_str)
+                } else {
+                    format!("{} in paths can only be used in start position", name_str)
+                };
+                return PathResult::Failed(ident.span, msg, false);
+            }
+
             let binding = if let Some(module) = module {
                 self.resolve_ident_in_module(module, ident.node, ns, false, record_used, path_span)
             } else if opt_ns == Some(MacroNS) {
@@ -2948,7 +2972,7 @@ impl<'a> Resolver<'a> {
                     let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
                         let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
                         let mut candidates =
-                            self.lookup_import_candidates(ident.node.name, TypeNS, is_mod);
+                            self.lookup_import_candidates(name, TypeNS, is_mod);
                         candidates.sort_by_key(|c| (c.path.segments.len(), c.path.to_string()));
                         if let Some(candidate) = candidates.get(0) {
                             format!("Did you mean `{}`?", candidate.path)
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index bcbabd70094..d72253e5a8a 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -606,10 +606,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         let module_result = self.resolve_path(&module_path, None, true, span);
         let module = match module_result {
             PathResult::Module(module) => module,
-            PathResult::Failed(span, msg, _) => {
+            PathResult::Failed(span, msg, false) => {
+                resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
+                return None;
+            }
+            PathResult::Failed(span, msg, true) => {
                 let (mut self_path, mut self_result) = (module_path.clone(), None);
                 if !self_path.is_empty() &&
-                    !token::Ident(self_path[0].node).is_path_segment_keyword()
+                    !token::Ident(self_path[0].node).is_path_segment_keyword() &&
+                    !(self_path.len() > 1 &&
+                      token::Ident(self_path[1].node).is_path_segment_keyword())
                 {
                     self_path[0].node.name = keywords::SelfValue.name();
                     self_result = Some(self.resolve_path(&self_path, None, false, span));
diff --git a/src/test/compile-fail/dollar-crate-is-keyword-2.rs b/src/test/compile-fail/dollar-crate-is-keyword-2.rs
index ac96279d614..87a29038035 100644
--- a/src/test/compile-fail/dollar-crate-is-keyword-2.rs
+++ b/src/test/compile-fail/dollar-crate-is-keyword-2.rs
@@ -13,8 +13,8 @@ mod a {}
 macro_rules! m {
     () => {
         use a::$crate; //~ ERROR unresolved import `a::$crate`
-        use a::$crate::b; //~ ERROR unresolved import `a::$crate`
-        type A = a::$crate; //~ ERROR cannot find type `$crate` in module `a`
+        use a::$crate::b; //~ ERROR `$crate` in paths can only be used in start position
+        type A = a::$crate; //~ ERROR `$crate` in paths can only be used in start position
     }
 }
 
diff --git a/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs b/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs
index 11841e6e3ef..75c2a5f5bc4 100644
--- a/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs
+++ b/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs
@@ -14,7 +14,7 @@ struct S;
 
 mod m {
     fn f() {
-        let s = crate::S; //~ ERROR undeclared type or module `crate`
+        let s = crate::S; //~ ERROR `crate` can only be used in absolute paths
     }
 }
 
diff --git a/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs b/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs
index cb587ecc854..8c5a971c2f7 100644
--- a/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs
+++ b/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs
@@ -15,7 +15,7 @@ mod m {
     pub struct Z;
     pub struct S1(crate (::m::Z)); // OK
     pub struct S2(::crate ::m::Z); // OK
-    pub struct S3(crate ::m::Z); //~ ERROR undeclared type or module `crate`
+    pub struct S3(crate ::m::Z); //~ ERROR `crate` can only be used in absolute paths
 }
 
 fn main() {
diff --git a/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs b/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
index b4a650efebe..2c94f7b0f59 100644
--- a/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
+++ b/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
@@ -11,5 +11,5 @@
 #![feature(crate_in_paths)]
 
 fn main() {
-    let crate = 0; //~ ERROR cannot find unit struct/variant or constant `crate` in this scope
+    let crate = 0; //~ ERROR `crate` can only be used in absolute paths
 }
diff --git a/src/test/compile-fail/super-at-top-level.rs b/src/test/compile-fail/super-at-top-level.rs
index 4db673e2006..c607711c44f 100644
--- a/src/test/compile-fail/super-at-top-level.rs
+++ b/src/test/compile-fail/super-at-top-level.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::f; //~ ERROR unresolved import `super` [E0432]
-              //~^ There are too many initial `super`s.
+use super::f; //~ ERROR There are too many initial `super`s
 
 fn main() {
 }
diff --git a/src/test/compile-fail/use-super-global-path.rs b/src/test/compile-fail/use-super-global-path.rs
index 24d3bccdf24..fc1a72f6f2b 100644
--- a/src/test/compile-fail/use-super-global-path.rs
+++ b/src/test/compile-fail/use-super-global-path.rs
@@ -14,11 +14,11 @@ struct S;
 struct Z;
 
 mod foo {
-    use ::super::{S, Z}; //~ ERROR unresolved import `super`
+    use ::super::{S, Z}; //~ ERROR global paths cannot start with `super`
 
     pub fn g() {
-        use ::super::main; //~ ERROR unresolved import `super`
-        main();
+        use ::super::main; //~ ERROR global paths cannot start with `super`
+        main(); //~ ERROR cannot find function `main` in this scope
     }
 }