about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/lib.rs36
-rw-r--r--src/test/ui/rust-2018/future-proofing-locals.rs49
-rw-r--r--src/test/ui/rust-2018/future-proofing-locals.stderr50
3 files changed, 134 insertions, 1 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index a33bd7aa732..84ce0892b6b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2364,6 +2364,36 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
         });
     }
 
+    fn future_proof_import(&mut self, use_tree: &ast::UseTree) {
+        if !self.session.rust_2018() {
+            return;
+        }
+
+        let segments = &use_tree.prefix.segments;
+        if !segments.is_empty() {
+            let ident = segments[0].ident;
+            if ident.is_path_segment_keyword() {
+                return;
+            }
+
+            let nss = match use_tree.kind {
+                ast::UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..],
+                _ => &[TypeNS],
+            };
+            for &ns in nss {
+                if let Some(LexicalScopeBinding::Def(..)) =
+                        self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) {
+                    let what = if ns == TypeNS { "type parameters" } else { "local variables" };
+                    self.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
+                }
+            }
+        } else if let ast::UseTreeKind::Nested(use_trees) = &use_tree.kind {
+            for (use_tree, _) in use_trees {
+                self.future_proof_import(use_tree);
+            }
+        }
+    }
+
     fn resolve_item(&mut self, item: &Item) {
         let name = item.ident.name;
         debug!("(resolving item) resolving {}", name);
@@ -2457,7 +2487,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
                 });
             }
 
-            ItemKind::Use(..) | ItemKind::ExternCrate(..) |
+            ItemKind::Use(ref use_tree) => {
+                self.future_proof_import(use_tree);
+            }
+
+            ItemKind::ExternCrate(..) |
             ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) => {
                 // do nothing, these are just around to be encoded
             }
diff --git a/src/test/ui/rust-2018/future-proofing-locals.rs b/src/test/ui/rust-2018/future-proofing-locals.rs
new file mode 100644
index 00000000000..d2e6dbbb954
--- /dev/null
+++ b/src/test/ui/rust-2018/future-proofing-locals.rs
@@ -0,0 +1,49 @@
+// edition:2018
+
+#![feature(uniform_paths, underscore_imports)]
+
+mod T {
+    pub struct U;
+}
+mod x {
+    pub struct y;
+}
+
+fn type_param<T>() {
+    use T as _; //~ ERROR imports cannot refer to type parameters
+    use T::U; //~ ERROR imports cannot refer to type parameters
+    use T::*; //~ ERROR imports cannot refer to type parameters
+}
+
+fn self_import<T>() {
+    use T; // FIXME Should be an error, but future-proofing fails due to `T` being "self-shadowed"
+}
+
+fn let_binding() {
+    let x = 10;
+
+    use x as _; //~ ERROR imports cannot refer to local variables
+    use x::y; // OK
+    use x::*; // OK
+}
+
+fn param_binding(x: u8) {
+    use x; //~ ERROR imports cannot refer to local variables
+}
+
+fn match_binding() {
+    match 0 {
+        x => {
+            use x; //~ ERROR imports cannot refer to local variables
+        }
+    }
+}
+
+fn nested<T>() {
+    let x = 10;
+
+    use {T as _, x}; //~ ERROR imports cannot refer to type parameters
+                     //~| ERROR imports cannot refer to local variables
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/future-proofing-locals.stderr b/src/test/ui/rust-2018/future-proofing-locals.stderr
new file mode 100644
index 00000000000..68354b332a9
--- /dev/null
+++ b/src/test/ui/rust-2018/future-proofing-locals.stderr
@@ -0,0 +1,50 @@
+error: imports cannot refer to type parameters
+  --> $DIR/future-proofing-locals.rs:13:9
+   |
+LL |     use T as _; //~ ERROR imports cannot refer to type parameters
+   |         ^
+
+error: imports cannot refer to type parameters
+  --> $DIR/future-proofing-locals.rs:14:9
+   |
+LL |     use T::U; //~ ERROR imports cannot refer to type parameters
+   |         ^
+
+error: imports cannot refer to type parameters
+  --> $DIR/future-proofing-locals.rs:15:9
+   |
+LL |     use T::*; //~ ERROR imports cannot refer to type parameters
+   |         ^
+
+error: imports cannot refer to local variables
+  --> $DIR/future-proofing-locals.rs:25:9
+   |
+LL |     use x as _; //~ ERROR imports cannot refer to local variables
+   |         ^
+
+error: imports cannot refer to local variables
+  --> $DIR/future-proofing-locals.rs:31:9
+   |
+LL |     use x; //~ ERROR imports cannot refer to local variables
+   |         ^
+
+error: imports cannot refer to local variables
+  --> $DIR/future-proofing-locals.rs:37:17
+   |
+LL |             use x; //~ ERROR imports cannot refer to local variables
+   |                 ^
+
+error: imports cannot refer to type parameters
+  --> $DIR/future-proofing-locals.rs:45:10
+   |
+LL |     use {T as _, x}; //~ ERROR imports cannot refer to type parameters
+   |          ^
+
+error: imports cannot refer to local variables
+  --> $DIR/future-proofing-locals.rs:45:18
+   |
+LL |     use {T as _, x}; //~ ERROR imports cannot refer to type parameters
+   |                  ^
+
+error: aborting due to 8 previous errors
+