about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-06-12 15:23:28 +0000
committerbors <bors@rust-lang.org>2018-06-12 15:23:28 +0000
commitef8cb40c9c03fe60aac47c8736045231633dbdac (patch)
tree372aa750a7d6b5351c8824c762ac7b68b8640825 /src/test
parent3f3ba6c3cb1707eaf63640fc6681ae389253fe18 (diff)
parentd13bfd294c55a47bb33e5846ce184c80cdf547dd (diff)
downloadrust-ef8cb40c9c03fe60aac47c8736045231633dbdac.tar.gz
rust-ef8cb40c9c03fe60aac47c8736045231633dbdac.zip
Auto merge of #51519 - ExpHP:issue-51331-b, r=petrochenkov
Fix for $crate var normalization in proc macro for externally defined macros

Fixes #51331, a bug that has existed in at least *some* form for a year and a half.

The PR includes the addition of a `fold_qpath` method to `syntax::fold::Folder`.  Overriding this method is useful for folds that modify paths in a way that invalidates indices (insertion or removal of a component), as it provides the opportunity to update `qself.position` in `<A as B>::C` paths.  I added it because the bugfix is messy without it.

(unfortunately, grepping around the codebase, I did not see anything else that could use it.)
Diffstat (limited to 'src/test')
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs2
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/auxiliary/external-crate-var.rs51
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/crate-var.rs52
3 files changed, 101 insertions, 4 deletions
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
index f4404b737f9..a6c9817f247 100644
--- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
@@ -16,6 +16,8 @@ extern crate proc_macro;
 
 use proc_macro::TokenStream;
 
+// Outputs another copy of the struct.  Useful for testing the tokens
+// seen by the proc_macro.
 #[proc_macro_derive(Double)]
 pub fn derive(input: TokenStream) -> TokenStream {
     format!("mod foo {{ {} }}", input.to_string()).parse().unwrap()
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/external-crate-var.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/external-crate-var.rs
new file mode 100644
index 00000000000..030c53b3e6f
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/external-crate-var.rs
@@ -0,0 +1,51 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct ExternFoo;
+
+pub trait ExternTrait {
+    const CONST: u32;
+    type Assoc;
+}
+
+impl ExternTrait for ExternFoo {
+    const CONST: u32 = 0;
+    type Assoc = ExternFoo;
+}
+
+#[macro_export]
+macro_rules! external { () => {
+    mod bar {
+        #[derive(Double)]
+        struct Bar($crate::ExternFoo);
+    }
+
+    mod qself {
+        #[derive(Double)]
+        struct QSelf(<$crate::ExternFoo as $crate::ExternTrait>::Assoc);
+    }
+
+    mod qself_recurse {
+        #[derive(Double)]
+        struct QSelfRecurse(<
+            <$crate::ExternFoo as $crate::ExternTrait>::Assoc
+            as $crate::ExternTrait>::Assoc
+        );
+    }
+
+    mod qself_in_const {
+        #[derive(Double)]
+        #[repr(u32)]
+        enum QSelfInConst {
+            Variant = <$crate::ExternFoo as $crate::ExternTrait>::CONST,
+        }
+    }
+} }
+
diff --git a/src/test/run-pass-fulldeps/proc-macro/crate-var.rs b/src/test/run-pass-fulldeps/proc-macro/crate-var.rs
index b6acb0faab2..41c15195bc8 100644
--- a/src/test/run-pass-fulldeps/proc-macro/crate-var.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/crate-var.rs
@@ -9,19 +9,63 @@
 // except according to those terms.
 
 // aux-build:double.rs
+// aux-build:external-crate-var.rs
 // ignore-stage1
 
 #![allow(unused)]
 
 #[macro_use]
 extern crate double;
+#[macro_use]
+extern crate external_crate_var;
 
 struct Foo;
 
-macro_rules! m { () => {
-    #[derive(Double)]
-    struct Bar($crate::Foo);
+trait Trait {
+    const CONST: u32;
+    type Assoc;
+}
+
+impl Trait for Foo {
+    const CONST: u32 = 0;
+    type Assoc = Foo;
+}
+
+macro_rules! local { () => {
+    // derive_Double outputs secondary copies of each definition
+    // to test what the proc_macro sees.
+    mod bar {
+        #[derive(Double)]
+        struct Bar($crate::Foo);
+    }
+
+    mod qself {
+        #[derive(Double)]
+        struct QSelf(<::Foo as $crate::Trait>::Assoc);
+    }
+
+    mod qself_recurse {
+        #[derive(Double)]
+        struct QSelfRecurse(<<$crate::Foo as $crate::Trait>::Assoc as $crate::Trait>::Assoc);
+    }
+
+    mod qself_in_const {
+        #[derive(Double)]
+        #[repr(u32)]
+        enum QSelfInConst {
+            Variant = <::Foo as $crate::Trait>::CONST,
+        }
+    }
 } }
-m!();
+
+mod local {
+    local!();
+}
+
+// and now repeat the above tests, using a macro defined in another crate
+
+mod external {
+    external!{}
+}
 
 fn main() {}