about summary refs log tree commit diff
path: root/src/librustc_resolve
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-04-25 04:19:06 +0000
committerbors <bors@rust-lang.org>2018-04-25 04:19:06 +0000
commit432fe0cefc76045a98a38ba6c7a74b018aae1b7d (patch)
tree92e4e30e507b840bff4200b9728b803912410055 /src/librustc_resolve
parent0c5740feb24bff4f13b68b565288dd8a42ab93f6 (diff)
parent2a5ce10dfb20e794d324cb1621e5ac892b7e421a (diff)
downloadrust-432fe0cefc76045a98a38ba6c7a74b018aae1b7d.tar.gz
rust-432fe0cefc76045a98a38ba6c7a74b018aae1b7d.zip
Auto merge of #50100 - Manishearth:edition-path-lint, r=nikomatsakis
Edition breakage lint for absolute paths starting with modules

We plan to enable `extern_absolute_paths` in the 2018 edition. To allow for that, folks must transition their paths in a previous edition to the new one. This makes paths which import module contents via `use module::` or `::module::` obsolete, and we must edition-lint these.

https://internals.rust-lang.org/t/the-great-module-adventure-continues/6678/205?u=manishearth is the current plan for paths.

r? @nikomatsakis

Fixes #48722
Diffstat (limited to 'src/librustc_resolve')
-rw-r--r--src/librustc_resolve/lib.rs50
-rw-r--r--src/librustc_resolve/macros.rs4
-rw-r--r--src/librustc_resolve/resolve_imports.rs8
3 files changed, 49 insertions, 13 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 671856c4e54..7a87a72afc2 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1654,11 +1654,12 @@ impl<'a> Resolver<'a> {
         let path: Vec<Ident> = segments.iter()
             .map(|seg| Ident::new(seg.name, span))
             .collect();
-        match self.resolve_path(&path, Some(namespace), true, span) {
+        // FIXME (Manishearth): Intra doc links won't get warned of epoch changes
+        match self.resolve_path(&path, Some(namespace), true, span, None) {
             PathResult::Module(module) => *def = module.def().unwrap(),
             PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
                 *def = path_res.base_def(),
-            PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) {
+            PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span, None) {
                 PathResult::Failed(span, msg, _) => {
                     error_callback(self, span, ResolutionError::FailedToResolve(&msg));
                 }
@@ -2360,7 +2361,8 @@ impl<'a> Resolver<'a> {
             if def != Def::Err {
                 new_id = Some(def.def_id());
                 let span = trait_ref.path.span;
-                if let PathResult::Module(module) = self.resolve_path(&path, None, false, span) {
+                if let PathResult::Module(module) = self.resolve_path(&path, None, false, span,
+                                                                      Some(trait_ref.ref_id)) {
                     new_val = Some((module, trait_ref.clone()));
                 }
             }
@@ -2819,7 +2821,8 @@ impl<'a> Resolver<'a> {
                     (format!(""), format!("the crate root"))
                 } else {
                     let mod_path = &path[..path.len() - 1];
-                    let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), false, span) {
+                    let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS),
+                                                             false, span, None) {
                         PathResult::Module(module) => module.def(),
                         _ => None,
                     }.map_or(format!(""), |def| format!("{} ", def.kind_name()));
@@ -3149,7 +3152,7 @@ impl<'a> Resolver<'a> {
             ));
         }
 
-        let result = match self.resolve_path(&path, Some(ns), true, span) {
+        let result = match self.resolve_path(&path, Some(ns), true, span, Some(id)) {
             PathResult::NonModule(path_res) => path_res,
             PathResult::Module(module) if !module.is_normal() => {
                 PathResolution::new(module.def().unwrap())
@@ -3186,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) {
+                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),
@@ -3205,7 +3208,9 @@ impl<'a> Resolver<'a> {
                     path: &[Ident],
                     opt_ns: Option<Namespace>, // `None` indicates a module path
                     record_used: bool,
-                    path_span: Span)
+                    path_span: Span,
+                    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;
@@ -3253,6 +3258,8 @@ impl<'a> Resolver<'a> {
                     let prev_name = path[0].name;
                     if prev_name == keywords::Extern.name() ||
                        prev_name == keywords::CrateRoot.name() &&
+                       // Note: When this feature stabilizes, this should
+                       // be gated on sess.rust_2018()
                        self.session.features_untracked().extern_absolute_paths {
                         // `::extern_crate::a::b`
                         let crate_id = self.crate_loader.process_path_extern(name, ident.span);
@@ -3324,6 +3331,33 @@ 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 {
+                                    let diag = lint::builtin::BuiltinLintDiagnostics
+                                                   ::AbsPathWithModule(path_span);
+                                    self.session.buffer_lint_with_diagnostic(
+                                        lint::builtin::ABSOLUTE_PATH_STARTING_WITH_MODULE,
+                                        id, path_span,
+                                        "Absolute paths must start with `self`, `super`, \
+                                        `crate`, or an external crate name in the 2018 edition",
+                                        diag);
+                                }
+                            }
+                        }
+                    }
                 }
                 Err(Undetermined) => return PathResult::Indeterminate,
                 Err(Determined) => {
@@ -3571,7 +3605,7 @@ impl<'a> Resolver<'a> {
             // Search in module.
             let mod_path = &path[..path.len() - 1];
             if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS),
-                                                                  false, span) {
+                                                                  false, span, None) {
                 add_module_candidates(module, &mut names);
             }
         }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 3a859c02c16..af1e17cd89c 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -438,7 +438,7 @@ impl<'a> Resolver<'a> {
                 return Err(Determinacy::Determined);
             }
 
-            let def = match self.resolve_path(&path, Some(MacroNS), false, span) {
+            let def = match self.resolve_path(&path, Some(MacroNS), false, span, None) {
                 PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => {
@@ -616,7 +616,7 @@ impl<'a> Resolver<'a> {
     pub fn finalize_current_module_macro_resolutions(&mut self) {
         let module = self.current_module;
         for &(ref path, span) in module.macro_resolutions.borrow().iter() {
-            match self.resolve_path(&path, Some(MacroNS), true, span) {
+            match self.resolve_path(&path, Some(MacroNS), true, span, None) {
                 PathResult::NonModule(_) => {},
                 PathResult::Failed(span, msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 37c62a7b0b4..e2a7f5668d2 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -535,7 +535,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             // For better failure detection, pretend that the import will not define any names
             // while resolving its module path.
             directive.vis.set(ty::Visibility::Invisible);
-            let result = self.resolve_path(&directive.module_path[..], None, false, directive.span);
+            let result = self.resolve_path(&directive.module_path[..], None, false,
+                                           directive.span, Some(directive.id));
             directive.vis.set(vis);
 
             match result {
@@ -663,7 +664,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             }
         }
 
-        let module_result = self.resolve_path(&module_path, None, true, span);
+        let module_result = self.resolve_path(&module_path, None, true, span, Some(directive.id));
         let module = match module_result {
             PathResult::Module(module) => module,
             PathResult::Failed(span, msg, false) => {
@@ -677,7 +678,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 if !self_path.is_empty() && !is_special(self_path[0]) &&
                    !(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));
+                    self_result = Some(self.resolve_path(&self_path, None, false,
+                                                         span, None));
                 }
                 return if let Some(PathResult::Module(..)) = self_result {
                     Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..]))))