]> git.lizzy.rs Git - rust.git/commitdiff
resolve: Future-proof against imports referring to local variables and generic parameters
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sat, 17 Nov 2018 17:00:00 +0000 (20:00 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sun, 18 Nov 2018 10:58:39 +0000 (13:58 +0300)
src/librustc_resolve/lib.rs
src/test/ui/rust-2018/future-proofing-locals.rs [new file with mode: 0644]
src/test/ui/rust-2018/future-proofing-locals.stderr [new file with mode: 0644]

index a33bd7aa732d74be5960e653706953d5497fca36..84ce0892b6b4f79aa710800ed6af75cf6e746bc1 100644 (file)
@@ -2364,6 +2364,36 @@ fn resolve_adt(&mut self, item: &Item, generics: &Generics) {
         });
     }
 
+    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 @@ fn resolve_item(&mut self, item: &Item) {
                 });
             }
 
-            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 (file)
index 0000000..d2e6dbb
--- /dev/null
@@ -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 (file)
index 0000000..68354b3
--- /dev/null
@@ -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
+