From 2e9b89ddc50f0409290a9f906cae8817c2473f9e Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sat, 4 Nov 2017 23:56:45 +0300
Subject: [PATCH 1/2] Support `::crate` in paths

---
 src/librustc_passes/ast_validation.rs         | 13 -------
 src/librustc_resolve/build_reduced_graph.rs   | 10 +-----
 src/librustc_resolve/lib.rs                   | 18 ++++++----
 src/libsyntax/ast.rs                          | 11 ++++--
 src/libsyntax/feature_gate.rs                 | 16 ++++++++-
 src/libsyntax/parse/parser.rs                 | 17 +++++++--
 src/libsyntax/parse/token.rs                  |  1 +
 .../crate-path-non-absolute.rs                | 21 +++++++++++
 .../crate-visibility-ambiguity.rs             | 23 ++++++++++++
 .../feature-gate-crate_in_paths.rs            | 15 ++++++++
 .../keyword-crate-as-identifier.rs            |  6 ++--
 .../compile-fail/use-super-global-path.rs     |  4 +--
 .../crate-path-absolute.rs                    | 36 +++++++++++++++++++
 13 files changed, 150 insertions(+), 41 deletions(-)
 create mode 100644 src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs
 create mode 100644 src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs
 create mode 100644 src/test/compile-fail/rfc-2126-crate-paths/feature-gate-crate_in_paths.rs
 rename src/test/{parse-fail => compile-fail/rfc-2126-crate-paths}/keyword-crate-as-identifier.rs (72%)
 create mode 100644 src/test/run-pass/rfc-2126-crate-paths/crate-path-absolute.rs

diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 40adc6bcb122f..3136aeaf8ca1f 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -21,7 +21,6 @@ use rustc::session::Session;
 use syntax::ast::*;
 use syntax::attr;
 use syntax::codemap::Spanned;
-use syntax::parse::token;
 use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 use syntax_pos::Span;
@@ -182,18 +181,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_ty(self, ty)
     }
 
-    fn visit_path(&mut self, path: &'a Path, _: NodeId) {
-        if path.segments.len() >= 2 && path.is_global() {
-            let ident = path.segments[1].identifier;
-            if token::Ident(ident).is_path_segment_keyword() {
-                self.err_handler()
-                    .span_err(path.span, &format!("global paths cannot start with `{}`", ident));
-            }
-        }
-
-        visit::walk_path(self, path)
-    }
-
     fn visit_item(&mut self, item: &'a Item) {
         match item.node {
             ItemKind::Use(ref view_path) => {
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index b30fc38fcbcdf..46513a5740aed 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -114,7 +114,7 @@ impl<'a> Resolver<'a> {
                 // Extract and intern the module part of the path. For
                 // globs and lists, the path is found directly in the AST;
                 // for simple paths we have to munge the path a little.
-                let mut module_path: Vec<_> = match view_path.node {
+                let module_path: Vec<_> = match view_path.node {
                     ViewPathSimple(_, ref full_path) => {
                         full_path.segments
                                  .split_last()
@@ -134,14 +134,6 @@ impl<'a> Resolver<'a> {
                     }
                 };
 
-                // This can be removed once warning cycle #36888 is complete.
-                if module_path.len() >= 2 &&
-                    module_path[0].node.name == keywords::CrateRoot.name() &&
-                    token::Ident(module_path[1].node).is_path_segment_keyword()
-                {
-                    module_path.remove(0);
-                }
-
                 // Build up the import directives.
                 let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 8207057fd0aae..5cf09d0d89aa9 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2886,12 +2886,18 @@ impl<'a> Resolver<'a> {
             }
             allow_super = false;
 
-            if i == 0 && ns == TypeNS && ident.node.name == keywords::CrateRoot.name() {
-                module = Some(self.resolve_crate_root(ident.node.ctxt.modern()));
-                continue
-            } else if i == 0 && ns == TypeNS && ident.node.name == keywords::DollarCrate.name() {
-                module = Some(self.resolve_crate_root(ident.node.ctxt));
-                continue
+            if ns == TypeNS {
+                if (i == 0 && ident.node.name == keywords::CrateRoot.name()) ||
+                   (i == 1 && ident.node.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() {
+                    // `$crate::a::b`
+                    module = Some(self.resolve_crate_root(ident.node.ctxt));
+                    continue
+                }
             }
 
             let binding = if let Some(module) = module {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 99dff4edaade7..ad9d58651207d 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -96,10 +96,15 @@ impl Path {
         }
     }
 
+    // Add starting "crate root" segment to all paths except those that
+    // already have it or start with `self`, `super`, `Self` or `$crate`.
     pub fn default_to_global(mut self) -> Path {
-        if !self.is_global() &&
-           !::parse::token::Ident(self.segments[0].identifier).is_path_segment_keyword() {
-            self.segments.insert(0, PathSegment::crate_root(self.span));
+        if !self.is_global() {
+            let ident = self.segments[0].identifier;
+            if !::parse::token::Ident(ident).is_path_segment_keyword() ||
+               ident.name == keywords::Crate.name() {
+                self.segments.insert(0, PathSegment::crate_root(self.span));
+            }
         }
         self
     }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index ebe7853b8abdb..6b12b55eec7e1 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -33,7 +33,7 @@ use syntax_pos::Span;
 use errors::{DiagnosticBuilder, Handler, FatalError};
 use visit::{self, FnKind, Visitor};
 use parse::ParseSess;
-use symbol::Symbol;
+use symbol::{keywords, Symbol};
 
 use std::env;
 
@@ -418,6 +418,9 @@ declare_features! (
 
     // #![wasm_import_memory] attribute
     (active, wasm_import_memory, "1.22.0", None),
+
+    // `crate` in paths
+    (active, crate_in_paths, "1.23.0", Some(45477)),
 );
 
 declare_features! (
@@ -1628,6 +1631,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         visit::walk_impl_item(self, ii);
     }
 
+    fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) {
+        for segment in &path.segments {
+            if segment.identifier.name == keywords::Crate.name() {
+                gate_feature_post!(&self, crate_in_paths, segment.span,
+                                   "`crate` in paths is experimental");
+            }
+        }
+
+        visit::walk_path(self, path);
+    }
+
     fn visit_vis(&mut self, vis: &'a ast::Visibility) {
         if let ast::Visibility::Crate(span, ast::CrateSugar::JustCrate) = *vis {
             gate_feature_post!(&self, crate_visibility_modifier, span,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index c1819307928ba..0b03429ea2e52 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3916,6 +3916,10 @@ impl<'a> Parser<'a> {
         self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
     }
 
+    fn is_crate_vis(&self) -> bool {
+        self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
+    }
+
     fn eat_auto_trait(&mut self) -> bool {
         if self.token.is_keyword(keywords::Auto)
             && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
@@ -4026,10 +4030,15 @@ impl<'a> Parser<'a> {
                 node: StmtKind::Item(macro_def),
                 span: lo.to(self.prev_span),
             }
-        // Starts like a simple path, but not a union item.
+        // Starts like a simple path, but not a union item or item with `crate` visibility.
+        // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts
+        // like a path (1 token), but it fact not a path.
+        // `union::b::c` - path, `union U { ... }` - not a path.
+        // `crate::b::c` - path, `crate struct S;` - not a path.
         } else if self.token.is_path_start() &&
                   !self.token.is_qpath_start() &&
-                  !self.is_union_item() {
+                  !self.is_union_item() &&
+                  !self.is_crate_vis() {
             let pth = self.parse_path(PathStyle::Expr)?;
 
             if !self.eat(&token::Not) {
@@ -5399,7 +5408,9 @@ impl<'a> Parser<'a> {
     pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> {
         maybe_whole!(self, NtVis, |x| x);
 
-        if self.eat_keyword(keywords::Crate) {
+        self.expected_tokens.push(TokenType::Keyword(keywords::Crate));
+        if self.is_crate_vis() {
+            self.bump(); // `crate`
             return Ok(Visibility::Crate(self.prev_span, CrateSugar::JustCrate));
         }
 
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index f83343bf9afa5..ff87f146c0a71 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -347,6 +347,7 @@ impl Token {
             Some(id) => id.name == keywords::Super.name() ||
                         id.name == keywords::SelfValue.name() ||
                         id.name == keywords::SelfType.name() ||
+                        id.name == keywords::Crate.name() ||
                         id.name == keywords::DollarCrate.name(),
             None => false,
         }
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
new file mode 100644
index 0000000000000..11841e6e3efbc
--- /dev/null
+++ b/src/test/compile-fail/rfc-2126-crate-paths/crate-path-non-absolute.rs
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(crate_in_paths)]
+
+struct S;
+
+mod m {
+    fn f() {
+        let s = crate::S; //~ ERROR undeclared type or module `crate`
+    }
+}
+
+fn main() {}
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
new file mode 100644
index 0000000000000..cb587ecc8545c
--- /dev/null
+++ b/src/test/compile-fail/rfc-2126-crate-paths/crate-visibility-ambiguity.rs
@@ -0,0 +1,23 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(crate_in_paths)]
+#![feature(crate_visibility_modifier)]
+
+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`
+}
+
+fn main() {
+    crate struct S; // OK (item in statement position)
+}
diff --git a/src/test/compile-fail/rfc-2126-crate-paths/feature-gate-crate_in_paths.rs b/src/test/compile-fail/rfc-2126-crate-paths/feature-gate-crate_in_paths.rs
new file mode 100644
index 0000000000000..830ec5959b702
--- /dev/null
+++ b/src/test/compile-fail/rfc-2126-crate-paths/feature-gate-crate_in_paths.rs
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S;
+
+fn main() {
+    let _ = ::crate::S; //~ ERROR `crate` in paths is experimental
+}
diff --git a/src/test/parse-fail/keyword-crate-as-identifier.rs b/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
similarity index 72%
rename from src/test/parse-fail/keyword-crate-as-identifier.rs
rename to src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
index 8a914ca7b178c..b4a650efebe37 100644
--- a/src/test/parse-fail/keyword-crate-as-identifier.rs
+++ b/src/test/compile-fail/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
@@ -8,10 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z parse-only
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py crate'
+#![feature(crate_in_paths)]
 
 fn main() {
-    let crate = "foo"; //~ error: expected pattern, found keyword `crate`
+    let crate = 0; //~ ERROR cannot find unit struct/variant or constant `crate` in this scope
 }
diff --git a/src/test/compile-fail/use-super-global-path.rs b/src/test/compile-fail/use-super-global-path.rs
index 4162e037cf32e..24d3bccdf24e5 100644
--- a/src/test/compile-fail/use-super-global-path.rs
+++ b/src/test/compile-fail/use-super-global-path.rs
@@ -14,10 +14,10 @@ struct S;
 struct Z;
 
 mod foo {
-    use ::super::{S, Z}; //~ ERROR global paths cannot start with `super`
+    use ::super::{S, Z}; //~ ERROR unresolved import `super`
 
     pub fn g() {
-        use ::super::main; //~ ERROR global paths cannot start with `super`
+        use ::super::main; //~ ERROR unresolved import `super`
         main();
     }
 }
diff --git a/src/test/run-pass/rfc-2126-crate-paths/crate-path-absolute.rs b/src/test/run-pass/rfc-2126-crate-paths/crate-path-absolute.rs
new file mode 100644
index 0000000000000..172c34e79d233
--- /dev/null
+++ b/src/test/run-pass/rfc-2126-crate-paths/crate-path-absolute.rs
@@ -0,0 +1,36 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(crate_in_paths)]
+
+use crate::m::f;
+
+mod m {
+    pub fn f() -> u8 { 1 }
+    pub fn g() -> u8 { 2 }
+
+    // OK, visibilities are implicitly absolute like imports
+    pub(in crate::m) struct S;
+}
+
+mod n
+{
+    use crate::m::f;
+    pub fn check() {
+        assert_eq!(f(), 1);
+        assert_eq!(::crate::m::g(), 2);
+    }
+}
+
+fn main() {
+    assert_eq!(f(), 1);
+    assert_eq!(::crate::m::g(), 2);
+    n::check();
+}

From 90f5cfdfbd3c9e39f897fd2271c7b1c7fdaae58e Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sun, 19 Nov 2017 17:05:29 +0300
Subject: [PATCH 2/2] Report special messages for path segment keywords in
 wrong positions

---
 src/librustc_resolve/lib.rs                   | 36 +++++++++++++++----
 src/librustc_resolve/resolve_imports.rs       | 10 ++++--
 .../compile-fail/dollar-crate-is-keyword-2.rs |  4 +--
 .../crate-path-non-absolute.rs                |  2 +-
 .../crate-visibility-ambiguity.rs             |  2 +-
 .../keyword-crate-as-identifier.rs            |  2 +-
 src/test/compile-fail/super-at-top-level.rs   |  3 +-
 .../compile-fail/use-super-global-path.rs     |  6 ++--
 8 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 5cf09d0d89aa9..42c31a6e47eaa 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 bcbabd700946a..d72253e5a8a48 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 ac96279d61467..87a2903803581 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 11841e6e3efbc..75c2a5f5bc477 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 cb587ecc8545c..8c5a971c2f756 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 b4a650efebe37..2c94f7b0f59df 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 4db673e2006f5..c607711c44f37 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 24d3bccdf24e5..fc1a72f6f2b90 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
     }
 }