about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-05-22 11:10:17 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-05-22 11:10:17 -0400
commit068c4364c7f793e12d998f5b9b212e723dafa210 (patch)
tree2b99c8214a3cc615cd6e1f63fafe27ca7e2b386b
parentcce913278041031bce87563fa985b0718f8ad939 (diff)
downloadrust-068c4364c7f793e12d998f5b9b212e723dafa210.tar.gz
rust-068c4364c7f793e12d998f5b9b212e723dafa210.zip
pass down information about the root tree and use that to guide lint
-rw-r--r--src/librustc_resolve/lib.rs78
-rw-r--r--src/librustc_resolve/macros.rs6
-rw-r--r--src/librustc_resolve/resolve_imports.rs12
3 files changed, 62 insertions, 34 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index e13e6bc6b74..939e6202257 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -12,6 +12,7 @@
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 
+#![feature(crate_visibility_modifier)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 
@@ -1655,11 +1656,11 @@ impl<'a> Resolver<'a> {
             .map(|seg| Ident::new(seg.name, span))
             .collect();
         // FIXME (Manishearth): Intra doc links won't get warned of epoch changes
-        match self.resolve_path(&path, Some(namespace), true, span, None) {
+        match self.resolve_path(&path, Some(namespace), true, span, CrateLint::No) {
             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, None) {
+            PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span, CrateLint::No) {
                 PathResult::Failed(span, msg, _) => {
                     error_callback(self, span, ResolutionError::FailedToResolve(&msg));
                 }
@@ -2378,8 +2379,13 @@ 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,
-                                                                      Some(trait_ref.ref_id)) {
+                if let PathResult::Module(module) = self.resolve_path(
+                    &path,
+                    None,
+                    false,
+                    span,
+                    CrateLint::SimplePath(trait_ref.ref_id),
+                ) {
                     new_val = Some((module, trait_ref.clone()));
                 }
             }
@@ -2839,7 +2845,7 @@ impl<'a> Resolver<'a> {
                 } else {
                     let mod_path = &path[..path.len() - 1];
                     let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS),
-                                                             false, span, None) {
+                                                             false, span, CrateLint::No) {
                         PathResult::Module(module) => module.def(),
                         _ => None,
                     }.map_or(format!(""), |def| format!("{} ", def.kind_name()));
@@ -3169,7 +3175,7 @@ impl<'a> Resolver<'a> {
             ));
         }
 
-        let result = match self.resolve_path(&path, Some(ns), true, span, Some(id)) {
+        let result = match self.resolve_path(&path, Some(ns), true, span, CrateLint::SimplePath(id)) {
             PathResult::NonModule(path_res) => path_res,
             PathResult::Module(module) if !module.is_normal() => {
                 PathResolution::new(module.def().unwrap())
@@ -3206,7 +3212,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, None) {
+                match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span, CrateLint::No) {
                     PathResult::NonModule(path_res) => path_res.base_def(),
                     PathResult::Module(module) => module.def().unwrap(),
                     _ => return Some(result),
@@ -3221,14 +3227,14 @@ impl<'a> Resolver<'a> {
         Some(result)
     }
 
-    fn resolve_path(&mut self,
-                    path: &[Ident],
-                    opt_ns: Option<Namespace>, // `None` indicates a module path
-                    record_used: bool,
-                    path_span: Span,
-                    node_id: Option<NodeId>) // None indicates that we don't care about linting
-                                             // `::module` paths
-                    -> PathResult<'a> {
+    fn resolve_path(
+        &mut self,
+        path: &[Ident],
+        opt_ns: Option<Namespace>, // `None` indicates a module path
+        record_used: bool,
+        path_span: Span,
+        crate_lint: CrateLint,
+    ) -> PathResult<'a> {
         let mut module = None;
         let mut allow_super = true;
         let mut second_binding = None;
@@ -3347,7 +3353,7 @@ impl<'a> Resolver<'a> {
                         return PathResult::NonModule(err_path_resolution());
                     } else if opt_ns.is_some() && (is_last || maybe_assoc) {
                         self.lint_if_path_starts_with_module(
-                            node_id,
+                            crate_lint,
                             path,
                             path_span,
                             second_binding,
@@ -3392,19 +3398,22 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        self.lint_if_path_starts_with_module(node_id, path, path_span, second_binding);
+        self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding);
 
         PathResult::Module(module.unwrap_or(self.graph_root))
     }
 
-    fn lint_if_path_starts_with_module(&self,
-                                       id: Option<NodeId>,
-                                       path: &[Ident],
-                                       path_span: Span,
-                                       second_binding: Option<&NameBinding>) {
-        let id = match id {
-            Some(id) => id,
-            None => return,
+    fn lint_if_path_starts_with_module(
+        &self,
+        crate_lint: CrateLint,
+        path: &[Ident],
+        path_span: Span,
+        second_binding: Option<&NameBinding>,
+    ) {
+        let (diag_id, diag_span) = match crate_lint {
+            CrateLint::No => return,
+            CrateLint::SimplePath(id) => (id, path_span),
+            CrateLint::UsePath { root_id, root_span } => (root_id, root_span),
         };
 
         let first_name = match path.get(0) {
@@ -3440,7 +3449,7 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        self.lint_path_starts_with_module(id, path_span);
+        self.lint_path_starts_with_module(diag_id, diag_span);
     }
 
     fn lint_path_starts_with_module(&self, id: NodeId, span: Span) {
@@ -3676,7 +3685,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, None) {
+                                                                  false, span, CrateLint::No) {
                 add_module_candidates(module, &mut names);
             }
         }
@@ -4475,4 +4484,19 @@ pub enum MakeGlobMap {
     No,
 }
 
+enum CrateLint {
+    /// Do not issue the lint
+    No,
+
+    /// This lint applies to some random path like `impl ::foo::Bar`
+    /// or whatever. In this case, we can take the span of that path.
+    SimplePath(NodeId),
+
+    /// This lint comes from a `use` statement. In this case, what we
+    /// care about really is the *root* `use` statement; e.g., if we
+    /// have nested things like `use a::{b, c}`, we care about the
+    /// `use a` part.
+    UsePath { root_id: NodeId, root_span: Span },
+}
+
 __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 0fc963a1367..c5d04293d03 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use {AmbiguityError, Resolver, ResolutionError, resolve_error};
+use {AmbiguityError, CrateLint, Resolver, ResolutionError, resolve_error};
 use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult};
 use Namespace::{self, MacroNS};
 use build_reduced_graph::BuildReducedGraphVisitor;
@@ -441,7 +441,7 @@ impl<'a> Resolver<'a> {
                 return Err(Determinacy::Determined);
             }
 
-            let def = match self.resolve_path(&path, Some(MacroNS), false, span, None) {
+            let def = match self.resolve_path(&path, Some(MacroNS), false, span, CrateLint::No) {
                 PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => {
@@ -619,7 +619,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, None) {
+            match self.resolve_path(&path, Some(MacroNS), true, span, CrateLint::No) {
                 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 fd657cbf805..2661cd7bb67 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -10,7 +10,7 @@
 
 use self::ImportDirectiveSubclass::*;
 
-use {AmbiguityError, Module, PerNS};
+use {AmbiguityError, CrateLint, Module, PerNS};
 use Namespace::{self, TypeNS, MacroNS};
 use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
 use Resolver;
@@ -94,6 +94,10 @@ impl<'a> ImportDirective<'a> {
     pub fn is_glob(&self) -> bool {
         match self.subclass { ImportDirectiveSubclass::GlobImport { .. } => true, _ => false }
     }
+
+    crate fn crate_lint(&self) -> CrateLint {
+        CrateLint::UsePath { root_id: self.root_id, root_span: self.root_span }
+    }
 }
 
 #[derive(Clone, Default, Debug)]
@@ -599,7 +603,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             // while resolving its module path.
             directive.vis.set(ty::Visibility::Invisible);
             let result = self.resolve_path(&directive.module_path[..], None, false,
-                                           directive.span, Some(directive.id));
+                                           directive.span, directive.crate_lint());
             directive.vis.set(vis);
 
             match result {
@@ -733,7 +737,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
             }
         }
 
-        let module_result = self.resolve_path(&module_path, None, true, span, Some(directive.id));
+        let module_result = self.resolve_path(&module_path, None, true, span, directive.crate_lint());
         let module = match module_result {
             PathResult::Module(module) => module,
             PathResult::Failed(span, msg, false) => {
@@ -748,7 +752,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, None));
+                                                         span, CrateLint::No));
                 }
                 return if let Some(PathResult::Module(..)) = self_result {
                     Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..]))))