about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKevin Jiang <kwj2104@columbia.edu>2021-03-18 00:15:39 -0400
committerK <kwj2104@columbia.edu>2021-04-01 22:55:47 -0400
commite433f5585296ba8892893e4c78f51d2d42ac7ea4 (patch)
treec293ef61f543a20b1b42e8619daadba6fdfed449
parent926ec1cb8b81ac47ba2e5b8a6780e95d39241afa (diff)
downloadrust-e433f5585296ba8892893e4c78f51d2d42ac7ea4.tar.gz
rust-e433f5585296ba8892893e4c78f51d2d42ac7ea4.zip
Fixed diagnostic and added test for issue 81508
-rw-r--r--compiler/rustc_resolve/src/late.rs2
-rw-r--r--compiler/rustc_resolve/src/lib.rs69
-rw-r--r--src/test/ui/resolve/issue-81508.rs22
-rw-r--r--src/test/ui/resolve/issue-81508.stderr21
4 files changed, 100 insertions, 14 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 1377bb781d0..987f1e6cc74 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1031,7 +1031,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             }
 
             ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
-                debug!("resolve_item ItemKind::Const");
                 self.with_item_rib(HasGenericParams::No, |this| {
                     this.visit_ty(ty);
                     if let Some(expr) = expr {
@@ -1597,6 +1596,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                         .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
                         .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
                     self.r.record_partial_res(pat.id, PartialRes::new(res));
+                    self.r.record_local_span(pat.id, pat.span);
                 }
                 PatKind::TupleStruct(ref path, ref sub_patterns) => {
                     self.smart_resolve_path(
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index fe5078f26bd..3a8cb0fd09a 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -884,6 +884,10 @@ pub struct Resolver<'a> {
     /// "self-confirming" import resolutions during import validation.
     unusable_binding: Option<&'a NameBinding<'a>>,
 
+    // Spans for local variables found during resolution
+    // Used for suggestions during error reporting
+    local_span_map: NodeMap<Span>,
+
     /// Resolutions for nodes that have a single resolution.
     partial_res_map: NodeMap<PartialRes>,
     /// Resolutions for import nodes, which have multiple resolutions in different namespaces.
@@ -1262,6 +1266,7 @@ impl<'a> Resolver<'a> {
             last_import_segment: false,
             unusable_binding: None,
 
+            local_span_map: Default::default(),
             partial_res_map: Default::default(),
             import_res_map: Default::default(),
             label_res_map: Default::default(),
@@ -1879,7 +1884,6 @@ impl<'a> Resolver<'a> {
                     ribs,
                 )));
             }
-
             module = match ribs[i].kind {
                 ModuleRibKind(module) => module,
                 MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
@@ -1890,7 +1894,6 @@ impl<'a> Resolver<'a> {
                 }
                 _ => continue,
             };
-
             match module.kind {
                 ModuleKind::Block(..) => {} // We can see through blocks
                 _ => break,
@@ -1909,17 +1912,19 @@ impl<'a> Resolver<'a> {
                 return Some(LexicalScopeBinding::Item(binding));
             }
         }
+        let returned_item = self
+            .early_resolve_ident_in_lexical_scope(
+                orig_ident,
+                ScopeSet::Late(ns, module, record_used_id),
+                parent_scope,
+                record_used,
+                record_used,
+                path_span,
+            )
+            .ok()
+            .map(LexicalScopeBinding::Item);
 
-        self.early_resolve_ident_in_lexical_scope(
-            orig_ident,
-            ScopeSet::Late(ns, module, record_used_id),
-            parent_scope,
-            record_used,
-            record_used,
-            path_span,
-        )
-        .ok()
-        .map(LexicalScopeBinding::Item)
+        returned_item
     }
 
     fn hygienic_lexical_parent(
@@ -2386,7 +2391,40 @@ impl<'a> Resolver<'a> {
                             .next()
                             .map_or(false, |c| c.is_ascii_uppercase())
                         {
-                            (format!("use of undeclared type `{}`", ident), None)
+                            // Add check case for similarly named item in alternative namespace
+                            let mut suggestion = None;
+
+                            if ribs.is_some() {
+                                if let Some(res) = self.resolve_ident_in_lexical_scope(
+                                    ident,
+                                    ValueNS,
+                                    parent_scope,
+                                    None,
+                                    path_span,
+                                    &ribs.unwrap()[ValueNS],
+                                ) {
+                                    let mut match_span: Option<Span> = None;
+                                    match res {
+                                        LexicalScopeBinding::Res(Res::Local(id)) => {
+                                            match_span =
+                                                Some(*self.local_span_map.get(&id).unwrap());
+                                        }
+                                        LexicalScopeBinding::Item(name_binding) => {
+                                            match_span = Some(name_binding.span);
+                                        }
+                                        _ => (),
+                                    };
+                                    if let Some(span) = match_span {
+                                        suggestion = Some((
+                                            vec![(span, String::from(""))],
+                                            format!("{} is defined here, but is not a type", ident),
+                                            Applicability::MaybeIncorrect,
+                                        ));
+                                    }
+                                }
+                            }
+
+                            (format!("use of undeclared type `{}`", ident), suggestion)
                         } else {
                             (format!("use of undeclared crate or module `{}`", ident), None)
                         }
@@ -2797,6 +2835,11 @@ impl<'a> Resolver<'a> {
         }
     }
 
+    fn record_local_span(&mut self, node: NodeId, span: Span) {
+        debug!("(recording local) recording {:?} for {:?}", node, span);
+        self.local_span_map.insert(node, span);
+    }
+
     fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
         vis.is_accessible_from(module.nearest_parent_mod, self)
     }
diff --git a/src/test/ui/resolve/issue-81508.rs b/src/test/ui/resolve/issue-81508.rs
new file mode 100644
index 00000000000..23605cd2fd9
--- /dev/null
+++ b/src/test/ui/resolve/issue-81508.rs
@@ -0,0 +1,22 @@
+// Confusing diagnostic when using variable as a type:
+//
+// Previous warnings indicate Foo is not used, when in fact it is
+// used improperly as a variable or constant. New warning points
+// out user may be trying to use variable as a type. Test demonstrates
+// cases for both local variable and const.
+
+fn main() {
+    let Baz: &str = "";
+
+    println!("{}", Baz::Bar); //~ ERROR: failed to resolve: use of undeclared type `Baz`
+}
+
+#[allow(non_upper_case_globals)]
+pub const Foo: &str = "";
+
+mod submod {
+    use super::Foo;
+    fn function() {
+        println!("{}", Foo::Bar); //~ ERROR: failed to resolve: use of undeclared type `Foo`
+    }
+}
diff --git a/src/test/ui/resolve/issue-81508.stderr b/src/test/ui/resolve/issue-81508.stderr
new file mode 100644
index 00000000000..b0d5e1a2692
--- /dev/null
+++ b/src/test/ui/resolve/issue-81508.stderr
@@ -0,0 +1,21 @@
+error[E0433]: failed to resolve: use of undeclared type `Baz`
+  --> $DIR/issue-81508.rs:11:20
+   |
+LL |     let Baz: &str = "";
+   |         --- help: Baz is defined here, but is not a type
+LL | 
+LL |     println!("{}", Baz::Bar);
+   |                    ^^^ use of undeclared type `Baz`
+
+error[E0433]: failed to resolve: use of undeclared type `Foo`
+  --> $DIR/issue-81508.rs:20:24
+   |
+LL |     use super::Foo;
+   |         ---------- help: Foo is defined here, but is not a type
+LL |     fn function() {
+LL |         println!("{}", Foo::Bar);
+   |                        ^^^ use of undeclared type `Foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.