about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2018-04-19 16:45:33 -0700
committerManish Goregaokar <manishsmail@gmail.com>2018-04-20 15:58:59 -0700
commit37d3bea3ec3d47dbf1f7352c32fab75ce408798c (patch)
tree95ccaea95f6b86d2818dbf6b02902ee5f7feea61
parent56ace0aac21c46e8340e0912e822724c5d15922e (diff)
downloadrust-37d3bea3ec3d47dbf1f7352c32fab75ce408798c.tar.gz
rust-37d3bea3ec3d47dbf1f7352c32fab75ce408798c.zip
Add ABSOLUTE_PATH_STARTING_WITH_MODULE epoch lint for path breakage
-rw-r--r--src/librustc/lint/builtin.rs8
-rw-r--r--src/librustc_lint/lib.rs7
-rw-r--r--src/librustc_resolve/lib.rs29
-rw-r--r--src/librustc_resolve/resolve_imports.rs2
4 files changed, 42 insertions, 4 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 97cfcf0f607..30ae830ee46 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -255,6 +255,13 @@ declare_lint! {
 }
 
 declare_lint! {
+    pub ABSOLUTE_PATH_STARTING_WITH_MODULE,
+    Allow,
+    "fully qualified paths that start with a module name \
+     instead of `crate`, `self`, or an extern crate name"
+}
+
+declare_lint! {
     pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
     Warn,
     "floating-point literals cannot be used in patterns"
@@ -314,6 +321,7 @@ impl LintPass for HardwiredLints {
             TYVAR_BEHIND_RAW_POINTER,
             ELIDED_LIFETIME_IN_PATH,
             BARE_TRAIT_OBJECT,
+            ABSOLUTE_PATH_STARTING_WITH_MODULE,
             UNSTABLE_NAME_COLLISION,
         )
     }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 16e8600f2d8..038d47dd5ea 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -40,7 +40,7 @@ extern crate rustc_mir;
 extern crate syntax_pos;
 
 use rustc::lint;
-use rustc::lint::builtin::BARE_TRAIT_OBJECT;
+use rustc::lint::builtin::{BARE_TRAIT_OBJECT, ABSOLUTE_PATH_STARTING_WITH_MODULE};
 use rustc::session;
 use rustc::util;
 
@@ -278,6 +278,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             // Note: this item represents future incompatibility of all unstable functions in the
             //       standard library, and thus should never be removed or changed to an error.
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(ABSOLUTE_PATH_STARTING_WITH_MODULE),
+            reference: "issue TBD",
+            edition: Some(Edition::Edition2018),
+        },
         ]);
 
     // Register renamed and removed lints
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 1abf336ed73..c0bb6921b69 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -3189,7 +3189,7 @@ impl<'a> Resolver<'a> {
            path[0].name != keywords::CrateRoot.name() &&
            path[0].name != keywords::DollarCrate.name() {
             let unqualified_result = {
-                match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span, Some(id)) {
+                match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span, None) {
                     PathResult::NonModule(path_res) => path_res.base_def(),
                     PathResult::Module(module) => module.def().unwrap(),
                     _ => return Some(result),
@@ -3209,7 +3209,8 @@ impl<'a> Resolver<'a> {
                     opt_ns: Option<Namespace>, // `None` indicates a module path
                     record_used: bool,
                     path_span: Span,
-                    _node_id: Option<NodeId>)
+                    node_id: Option<NodeId>) // None indicates that we don't care about linting
+                                             // `::module` paths
                     -> PathResult<'a> {
         let mut module = None;
         let mut allow_super = true;
@@ -3328,6 +3329,30 @@ impl<'a> Resolver<'a> {
                                                   format!("Not a module `{}`", ident),
                                                   is_last);
                     }
+
+                    if let Some(id) = node_id {
+                        if i == 1 && self.session.features_untracked().crate_in_paths
+                                  && !self.session.rust_2018() {
+                            let prev_name = path[0].name;
+                            if prev_name == keywords::Extern.name() ||
+                               prev_name == keywords::CrateRoot.name() {
+                                let mut is_crate = false;
+                                if let NameBindingKind::Import { directive: d, .. } = binding.kind {
+                                    if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass {
+                                        is_crate = true;
+                                    }
+                                }
+
+                                if !is_crate {
+                                    self.session.buffer_lint(
+                                        lint::builtin::ABSOLUTE_PATH_STARTING_WITH_MODULE,
+                                        id, path_span,
+                                        "Fully-qualified paths must start with `self`, `super`,
+                                        `crate`, or an external crate name in the 2018 edition");
+                                }
+                            }
+                        }
+                    }
                 }
                 Err(Undetermined) => return PathResult::Indeterminate,
                 Err(Determined) => {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index d6230cc4a67..e2a7f5668d2 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -679,7 +679,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                    !(self_path.len() > 1 && is_special(self_path[1])) {
                     self_path[0].name = keywords::SelfValue.name();
                     self_result = Some(self.resolve_path(&self_path, None, false,
-                                                         span, Some(directive.id)));
+                                                         span, None));
                 }
                 return if let Some(PathResult::Module(..)) = self_result {
                     Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..]))))