about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_resolve/lib.rs26
-rw-r--r--src/test/ui/hygiene/generic_params.rs104
-rw-r--r--src/test/ui/hygiene/generic_params.stderr6
-rw-r--r--src/test/ui/hygiene/ty_params.rs14
4 files changed, 128 insertions, 22 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index a5e498fa756..8884d1cd27f 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -872,8 +872,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
         debug!("(resolving function) entering function");
         let rib_kind = match function_kind {
             FnKind::ItemFn(..) => FnItemRibKind,
-            FnKind::Method(..) => AssocItemRibKind,
-            FnKind::Closure(_) => NormalRibKind,
+            FnKind::Method(..) | FnKind::Closure(_) => NormalRibKind,
         };
 
         // Create a value rib for the function.
@@ -2310,21 +2309,32 @@ impl<'a> Resolver<'a> {
         if ident.name == kw::Invalid {
             return Some(LexicalScopeBinding::Res(Res::Err));
         }
-        ident.span = if ident.name == kw::SelfUpper {
+        let (general_span, modern_span) = if ident.name == kw::SelfUpper {
             // FIXME(jseyfried) improve `Self` hygiene
-            ident.span.with_ctxt(SyntaxContext::empty())
+            let empty_span = ident.span.with_ctxt(SyntaxContext::empty());
+            (empty_span, empty_span)
         } else if ns == TypeNS {
-            ident.span.modern()
+            let modern_span = ident.span.modern();
+            (modern_span, modern_span)
         } else {
-            ident.span.modern_and_legacy()
+            (ident.span.modern_and_legacy(), ident.span.modern())
         };
+        ident.span = general_span;
+        let modern_ident = Ident { span: modern_span, ..ident };
 
         // Walk backwards up the ribs in scope.
         let record_used = record_used_id.is_some();
         let mut module = self.graph_root;
         for i in (0 .. self.ribs[ns].len()).rev() {
             debug!("walk rib\n{:?}", self.ribs[ns][i].bindings);
-            if let Some(res) = self.ribs[ns][i].bindings.get(&ident).cloned() {
+            // Use the rib kind to determine whether we are resolving parameters
+            // (modern hygiene) or local variables (legacy hygiene).
+            let rib_ident = if let AssocItemRibKind | ItemRibKind = self.ribs[ns][i].kind {
+                modern_ident
+            } else {
+                ident
+            };
+            if let Some(res) = self.ribs[ns][i].bindings.get(&rib_ident).cloned() {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Res(
                     self.validate_res_from_ribs(ns, i, res, record_used, path_span),
@@ -2360,7 +2370,7 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        ident.span = ident.span.modern();
+        ident = modern_ident;
         let mut poisoned = None;
         loop {
             let opt_module = if let Some(node_id) = record_used_id {
diff --git a/src/test/ui/hygiene/generic_params.rs b/src/test/ui/hygiene/generic_params.rs
new file mode 100644
index 00000000000..9dc5adfce47
--- /dev/null
+++ b/src/test/ui/hygiene/generic_params.rs
@@ -0,0 +1,104 @@
+// Ensure that generic parameters always have modern hygiene.
+
+// check-pass
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro, rustc_attrs, const_generics)]
+
+mod type_params {
+    macro m($T:ident) {
+        fn f<$T: Clone, T: PartialEq>(t1: $T, t2: T) -> ($T, bool) {
+            (t1.clone(), t2 == t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "semitransparent"]
+    macro n($T:ident) {
+        fn g<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+        fn h<T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+    }
+
+    #[rustc_macro_transparency = "transparent"]
+    macro p($T:ident) {
+        fn j<$T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+        fn k<T: Clone>(t1: $T, t2: T) -> (T, $T) {
+            (t1.clone(), t2.clone())
+        }
+    }
+
+    m!(T);
+    n!(T);
+    p!(T);
+}
+
+mod lifetime_params {
+    macro m($a:lifetime) {
+        fn f<'b, 'c, $a: 'b, 'a: 'c>(t1: &$a(), t2: &'a ()) -> (&'b (), &'c ()) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "semitransparent"]
+    macro n($a:lifetime) {
+        fn g<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+        fn h<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "transparent"]
+    macro p($a:lifetime) {
+        fn j<$a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+        fn k<'a>(t1: &$a(), t2: &'a ()) -> (&'a (), &$a ()) {
+            (t1, t2)
+        }
+    }
+
+    m!('a);
+    n!('a);
+    p!('a);
+}
+
+mod const_params {
+    macro m($C:ident) {
+        fn f<const $C: usize, const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); $C], [(); C]) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "semitransparent"]
+    macro n($C:ident) {
+        fn g<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+        fn h<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+    }
+
+    #[rustc_macro_transparency = "transparent"]
+    macro p($C:ident) {
+        fn j<const $C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+        fn k<const C: usize>(t1: [(); $C], t2: [(); C]) -> ([(); C], [(); $C]) {
+            (t1, t2)
+        }
+    }
+
+    m!(C);
+    n!(C);
+    p!(C);
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/generic_params.stderr b/src/test/ui/hygiene/generic_params.stderr
new file mode 100644
index 00000000000..ecd228a5db5
--- /dev/null
+++ b/src/test/ui/hygiene/generic_params.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/generic_params.rs:6:37
+   |
+LL | #![feature(decl_macro, rustc_attrs, const_generics)]
+   |                                     ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/hygiene/ty_params.rs b/src/test/ui/hygiene/ty_params.rs
deleted file mode 100644
index b296bfe5988..00000000000
--- a/src/test/ui/hygiene/ty_params.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// check-pass
-// ignore-pretty pretty-printing is unhygienic
-
-#![feature(decl_macro)]
-
-macro m($T:ident) {
-    fn f<T, $T>(t: T, t2: $T) -> (T, $T) {
-        (t, t2)
-    }
-}
-
-m!(T);
-
-fn main() {}