about summary refs log tree commit diff
path: root/tests/ui/proc-macro/auxiliary
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/ui/proc-macro/auxiliary
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/ui/proc-macro/auxiliary')
-rw-r--r--tests/ui/proc-macro/auxiliary/add-impl.rs21
-rw-r--r--tests/ui/proc-macro/auxiliary/amputate-span.rs14
-rw-r--r--tests/ui/proc-macro/auxiliary/api/cmp.rs21
-rw-r--r--tests/ui/proc-macro/auxiliary/api/mod.rs24
-rw-r--r--tests/ui/proc-macro/auxiliary/api/parse.rs55
-rw-r--r--tests/ui/proc-macro/auxiliary/append-impl.rs16
-rw-r--r--tests/ui/proc-macro/auxiliary/assert-span-pos.rs37
-rw-r--r--tests/ui/proc-macro/auxiliary/attr-args.rs28
-rw-r--r--tests/ui/proc-macro/auxiliary/attr-cfg.rs21
-rw-r--r--tests/ui/proc-macro/auxiliary/attr-on-trait.rs15
-rw-r--r--tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs51
-rw-r--r--tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs49
-rw-r--r--tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs35
-rw-r--r--tests/ui/proc-macro/auxiliary/attributes-included.rs150
-rw-r--r--tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs23
-rw-r--r--tests/ui/proc-macro/auxiliary/bang-macro.rs17
-rw-r--r--tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/builtin-attrs.rs27
-rw-r--r--tests/ui/proc-macro/auxiliary/call-deprecated.rs19
-rw-r--r--tests/ui/proc-macro/auxiliary/call-site.rs27
-rw-r--r--tests/ui/proc-macro/auxiliary/cond_plugin.rs38
-rw-r--r--tests/ui/proc-macro/auxiliary/count_compound_ops.rs32
-rw-r--r--tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs18
-rw-r--r--tests/ui/proc-macro/auxiliary/custom-quote.rs32
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-a.rs15
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-atob.rs15
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs14
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-b-rpass.rs17
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-b.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-bad.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-clona.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-ctod.rs15
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-foo.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs2
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs12
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs15
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-nothing.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-same-struct.rs21
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-two-attrs.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-union.rs18
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-unstable-2.rs17
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-unstable.rs14
-rw-r--r--tests/ui/proc-macro/auxiliary/dollar-crate-external.rs22
-rw-r--r--tests/ui/proc-macro/auxiliary/double.rs16
-rw-r--r--tests/ui/proc-macro/auxiliary/duplicate.rs32
-rw-r--r--tests/ui/proc-macro/auxiliary/edition-imports-2015.rs20
-rw-r--r--tests/ui/proc-macro/auxiliary/empty-crate.rs5
-rw-r--r--tests/ui/proc-macro/auxiliary/expand-expr.rs166
-rw-r--r--tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs22
-rw-r--r--tests/ui/proc-macro/auxiliary/external-crate-var.rs40
-rw-r--r--tests/ui/proc-macro/auxiliary/first-second.rs20
-rw-r--r--tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs25
-rw-r--r--tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs23
-rw-r--r--tests/ui/proc-macro/auxiliary/gen-macro-rules.rs12
-rw-r--r--tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs16
-rw-r--r--tests/ui/proc-macro/auxiliary/generate-mod.rs58
-rw-r--r--tests/ui/proc-macro/auxiliary/hygiene_example.rs7
-rw-r--r--tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs27
-rw-r--r--tests/ui/proc-macro/auxiliary/included-file.txt1
-rw-r--r--tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs28
-rw-r--r--tests/ui/proc-macro/auxiliary/is-available.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-104884.rs23
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-38586.rs11
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-39889.rs17
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-42708.rs18
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-50061.rs12
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-50493.rs21
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-59191.rs16
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-66286.rs14
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-75801.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-79242.rs16
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-79825.rs14
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-83510.rs19
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-91800-macro.rs26
-rw-r--r--tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs26
-rw-r--r--tests/ui/proc-macro/auxiliary/lifetimes.rs20
-rw-r--r--tests/ui/proc-macro/auxiliary/macro-only-syntax.rs89
-rw-r--r--tests/ui/proc-macro/auxiliary/make-macro.rs18
-rw-r--r--tests/ui/proc-macro/auxiliary/meta-delim.rs12
-rw-r--r--tests/ui/proc-macro/auxiliary/meta-macro.rs15
-rw-r--r--tests/ui/proc-macro/auxiliary/mixed-site-span.rs40
-rw-r--r--tests/ui/proc-macro/auxiliary/modify-ast.rs47
-rw-r--r--tests/ui/proc-macro/auxiliary/multiple-derives.rs22
-rw-r--r--tests/ui/proc-macro/auxiliary/multispan.rs37
-rw-r--r--tests/ui/proc-macro/auxiliary/negative-token.rs18
-rw-r--r--tests/ui/proc-macro/auxiliary/nested-macro-rules.rs16
-rw-r--r--tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs25
-rw-r--r--tests/ui/proc-macro/auxiliary/not-joint.rs30
-rw-r--r--tests/ui/proc-macro/auxiliary/parent-source-spans.rs43
-rw-r--r--tests/ui/proc-macro/auxiliary/proc-macro-panic.rs13
-rw-r--r--tests/ui/proc-macro/auxiliary/raw-ident.rs35
-rw-r--r--tests/ui/proc-macro/auxiliary/re-export.rs19
-rw-r--r--tests/ui/proc-macro/auxiliary/recollect.rs12
-rw-r--r--tests/ui/proc-macro/auxiliary/resolved-located-at.rs31
-rw-r--r--tests/ui/proc-macro/auxiliary/span-api-tests.rs45
-rw-r--r--tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs49
-rw-r--r--tests/ui/proc-macro/auxiliary/span-test-macros.rs9
-rw-r--r--tests/ui/proc-macro/auxiliary/subspan.rs38
-rw-r--r--tests/ui/proc-macro/auxiliary/test-macros.rs180
-rw-r--r--tests/ui/proc-macro/auxiliary/three-equals.rs49
-rw-r--r--tests/ui/proc-macro/auxiliary/weird-hygiene.rs48
101 files changed, 2795 insertions, 0 deletions
diff --git a/tests/ui/proc-macro/auxiliary/add-impl.rs b/tests/ui/proc-macro/auxiliary/add-impl.rs
new file mode 100644
index 00000000000..741e64875b6
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/add-impl.rs
@@ -0,0 +1,21 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(AddImpl)]
+// #[cfg(proc_macro)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    "impl B {
+            fn foo(&self) {}
+        }
+
+        fn foo() {}
+
+        mod bar { pub fn foo() {} }
+    ".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/amputate-span.rs b/tests/ui/proc-macro/auxiliary/amputate-span.rs
new file mode 100644
index 00000000000..1a82119ae95
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/amputate-span.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn drop_first_token(attr: TokenStream, input: TokenStream) -> TokenStream {
+    assert!(attr.is_empty());
+    input.into_iter().skip(1).collect()
+}
diff --git a/tests/ui/proc-macro/auxiliary/api/cmp.rs b/tests/ui/proc-macro/auxiliary/api/cmp.rs
new file mode 100644
index 00000000000..5784a6e5d94
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/api/cmp.rs
@@ -0,0 +1,21 @@
+use proc_macro::{LineColumn, Punct, Spacing};
+
+pub fn test() {
+    test_line_column_ord();
+    test_punct_eq();
+}
+
+fn test_line_column_ord() {
+    let line0_column0 = LineColumn { line: 0, column: 0 };
+    let line0_column1 = LineColumn { line: 0, column: 1 };
+    let line1_column0 = LineColumn { line: 1, column: 0 };
+    assert!(line0_column0 < line0_column1);
+    assert!(line0_column1 < line1_column0);
+}
+
+fn test_punct_eq() {
+    let colon_alone = Punct::new(':', Spacing::Alone);
+    assert_eq!(colon_alone, ':');
+    let colon_joint = Punct::new(':', Spacing::Joint);
+    assert_eq!(colon_joint, ':');
+}
diff --git a/tests/ui/proc-macro/auxiliary/api/mod.rs b/tests/ui/proc-macro/auxiliary/api/mod.rs
new file mode 100644
index 00000000000..739c25132e7
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/api/mod.rs
@@ -0,0 +1,24 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![crate_name = "proc_macro_api_tests"]
+#![feature(proc_macro_span)]
+#![deny(dead_code)] // catch if a test function is never called
+
+extern crate proc_macro;
+
+mod cmp;
+mod parse;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn run(input: TokenStream) -> TokenStream {
+    assert!(input.is_empty());
+
+    cmp::test();
+    parse::test();
+
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/api/parse.rs b/tests/ui/proc-macro/auxiliary/api/parse.rs
new file mode 100644
index 00000000000..27391f83111
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/api/parse.rs
@@ -0,0 +1,55 @@
+// ignore-tidy-linelength
+
+use proc_macro::Literal;
+
+pub fn test() {
+    test_display_literal();
+    test_parse_literal();
+}
+
+fn test_display_literal() {
+    assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10");
+    assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize");
+    assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0");
+    assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32");
+    assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0");
+    assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64");
+    assert_eq!(
+        Literal::f64_unsuffixed(1e100).to_string(),
+        "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
+    );
+
+    assert_eq!(
+        Literal::string("a \t ❤ ' \" \u{1}").to_string(),
+        "\"a \\t ❤ ' \\\" \\u{1}\"",
+    );
+    assert_eq!(Literal::character('a').to_string(), "'a'");
+    assert_eq!(Literal::character('\t').to_string(), "'\\t'");
+    assert_eq!(Literal::character('❤').to_string(), "'❤'");
+    assert_eq!(Literal::character('\'').to_string(), "'\\''");
+    assert_eq!(Literal::character('"').to_string(), "'\"'");
+    assert_eq!(Literal::character('\u{1}').to_string(), "'\\u{1}'");
+}
+
+fn test_parse_literal() {
+    assert_eq!("1".parse::<Literal>().unwrap().to_string(), "1");
+    assert_eq!("1.0".parse::<Literal>().unwrap().to_string(), "1.0");
+    assert_eq!("'a'".parse::<Literal>().unwrap().to_string(), "'a'");
+    assert_eq!("\"\n\"".parse::<Literal>().unwrap().to_string(), "\"\n\"");
+    assert_eq!("b\"\"".parse::<Literal>().unwrap().to_string(), "b\"\"");
+    assert_eq!("r##\"\"##".parse::<Literal>().unwrap().to_string(), "r##\"\"##");
+    assert_eq!("10ulong".parse::<Literal>().unwrap().to_string(), "10ulong");
+    assert_eq!("-10ulong".parse::<Literal>().unwrap().to_string(), "-10ulong");
+
+    assert!("true".parse::<Literal>().is_err());
+    assert!(".8".parse::<Literal>().is_err());
+    assert!("0 1".parse::<Literal>().is_err());
+    assert!("'a".parse::<Literal>().is_err());
+    assert!(" 0".parse::<Literal>().is_err());
+    assert!("0 ".parse::<Literal>().is_err());
+    assert!("/* comment */0".parse::<Literal>().is_err());
+    assert!("0/* comment */".parse::<Literal>().is_err());
+    assert!("0// comment".parse::<Literal>().is_err());
+    assert!("- 10".parse::<Literal>().is_err());
+    assert!("-'x'".parse::<Literal>().is_err());
+}
diff --git a/tests/ui/proc-macro/auxiliary/append-impl.rs b/tests/ui/proc-macro/auxiliary/append-impl.rs
new file mode 100644
index 00000000000..b032b133759
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/append-impl.rs
@@ -0,0 +1,16 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Append)]
+pub fn derive_a(input: TokenStream) -> TokenStream {
+    "impl Append for A {
+         fn foo(&self) {}
+     }
+    ".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/assert-span-pos.rs b/tests/ui/proc-macro/auxiliary/assert-span-pos.rs
new file mode 100644
index 00000000000..455c5c7c380
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/assert-span-pos.rs
@@ -0,0 +1,37 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_diagnostic, proc_macro_span)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span};
+
+fn lit_span(tt: TokenTree) -> (Span, String) {
+    match tt {
+        TokenTree::Literal(..) |
+        TokenTree::Group(..) => (tt.span(), tt.to_string().trim().into()),
+        _ => panic!("expected a literal in token tree, got: {:?}", tt)
+    }
+}
+
+#[proc_macro]
+pub fn assert_span_pos(input: TokenStream) -> TokenStream {
+    let mut tokens = input.into_iter();
+    let (sp1, str1) = lit_span(tokens.next().expect("first argument"));
+    let _ = tokens.next();
+    let (_sp2, str2) = lit_span(tokens.next().expect("second argument"));
+
+    let line: usize = str1.parse().unwrap();
+    let col: usize = str2.parse().unwrap();
+
+    let sp1s = sp1.start();
+    if (line, col) != (sp1s.line, sp1s.column) {
+        let msg = format!("line/column mismatch: ({}, {}) != ({}, {})", line, col,
+            sp1s.line, sp1s.column);
+        sp1.error(msg).emit();
+    }
+
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/attr-args.rs b/tests/ui/proc-macro/auxiliary/attr-args.rs
new file mode 100644
index 00000000000..5f76a4484e1
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/attr-args.rs
@@ -0,0 +1,28 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream {
+    let args = args.to_string();
+
+    assert_eq!(args, r#"text = "Hello, world!""#);
+
+    let input = input.to_string();
+
+    assert_eq!(input, "fn foo() {}");
+
+    r#"
+        fn foo() -> &'static str { "Hello, world!" }
+    "#.parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn identity(attr_args: TokenStream, _: TokenStream) -> TokenStream {
+    attr_args
+}
diff --git a/tests/ui/proc-macro/auxiliary/attr-cfg.rs b/tests/ui/proc-macro/auxiliary/attr-cfg.rs
new file mode 100644
index 00000000000..2f0054cc14a
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/attr-cfg.rs
@@ -0,0 +1,21 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn attr_cfg(args: TokenStream, input: TokenStream) -> TokenStream {
+    let input_str = input.to_string();
+
+    assert_eq!(input_str, "fn outer() -> u8
+{
+    #[cfg(foo)] fn inner() -> u8 { 1 } #[cfg(bar)] fn inner() -> u8 { 2 }
+    inner()
+}");
+
+    input
+}
diff --git a/tests/ui/proc-macro/auxiliary/attr-on-trait.rs b/tests/ui/proc-macro/auxiliary/attr-on-trait.rs
new file mode 100644
index 00000000000..3787b8eeccc
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/attr-on-trait.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn foo(attr: TokenStream, item: TokenStream) -> TokenStream {
+    drop(attr);
+    assert_eq!(item.to_string(), "fn foo() {}");
+    "fn foo(&self);".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs
new file mode 100644
index 00000000000..5b386b46bb7
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs
@@ -0,0 +1,51 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "println! (\"{}\", string) ;");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "print_str(\"string\")");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "println! (\"{}\", string)");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert!(!item.to_string().is_empty());
+    "".parse().unwrap()
+
+}
+
+#[proc_macro_attribute]
+pub fn noop(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert!(!item.to_string().is_empty());
+    item
+}
diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs
new file mode 100644
index 00000000000..4d6dc06b4a4
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs
@@ -0,0 +1,49 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn expect_my_macro_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "my_macro! (\"{}\", string) ;");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "print_str(\"string\")");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn expect_my_macro_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert_eq!(item.to_string(), "my_macro! (\"{}\", string)");
+    item
+}
+
+#[proc_macro_attribute]
+pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    format!("{}, {}", item, item).parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream {
+    assert!(attr.to_string().is_empty());
+    assert!(!item.to_string().is_empty());
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs b/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs
new file mode 100644
index 00000000000..4d3279584c4
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/attribute-spans-preserved.rs
@@ -0,0 +1,35 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn foo(attr: TokenStream, f: TokenStream) -> TokenStream {
+    let mut tokens = f.into_iter();
+    assert_eq!(tokens.next().unwrap().to_string(), "#");
+    let next_attr = match tokens.next().unwrap() {
+        TokenTree::Group(g) => g,
+        _ => panic!(),
+    };
+
+    let fn_tok = tokens.next().unwrap();
+    let ident_tok = tokens.next().unwrap();
+    let args_tok = tokens.next().unwrap();
+    let body = tokens.next().unwrap();
+
+    let new_body = attr.into_iter()
+        .chain(next_attr.stream().into_iter().skip(1));
+
+    let tokens = vec![
+        fn_tok,
+        ident_tok,
+        args_tok,
+        Group::new(Delimiter::Brace, new_body.collect()).into(),
+    ].into_iter().collect::<TokenStream>();
+    println!("{}", tokens);
+    return tokens
+}
diff --git a/tests/ui/proc-macro/auxiliary/attributes-included.rs b/tests/ui/proc-macro/auxiliary/attributes-included.rs
new file mode 100644
index 00000000000..a5eb40b28dc
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/attributes-included.rs
@@ -0,0 +1,150 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Delimiter, Literal, Spacing, Group};
+
+#[proc_macro_attribute]
+pub fn foo(attr: TokenStream, input: TokenStream) -> TokenStream {
+    assert!(attr.is_empty());
+    let input = input.into_iter().collect::<Vec<_>>();
+    {
+        let mut cursor = &input[..];
+        assert_inline(&mut cursor);
+        assert_doc(&mut cursor);
+        assert_inline(&mut cursor);
+        assert_doc(&mut cursor);
+        assert_foo(&mut cursor);
+        assert!(cursor.is_empty());
+    }
+    fold_stream(input.into_iter().collect())
+}
+
+#[proc_macro_attribute]
+pub fn bar(attr: TokenStream, input: TokenStream) -> TokenStream {
+    assert!(attr.is_empty());
+    let input = input.into_iter().collect::<Vec<_>>();
+    {
+        let mut cursor = &input[..];
+        assert_inline(&mut cursor);
+        assert_doc(&mut cursor);
+        assert_invoc(&mut cursor);
+        assert_inline(&mut cursor);
+        assert_doc(&mut cursor);
+        assert_foo(&mut cursor);
+        assert!(cursor.is_empty());
+    }
+    input.into_iter().collect()
+}
+
+fn assert_inline(slice: &mut &[TokenTree]) {
+    match &slice[0] {
+        TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'),
+        _ => panic!("expected '#' char"),
+    }
+    match &slice[1] {
+        TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket),
+        _ => panic!("expected brackets"),
+    }
+    *slice = &slice[2..];
+}
+
+fn assert_doc(slice: &mut &[TokenTree]) {
+    match &slice[0] {
+        TokenTree::Punct(tt) => {
+            assert_eq!(tt.as_char(), '#');
+            assert_eq!(tt.spacing(), Spacing::Alone);
+        }
+        _ => panic!("expected #"),
+    }
+    let inner = match &slice[1] {
+        TokenTree::Group(tt) => {
+            assert_eq!(tt.delimiter(), Delimiter::Bracket);
+            tt.stream()
+        }
+        _ => panic!("expected brackets"),
+    };
+    let tokens = inner.into_iter().collect::<Vec<_>>();
+    let tokens = &tokens[..];
+
+    if tokens.len() != 3 {
+        panic!("expected three tokens in doc")
+    }
+
+    match &tokens[0] {
+        TokenTree::Ident(tt) => assert_eq!("doc", &*tt.to_string()),
+        _ => panic!("expected `doc`"),
+    }
+    match &tokens[1] {
+        TokenTree::Punct(tt) => {
+            assert_eq!(tt.as_char(), '=');
+            assert_eq!(tt.spacing(), Spacing::Alone);
+        }
+        _ => panic!("expected equals"),
+    }
+    match tokens[2] {
+        TokenTree::Literal(_) => {}
+        _ => panic!("expected literal"),
+    }
+
+    *slice = &slice[2..];
+}
+
+fn assert_invoc(slice: &mut &[TokenTree]) {
+    match &slice[0] {
+        TokenTree::Punct(tt) => assert_eq!(tt.as_char(), '#'),
+        _ => panic!("expected '#' char"),
+    }
+    match &slice[1] {
+        TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Bracket),
+        _ => panic!("expected brackets"),
+    }
+    *slice = &slice[2..];
+}
+
+fn assert_foo(slice: &mut &[TokenTree]) {
+    match &slice[0] {
+        TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "fn"),
+        _ => panic!("expected fn"),
+    }
+    match &slice[1] {
+        TokenTree::Ident(tt) => assert_eq!(&*tt.to_string(), "foo"),
+        _ => panic!("expected foo"),
+    }
+    match &slice[2] {
+        TokenTree::Group(tt) => {
+            assert_eq!(tt.delimiter(), Delimiter::Parenthesis);
+            assert!(tt.stream().is_empty());
+        }
+        _ => panic!("expected parens"),
+    }
+    match &slice[3] {
+        TokenTree::Group(tt) => assert_eq!(tt.delimiter(), Delimiter::Brace),
+        _ => panic!("expected braces"),
+    }
+    *slice = &slice[4..];
+}
+
+fn fold_stream(input: TokenStream) -> TokenStream {
+    input.into_iter().map(fold_tree).collect()
+}
+
+fn fold_tree(input: TokenTree) -> TokenTree {
+    match input {
+        TokenTree::Group(b) => {
+            TokenTree::Group(Group::new(b.delimiter(), fold_stream(b.stream())))
+        }
+        TokenTree::Punct(b) => TokenTree::Punct(b),
+        TokenTree::Ident(a) => TokenTree::Ident(a),
+        TokenTree::Literal(a) => {
+            if a.to_string() != "\"foo\"" {
+                TokenTree::Literal(a)
+            } else {
+                TokenTree::Literal(Literal::i32_unsuffixed(3))
+            }
+        }
+    }
+}
diff --git a/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs
new file mode 100644
index 00000000000..93a339840d6
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/attributes-on-definitions.rs
@@ -0,0 +1,23 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(allow_internal_unsafe)]
+#![feature(allow_internal_unstable)]
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+#[allow_internal_unstable(proc_macro_internals)]
+#[allow_internal_unsafe]
+#[deprecated(since = "1.0.0", note = "test")]
+pub fn with_attrs(_: TokenStream) -> TokenStream {
+    "
+    extern crate proc_macro;
+    use ::proc_macro::bridge;
+
+    fn contains_unsafe() { unsafe {} }
+    ".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/bang-macro.rs b/tests/ui/proc-macro/auxiliary/bang-macro.rs
new file mode 100644
index 00000000000..ff000228218
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/bang-macro.rs
@@ -0,0 +1,17 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn rewrite(input: TokenStream) -> TokenStream {
+    let input = input.to_string();
+
+    assert_eq!(input, r#""Hello, world!""#);
+
+    r#""NOT Hello, world!""#.parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs b/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs
new file mode 100644
index 00000000000..fcaaba6023d
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/bang_proc_macro2.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn bang_proc_macro2(_: TokenStream) -> TokenStream {
+    "let x = foobar2;".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/builtin-attrs.rs b/tests/ui/proc-macro/auxiliary/builtin-attrs.rs
new file mode 100644
index 00000000000..6edafae3985
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/builtin-attrs.rs
@@ -0,0 +1,27 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn feature(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn repr(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn test(_: TokenStream, input: TokenStream) -> TokenStream {
+    "struct Test;".parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn bench(_: TokenStream, input: TokenStream) -> TokenStream {
+    "struct Bench;".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/call-deprecated.rs b/tests/ui/proc-macro/auxiliary/call-deprecated.rs
new file mode 100644
index 00000000000..2f484809a5c
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/call-deprecated.rs
@@ -0,0 +1,19 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+#[deprecated(since = "1.0.0", note = "test")]
+pub fn attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+#[deprecated(since = "1.0.0", note = "test")]
+pub fn attr_remove(_: TokenStream, _: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/call-site.rs b/tests/ui/proc-macro/auxiliary/call-site.rs
new file mode 100644
index 00000000000..e64a5a3438a
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/call-site.rs
@@ -0,0 +1,27 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn check(input: TokenStream) -> TokenStream {
+    // Parsed `x2` can refer to `x2` from `input`
+    let parsed1: TokenStream = "let x3 = x2;".parse().unwrap();
+    // `x3` parsed from one string can refer to `x3` parsed from another string.
+    let parsed2: TokenStream = "let x4 = x3;".parse().unwrap();
+    // Manually assembled `x4` can refer to parsed `x4`.
+    let manual: Vec<TokenTree> = vec![
+        Ident::new("let", Span::call_site()).into(),
+        Ident::new("x5", Span::call_site()).into(),
+        Punct::new('=', Spacing::Alone).into(),
+        Ident::new("x4", Span::call_site()).into(),
+        Punct::new(';', Spacing::Alone).into(),
+    ];
+    input.into_iter().chain(parsed1.into_iter())
+                     .chain(parsed2.into_iter())
+                     .chain(manual.into_iter())
+                     .collect()
+}
diff --git a/tests/ui/proc-macro/auxiliary/cond_plugin.rs b/tests/ui/proc-macro/auxiliary/cond_plugin.rs
new file mode 100644
index 00000000000..8d3c4ec239a
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/cond_plugin.rs
@@ -0,0 +1,38 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn cond(input: TokenStream) -> TokenStream {
+    let mut conds = Vec::new();
+    let mut input = input.into_iter().peekable();
+    while let Some(tree) = input.next() {
+        let cond = match tree {
+            TokenTree::Group(tt) => tt.stream(),
+            _ => panic!("Invalid input"),
+        };
+        let mut cond_trees = cond.clone().into_iter();
+        let test = cond_trees.next().expect("Unexpected empty condition in `cond!`");
+        let rhs = cond_trees.collect::<TokenStream>();
+        if rhs.is_empty() {
+            panic!("Invalid macro usage in cond: {}", cond);
+        }
+        let is_else = match test {
+            TokenTree::Ident(ref word) => &*word.to_string() == "else",
+            _ => false,
+        };
+        conds.push(if is_else || input.peek().is_none() {
+            quote!({ $rhs })
+        } else {
+            quote!(if $test { $rhs } else)
+        });
+    }
+
+    conds.into_iter().flat_map(|x| x.into_iter()).collect()
+}
diff --git a/tests/ui/proc-macro/auxiliary/count_compound_ops.rs b/tests/ui/proc-macro/auxiliary/count_compound_ops.rs
new file mode 100644
index 00000000000..3a656d6485e
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/count_compound_ops.rs
@@ -0,0 +1,32 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Spacing, Literal, quote};
+
+#[proc_macro]
+pub fn count_compound_ops(input: TokenStream) -> TokenStream {
+    assert_eq!(count_compound_ops_helper(quote!(++ (&&) 4@a)), 3);
+    let l = Literal::u32_suffixed(count_compound_ops_helper(input));
+    TokenTree::from(l).into()
+}
+
+fn count_compound_ops_helper(input: TokenStream) -> u32 {
+    let mut count = 0;
+    for token in input {
+        match &token {
+            TokenTree::Punct(tt) if tt.spacing() == Spacing::Alone => {
+                count += 1;
+            }
+            TokenTree::Group(tt) => {
+                count += count_compound_ops_helper(tt.stream());
+            }
+            _ => {}
+        }
+    }
+    count
+}
diff --git a/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs b/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs
new file mode 100644
index 00000000000..41f73f5963a
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs
@@ -0,0 +1,18 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo)]
+pub fn foo(a: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
+
+#[proc_macro_derive(Bar, attributes(custom))]
+pub fn bar(a: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/custom-quote.rs b/tests/ui/proc-macro/auxiliary/custom-quote.rs
new file mode 100644
index 00000000000..3b7811748ed
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/custom-quote.rs
@@ -0,0 +1,32 @@
+// force-host
+// no-prefer-dynamic
+// ignore-tidy-linelength
+
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use std::iter::FromIterator;
+use std::str::FromStr;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn custom_quote(input: TokenStream) -> TokenStream {
+    let mut tokens: Vec<_> = input.into_iter().collect();
+    assert_eq!(tokens.len(), 1, "Unexpected input: {:?}", tokens);
+    match tokens.pop() {
+        Some(TokenTree::Ident(ident)) => {
+            assert_eq!(ident.to_string(), "my_ident");
+
+            let proc_macro_crate = TokenStream::from_str("::proc_macro").unwrap();
+            let quoted_span = proc_macro::quote_span(proc_macro_crate, ident.span());
+            let prefix = TokenStream::from_str(r#"let mut ident = proc_macro::Ident::new("my_ident", proc_macro::Span::call_site());"#).unwrap();
+            let set_span_method = TokenStream::from_str("ident.set_span").unwrap();
+            let set_span_arg = TokenStream::from(TokenTree::Group(Group::new(Delimiter::Parenthesis, quoted_span)));
+            let suffix = TokenStream::from_str(";proc_macro::TokenStream::from(proc_macro::TokenTree::Ident(ident))").unwrap();
+            let full_stream = TokenStream::from_iter([prefix, set_span_method, set_span_arg, suffix]);
+            full_stream
+        }
+        _ => unreachable!()
+    }
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-a.rs b/tests/ui/proc-macro/auxiliary/derive-a.rs
new file mode 100644
index 00000000000..79a3864bf99
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-a.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    let input = input.to_string();
+    assert!(input.contains("struct A ;"));
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-atob.rs b/tests/ui/proc-macro/auxiliary/derive-atob.rs
new file mode 100644
index 00000000000..207b7fd3203
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-atob.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(AToB)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    let input = input.to_string();
+    assert_eq!(input, "struct A ;");
+    "struct B;".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs b/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs
new file mode 100644
index 00000000000..e7e9634e0bd
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-attr-cfg.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo, attributes(foo))]
+pub fn derive(input: TokenStream) -> TokenStream {
+    assert!(!input.to_string().contains("#[cfg(any())]"));
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs
new file mode 100644
index 00000000000..641a95f78c1
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs
@@ -0,0 +1,17 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(B, attributes(B, C))]
+pub fn derive(input: TokenStream) -> TokenStream {
+    let input = input.to_string();
+    assert!(input.contains("#[B [arbitrary tokens]]"));
+    assert!(input.contains("struct B {"));
+    assert!(input.contains("#[C]"));
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-b.rs b/tests/ui/proc-macro/auxiliary/derive-b.rs
new file mode 100644
index 00000000000..e7ab6c0729f
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-b.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(B, attributes(B))]
+pub fn derive_b(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-bad.rs b/tests/ui/proc-macro/auxiliary/derive-bad.rs
new file mode 100644
index 00000000000..90bb9b1baf2
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-bad.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn derive_a(_input: TokenStream) -> TokenStream {
+    "struct A { inner }".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-clona.rs b/tests/ui/proc-macro/auxiliary/derive-clona.rs
new file mode 100644
index 00000000000..4a35c9d0dbb
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-clona.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Clona)]
+pub fn derive_clonea(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-ctod.rs b/tests/ui/proc-macro/auxiliary/derive-ctod.rs
new file mode 100644
index 00000000000..2efe5a91340
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-ctod.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(CToD)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    let input = input.to_string();
+    assert_eq!(input, "struct C ;");
+    "struct D;".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-foo.rs b/tests/ui/proc-macro/auxiliary/derive-foo.rs
new file mode 100644
index 00000000000..3ea027d4f53
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-foo.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(FooWithLongName)]
+pub fn derive_foo(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs
new file mode 100644
index 00000000000..ab532da2992
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs
@@ -0,0 +1,2 @@
+#[macro_export]
+macro_rules! empty_helper { () => () }
diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs
new file mode 100644
index 00000000000..370a1a2794d
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive(same_name, attributes(same_name))]
+pub fn derive_a(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs
new file mode 100644
index 00000000000..41d3a184640
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-helper-shadowing.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive(GenHelperUse)]
+pub fn derive_a(_: TokenStream) -> TokenStream {
+    "
+    #[empty_helper]
+    struct Uwu;
+    ".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-nothing.rs b/tests/ui/proc-macro/auxiliary/derive-nothing.rs
new file mode 100644
index 00000000000..b6d1e133af7
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-nothing.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Nothing)]
+pub fn nothing(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-same-struct.rs b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs
new file mode 100644
index 00000000000..7598d632cb6
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs
@@ -0,0 +1,21 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(AToB)]
+pub fn derive1(input: TokenStream) -> TokenStream {
+    println!("input1: {:?}", input.to_string());
+    assert_eq!(input.to_string(), "struct A ;");
+    "#[derive(BToC)] struct B;".parse().unwrap()
+}
+
+#[proc_macro_derive(BToC)]
+pub fn derive2(input: TokenStream) -> TokenStream {
+    assert_eq!(input.to_string(), "struct B ;");
+    "struct C;".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs b/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs
new file mode 100644
index 00000000000..a6f0eec126a
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-two-attrs.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_derive(A, attributes(b))]
+pub fn foo(_x: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-union.rs b/tests/ui/proc-macro/auxiliary/derive-union.rs
new file mode 100644
index 00000000000..05883170c6c
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-union.rs
@@ -0,0 +1,18 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(UnionTest)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    let input = input.to_string();
+    assert!(input.contains("#[repr(C)]"));
+    assert!(input.contains("union Test {"));
+    assert!(input.contains("a : u8,"));
+    assert!(input.contains("}"));
+    "".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs b/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs
new file mode 100644
index 00000000000..eac21b04983
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-unstable-2.rs
@@ -0,0 +1,17 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Unstable)]
+pub fn derive(_input: TokenStream) -> TokenStream {
+
+    "
+        #[rustc_foo]
+        fn foo() {}
+    ".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/derive-unstable.rs b/tests/ui/proc-macro/auxiliary/derive-unstable.rs
new file mode 100644
index 00000000000..2ccd3f88200
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/derive-unstable.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Unstable)]
+pub fn derive(_input: TokenStream) -> TokenStream {
+
+    "unsafe fn foo() -> u32 { ::std::intrinsics::abort() }".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/dollar-crate-external.rs b/tests/ui/proc-macro/auxiliary/dollar-crate-external.rs
new file mode 100644
index 00000000000..bdcdb7922ca
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/dollar-crate-external.rs
@@ -0,0 +1,22 @@
+pub type S = u8;
+
+#[macro_export]
+macro_rules! external {
+    () => {
+        print_bang! {
+            struct M($crate::S);
+        }
+
+        #[print_attr]
+        struct A($crate::S);
+
+        #[derive(Print)]
+        struct D($crate::S);
+    };
+}
+
+#[macro_export]
+macro_rules! issue_62325 { () => {
+    #[print_attr]
+    struct B(identity!($crate::S));
+}}
diff --git a/tests/ui/proc-macro/auxiliary/double.rs b/tests/ui/proc-macro/auxiliary/double.rs
new file mode 100644
index 00000000000..99eb4e37546
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/double.rs
@@ -0,0 +1,16 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_quote)]
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+// 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 {
+    quote!(mod foo { $input })
+}
diff --git a/tests/ui/proc-macro/auxiliary/duplicate.rs b/tests/ui/proc-macro/auxiliary/duplicate.rs
new file mode 100644
index 00000000000..b8f82b46f09
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/duplicate.rs
@@ -0,0 +1,32 @@
+// force-host
+// no-prefer-dynamic
+
+#![deny(unused)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn duplicate(attr: TokenStream, item: TokenStream) -> TokenStream {
+    let mut new_name = Some(attr.into_iter().nth(0).unwrap());
+    let mut encountered_idents = 0;
+    let input = item.to_string();
+    let ret = item
+        .into_iter()
+        .map(move |token| match token {
+            TokenTree::Ident(_) if encountered_idents == 1 => {
+                encountered_idents += 1;
+                new_name.take().unwrap()
+            }
+            TokenTree::Ident(_) => {
+                encountered_idents += 1;
+                token
+            }
+            _ => token,
+        })
+        .collect::<TokenStream>();
+    let mut input_again = input.parse::<TokenStream>().unwrap();
+    input_again.extend(ret);
+    input_again
+}
diff --git a/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs b/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs
new file mode 100644
index 00000000000..27c59b805e2
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/edition-imports-2015.rs
@@ -0,0 +1,20 @@
+// edition:2015
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Derive2015)]
+pub fn derive_2015(_: TokenStream) -> TokenStream {
+    "
+    use import::Path;
+
+    fn check_absolute() {
+        let x = ::absolute::Path;
+    }
+    ".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/empty-crate.rs b/tests/ui/proc-macro/auxiliary/empty-crate.rs
new file mode 100644
index 00000000000..1cf7534b289
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/empty-crate.rs
@@ -0,0 +1,5 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![deny(unused_variables)]
diff --git a/tests/ui/proc-macro/auxiliary/expand-expr.rs b/tests/ui/proc-macro/auxiliary/expand-expr.rs
new file mode 100644
index 00000000000..1d6ef8a1361
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/expand-expr.rs
@@ -0,0 +1,166 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![deny(warnings)]
+#![feature(proc_macro_expand, proc_macro_span)]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+use std::str::FromStr;
+
+// Flatten the TokenStream, removing any toplevel `Delimiter::None`s for
+// comparison.
+fn flatten(ts: TokenStream) -> Vec<TokenTree> {
+    ts.into_iter()
+        .flat_map(|tt| match &tt {
+            TokenTree::Group(group) if group.delimiter() == Delimiter::None => {
+                flatten(group.stream())
+            }
+            _ => vec![tt],
+        })
+        .collect()
+}
+
+// Assert that two TokenStream values are roughly equal to one-another.
+fn assert_ts_eq(lhs: &TokenStream, rhs: &TokenStream) {
+    let ltts = flatten(lhs.clone());
+    let rtts = flatten(rhs.clone());
+
+    if ltts.len() != rtts.len() {
+        panic!(
+            "expected the same number of tts ({} == {})\nlhs:\n{:#?}\nrhs:\n{:#?}",
+            ltts.len(),
+            rtts.len(),
+            lhs,
+            rhs
+        )
+    }
+
+    for (ltt, rtt) in ltts.iter().zip(&rtts) {
+        match (ltt, rtt) {
+            (TokenTree::Group(l), TokenTree::Group(r)) => {
+                assert_eq!(
+                    l.delimiter(),
+                    r.delimiter(),
+                    "expected delimiters to match for {:?} and {:?}",
+                    l,
+                    r
+                );
+                assert_ts_eq(&l.stream(), &r.stream());
+            }
+            (TokenTree::Punct(l), TokenTree::Punct(r)) => assert_eq!(
+                (l.as_char(), l.spacing()),
+                (r.as_char(), r.spacing()),
+                "expected punct to match for {:?} and {:?}",
+                l,
+                r
+            ),
+            (TokenTree::Ident(l), TokenTree::Ident(r)) => assert_eq!(
+                l.to_string(),
+                r.to_string(),
+                "expected ident to match for {:?} and {:?}",
+                l,
+                r
+            ),
+            (TokenTree::Literal(l), TokenTree::Literal(r)) => assert_eq!(
+                l.to_string(),
+                r.to_string(),
+                "expected literal to match for {:?} and {:?}",
+                l,
+                r
+            ),
+            (l, r) => panic!("expected type to match for {:?} and {:?}", l, r),
+        }
+    }
+}
+
+#[proc_macro]
+pub fn expand_expr_is(input: TokenStream) -> TokenStream {
+    let mut iter = input.into_iter();
+    let mut expected_tts = Vec::new();
+    let comma = loop {
+        match iter.next() {
+            Some(TokenTree::Punct(p)) if p.as_char() == ',' => break p,
+            Some(tt) => expected_tts.push(tt),
+            None => panic!("expected comma"),
+        }
+    };
+
+    // Make sure that `Ident` and `Literal` objects from this proc-macro's
+    // environment are not invalidated when `expand_expr` recursively invokes
+    // another macro by taking a local copy, and checking it after the fact.
+    let pre_expand_span = comma.span();
+    let pre_expand_ident = Ident::new("ident", comma.span());
+    let pre_expand_literal = Literal::string("literal");
+    let pre_expand_call_site = Span::call_site();
+
+    let expected = expected_tts.into_iter().collect::<TokenStream>();
+    let expanded = iter.collect::<TokenStream>().expand_expr().expect("expand_expr failed");
+    assert!(
+        expected.to_string() == expanded.to_string(),
+        "assert failed\nexpected: `{}`\nexpanded: `{}`",
+        expected.to_string(),
+        expanded.to_string()
+    );
+
+    // Also compare the raw tts to make sure they line up.
+    assert_ts_eq(&expected, &expanded);
+
+    assert!(comma.span().eq(&pre_expand_span), "pre-expansion span is still equal");
+    assert_eq!(pre_expand_ident.to_string(), "ident", "pre-expansion identifier is still valid");
+    assert_eq!(
+        pre_expand_literal.to_string(),
+        "\"literal\"",
+        "pre-expansion literal is still valid"
+    );
+    assert!(Span::call_site().eq(&pre_expand_call_site), "pre-expansion call-site is still equal");
+
+    TokenStream::new()
+}
+
+#[proc_macro]
+pub fn expand_expr_fail(input: TokenStream) -> TokenStream {
+    match input.expand_expr() {
+        Ok(ts) => panic!("expand_expr unexpectedly succeeded: `{}`", ts),
+        Err(_) => TokenStream::new(),
+    }
+}
+
+#[proc_macro]
+pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream {
+    // Check that the passed in `file!()` invocation and a parsed `file!`
+    // invocation expand to the same literal.
+    let input_t = ts.expand_expr().expect("expand_expr failed on macro input").to_string();
+    let parse_t = TokenStream::from_str("file!{}")
+        .unwrap()
+        .expand_expr()
+        .expect("expand_expr failed on internal macro")
+        .to_string();
+    assert_eq!(input_t, parse_t);
+
+    // Check that the literal matches `Span::call_site().source_file().path()`
+    let expect_t =
+        Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string();
+    assert_eq!(input_t, expect_t);
+
+    TokenStream::new()
+}
+
+#[proc_macro]
+pub fn recursive_expand(_: TokenStream) -> TokenStream {
+    // Recursively call until we hit the recursion limit and get an error.
+    //
+    // NOTE: This doesn't panic if expansion fails because that'll cause a very
+    // large number of errors to fill the output.
+    TokenStream::from_str("recursive_expand!{}")
+        .unwrap()
+        .expand_expr()
+        .unwrap_or(std::iter::once(TokenTree::Literal(Literal::u32_suffixed(0))).collect())
+}
+
+#[proc_macro]
+pub fn echo_pm(input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs
new file mode 100644
index 00000000000..d779d57af14
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs
@@ -0,0 +1,22 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![deny(warnings)]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(A)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    let input = input.to_string();
+    assert!(input.contains("struct A ;"));
+    r#"
+        impl A {
+            fn a(&self) {
+                panic!("hello");
+            }
+        }
+    "#.parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/external-crate-var.rs b/tests/ui/proc-macro/auxiliary/external-crate-var.rs
new file mode 100644
index 00000000000..4319e921225
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/external-crate-var.rs
@@ -0,0 +1,40 @@
+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/tests/ui/proc-macro/auxiliary/first-second.rs b/tests/ui/proc-macro/auxiliary/first-second.rs
new file mode 100644
index 00000000000..6331608fbe5
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/first-second.rs
@@ -0,0 +1,20 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Group, Delimiter};
+
+#[proc_macro_attribute]
+pub fn first(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    let tokens: TokenStream = "#[derive(Second)]".parse().unwrap();
+    let wrapped = TokenTree::Group(Group::new(Delimiter::None, item.into_iter().collect()));
+    tokens.into_iter().chain(std::iter::once(wrapped)).collect()
+}
+
+#[proc_macro_derive(Second)]
+pub fn second(item: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs b/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs
new file mode 100644
index 00000000000..d1a1c584f8b
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/gen-lifetime-token.rs
@@ -0,0 +1,25 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn bar(_input: TokenStream) -> TokenStream {
+    let mut ret = Vec::<TokenTree>::new();
+    ret.push(Ident::new("static", Span::call_site()).into());
+    ret.push(Ident::new("FOO", Span::call_site()).into());
+    ret.push(Punct::new(':', Spacing::Alone).into());
+    ret.push(Punct::new('&', Spacing::Alone).into());
+    ret.push(Punct::new('\'', Spacing::Joint).into());
+    ret.push(Ident::new("static", Span::call_site()).into());
+    ret.push(Ident::new("i32", Span::call_site()).into());
+    ret.push(Punct::new('=', Spacing::Alone).into());
+    ret.push(Punct::new('&', Spacing::Alone).into());
+    ret.push(Literal::i32_unsuffixed(1).into());
+    ret.push(Punct::new(';', Spacing::Alone).into());
+    ret.into_iter().collect()
+}
diff --git a/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs b/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs
new file mode 100644
index 00000000000..548fefe76f5
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs
@@ -0,0 +1,23 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn gen_macro_rules(_: TokenStream) -> TokenStream {
+    "
+    macro_rules! generated {() => {
+        struct ItemDef;
+        let local_def = 0;
+
+        ItemUse; // OK
+        local_use; // ERROR
+        break 'label_use; // ERROR
+
+        type DollarCrate = $crate::ItemUse; // OK
+    }}
+    ".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs b/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs
new file mode 100644
index 00000000000..d4b67d6b0b0
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/gen-macro-rules.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(repro)]
+pub fn proc_macro_hack_expr(_input: TokenStream) -> TokenStream {
+    "macro_rules! m {()=>{}}".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs b/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs
new file mode 100644
index 00000000000..3f3e12eed6c
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/generate-dollar-ident.rs
@@ -0,0 +1,16 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn dollar_ident(input: TokenStream) -> TokenStream {
+    let black_hole = input.into_iter().next().unwrap();
+    quote! {
+        $black_hole!($$var);
+    }
+}
diff --git a/tests/ui/proc-macro/auxiliary/generate-mod.rs b/tests/ui/proc-macro/auxiliary/generate-mod.rs
new file mode 100644
index 00000000000..e950f7d62d6
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/generate-mod.rs
@@ -0,0 +1,58 @@
+// run-pass
+// force-host
+// no-prefer-dynamic
+// ignore-pass
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn check(_: TokenStream) -> TokenStream {
+    "
+    type Alias = FromOutside; // OK
+    struct Outer;
+    mod inner {
+        type Alias = FromOutside; // `FromOutside` shouldn't be available from here
+        type Inner = Outer; // `Outer` shouldn't be available from here
+    }
+    ".parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn check_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+    "
+    type AliasAttr = FromOutside; // OK
+    struct OuterAttr;
+    mod inner_attr {
+        type Alias = FromOutside; // `FromOutside` shouldn't be available from here
+        type Inner = OuterAttr; // `OuterAttr` shouldn't be available from here
+    }
+    ".parse().unwrap()
+}
+
+#[proc_macro_derive(CheckDerive)]
+pub fn check_derive(_: TokenStream) -> TokenStream {
+    "
+    type AliasDerive = FromOutside; // OK
+    struct OuterDerive;
+    mod inner_derive {
+        type Alias = FromOutside; // `FromOutside` shouldn't be available from here
+        type Inner = OuterDerive; // `OuterDerive` shouldn't be available from here
+    }
+    ".parse().unwrap()
+}
+
+#[proc_macro_derive(CheckDeriveLint)]
+pub fn check_derive_lint(_: TokenStream) -> TokenStream {
+    "
+    type AliasDeriveLint = FromOutside; // OK
+    struct OuterDeriveLint;
+    #[allow(proc_macro_derive_resolution_fallback)]
+    mod inner_derive_lint {
+        type Alias = FromOutside; // `FromOutside` shouldn't be available from here
+        type Inner = OuterDeriveLint; // `OuterDeriveLint` shouldn't be available from here
+    }
+    ".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/hygiene_example.rs b/tests/ui/proc-macro/auxiliary/hygiene_example.rs
new file mode 100644
index 00000000000..f7e7e0b5751
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/hygiene_example.rs
@@ -0,0 +1,7 @@
+extern crate hygiene_example_codegen;
+
+pub use hygiene_example_codegen::hello;
+
+pub fn print(string: &str) {
+    println!("{}", string);
+}
diff --git a/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs b/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs
new file mode 100644
index 00000000000..2bd4d33360f
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/hygiene_example_codegen.rs
@@ -0,0 +1,27 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro as proc_macro_renamed; // This does not break `quote!`
+
+use proc_macro_renamed::{TokenStream, quote};
+
+#[proc_macro]
+pub fn hello(input: TokenStream) -> TokenStream {
+    quote!(hello_helper!($input))
+    //^ `hello_helper!` always resolves to the following proc macro,
+    //| no matter where `hello!` is used.
+}
+
+#[proc_macro]
+pub fn hello_helper(input: TokenStream) -> TokenStream {
+    quote! {
+        extern crate hygiene_example; // This is never a conflict error
+        let string = format!("hello {}", $input);
+        //^ `format!` always resolves to the prelude macro,
+        //| even if a different `format!` is in scope where `hello!` is used.
+        hygiene_example::print(&string)
+    }
+}
diff --git a/tests/ui/proc-macro/auxiliary/included-file.txt b/tests/ui/proc-macro/auxiliary/included-file.txt
new file mode 100644
index 00000000000..b4720047d6c
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/included-file.txt
@@ -0,0 +1 @@
+Included file contents
diff --git a/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs b/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs
new file mode 100644
index 00000000000..518dfd0d688
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/invalid-punct-ident.rs
@@ -0,0 +1,28 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_raw_ident)]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn invalid_punct(_: TokenStream) -> TokenStream {
+    TokenTree::from(Punct::new('`', Spacing::Alone)).into()
+}
+
+#[proc_macro]
+pub fn invalid_ident(_: TokenStream) -> TokenStream {
+    TokenTree::from(Ident::new("*", Span::call_site())).into()
+}
+
+#[proc_macro]
+pub fn invalid_raw_ident(_: TokenStream) -> TokenStream {
+    TokenTree::from(Ident::new_raw("self", Span::call_site())).into()
+}
+
+#[proc_macro]
+pub fn lexer_failure(_: TokenStream) -> TokenStream {
+    "a b ) c".parse().expect("parsing failed without panic")
+}
diff --git a/tests/ui/proc-macro/auxiliary/is-available.rs b/tests/ui/proc-macro/auxiliary/is-available.rs
new file mode 100644
index 00000000000..03f5265e376
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/is-available.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{Literal, TokenStream, TokenTree};
+
+#[proc_macro]
+pub fn from_inside_proc_macro(_input: TokenStream) -> TokenStream {
+    proc_macro::is_available().to_string().parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-104884.rs b/tests/ui/proc-macro/auxiliary/issue-104884.rs
new file mode 100644
index 00000000000..0de59d00573
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-104884.rs
@@ -0,0 +1,23 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(AddImpl)]
+
+pub fn derive(input: TokenStream) -> TokenStream {
+    "use std::cmp::Ordering;
+
+    impl<T> Ord for PriorityQueue<T> {
+        fn cmp(&self, other: &Self) -> Ordering {
+            self.0.cmp(&self.height)
+        }
+    }
+    "
+    .parse()
+    .unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-38586.rs b/tests/ui/proc-macro/auxiliary/issue-38586.rs
new file mode 100644
index 00000000000..f3a19081c47
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-38586.rs
@@ -0,0 +1,11 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+#[proc_macro_derive(A)]
+pub fn derive_a(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
+    "fn f() { println!(\"{}\", foo); }".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-39889.rs b/tests/ui/proc-macro/auxiliary/issue-39889.rs
new file mode 100644
index 00000000000..e7af66da797
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-39889.rs
@@ -0,0 +1,17 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Issue39889)]
+pub fn f(_input: TokenStream) -> TokenStream {
+    let rules = r#"
+        macro_rules! id {
+            ($($tt:tt)*) => { $($tt)* };
+        }
+    "#;
+    rules.parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-42708.rs b/tests/ui/proc-macro/auxiliary/issue-42708.rs
new file mode 100644
index 00000000000..dae05204b8b
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-42708.rs
@@ -0,0 +1,18 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Test)]
+pub fn derive(_input: TokenStream) -> TokenStream {
+    "fn f(s: S) { s.x }".parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn attr_test(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-50061.rs b/tests/ui/proc-macro/auxiliary/issue-50061.rs
new file mode 100644
index 00000000000..f5fe8cabbce
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-50061.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn check(_a: TokenStream, b: TokenStream) -> TokenStream {
+    b.into_iter().collect()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-50493.rs b/tests/ui/proc-macro/auxiliary/issue-50493.rs
new file mode 100644
index 00000000000..f72024948a9
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-50493.rs
@@ -0,0 +1,21 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Derive)]
+pub fn derive(_: TokenStream) -> TokenStream {
+    let code = "
+        fn one(r: Restricted) {
+            r.field;
+        }
+        fn two(r: Restricted) {
+            r.field;
+        }
+    ";
+
+    code.parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-59191.rs b/tests/ui/proc-macro/auxiliary/issue-59191.rs
new file mode 100644
index 00000000000..d9ee77067ec
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-59191.rs
@@ -0,0 +1,16 @@
+// edition:2018
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn no_main(_attrs: TokenStream, _input: TokenStream) -> TokenStream {
+    let new_krate = r#"
+        fn main() {}
+    "#;
+    new_krate.parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-66286.rs b/tests/ui/proc-macro/auxiliary/issue-66286.rs
new file mode 100644
index 00000000000..6217f1c7e61
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-66286.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn vec_ice(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    // This redundant convert is necessary to reproduce ICE.
+    input.into_iter().collect()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-75801.rs b/tests/ui/proc-macro/auxiliary/issue-75801.rs
new file mode 100644
index 00000000000..d6c031d7d4f
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-75801.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn foo(_args: TokenStream, item: TokenStream) -> TokenStream {
+    item
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-79242.rs b/tests/ui/proc-macro/auxiliary/issue-79242.rs
new file mode 100644
index 00000000000..e586980f0ad
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-79242.rs
@@ -0,0 +1,16 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn dummy(input: TokenStream) -> TokenStream {
+    // Iterate to force internal conversion of nonterminals
+    // to `proc_macro` structs
+    for _ in input {}
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-79825.rs b/tests/ui/proc-macro/auxiliary/issue-79825.rs
new file mode 100644
index 00000000000..930891b1d43
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-79825.rs
@@ -0,0 +1,14 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn assert_input(args: TokenStream, input: TokenStream) -> TokenStream {
+    assert_eq!(input.to_string(), "trait Alias = Sized ;");
+    assert!(args.is_empty());
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-83510.rs b/tests/ui/proc-macro/auxiliary/issue-83510.rs
new file mode 100644
index 00000000000..1d6ef3914a9
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-83510.rs
@@ -0,0 +1,19 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn dance_like_you_want_to_ice(_: TokenStream) -> TokenStream {
+    r#"
+    impl Foo {
+        type Bar = Box<()> + Baz;
+    }
+    "#
+    .parse()
+    .unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs b/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs
new file mode 100644
index 00000000000..958a8bed9e2
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/issue-91800-macro.rs
@@ -0,0 +1,26 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+fn compile_error() -> TokenStream {
+    r#"compile_error!("")"#.parse().unwrap()
+}
+
+#[proc_macro_derive(MyTrait)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    compile_error()
+}
+#[proc_macro_attribute]
+pub fn attribute_macro(_attr: TokenStream, mut input: TokenStream) -> TokenStream {
+    input.extend(compile_error());
+    input
+}
+#[proc_macro]
+pub fn fn_macro(_item: TokenStream) -> TokenStream {
+    compile_error()
+}
diff --git a/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs b/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs
new file mode 100644
index 00000000000..4e5d22e6e3e
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/lifetimes-rpass.rs
@@ -0,0 +1,26 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn lifetimes_bang(input: TokenStream) -> TokenStream {
+    // Roundtrip through token trees
+    input.into_iter().collect()
+}
+
+#[proc_macro_attribute]
+pub fn lifetimes_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    // Roundtrip through AST
+    input
+}
+
+#[proc_macro_derive(Lifetimes)]
+pub fn lifetimes_derive(input: TokenStream) -> TokenStream {
+    // Roundtrip through a string
+    format!("mod m {{ {} }}", input).parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/lifetimes.rs b/tests/ui/proc-macro/auxiliary/lifetimes.rs
new file mode 100644
index 00000000000..212164dd2c9
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/lifetimes.rs
@@ -0,0 +1,20 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn single_quote_alone(_: TokenStream) -> TokenStream {
+    // `&'a u8`, but the `'` token is not joint
+    let trees: Vec<TokenTree> = vec![
+        Punct::new('&', Spacing::Alone).into(),
+        Punct::new('\'', Spacing::Alone).into(),
+        Ident::new("a", Span::call_site()).into(),
+        Ident::new("u8", Span::call_site()).into(),
+    ];
+    trees.into_iter().collect()
+}
diff --git a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs
new file mode 100644
index 00000000000..c72306c3d50
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs
@@ -0,0 +1,89 @@
+// force-host
+// no-prefer-dynamic
+
+// These are tests for syntax that is accepted by the Rust parser but
+// unconditionally rejected semantically after macro expansion. Attribute macros
+// are permitted to accept such syntax as long as they replace it with something
+// that makes sense to Rust.
+//
+// We also inspect some of the spans to verify the syntax is not triggering the
+// lossy string reparse hack (https://github.com/rust-lang/rust/issues/43081).
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_span)]
+
+extern crate proc_macro;
+use proc_macro::{token_stream, Delimiter, TokenStream, TokenTree};
+use std::path::Component;
+
+// unsafe mod m {
+//     pub unsafe mod inner;
+// }
+#[proc_macro_attribute]
+pub fn expect_unsafe_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
+    let tokens = &mut input.into_iter();
+    expect(tokens, "unsafe");
+    expect(tokens, "mod");
+    expect(tokens, "m");
+    let tokens = &mut expect_brace(tokens);
+    expect(tokens, "pub");
+    expect(tokens, "unsafe");
+    expect(tokens, "mod");
+    let ident = expect(tokens, "inner");
+    expect(tokens, ";");
+    check_useful_span(ident, "unsafe-mod.rs");
+    TokenStream::new()
+}
+
+// unsafe extern {
+//     type T;
+// }
+#[proc_macro_attribute]
+pub fn expect_unsafe_foreign_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
+    let tokens = &mut input.into_iter();
+    expect(tokens, "unsafe");
+    expect(tokens, "extern");
+    let tokens = &mut expect_brace(tokens);
+    expect(tokens, "type");
+    let ident = expect(tokens, "T");
+    expect(tokens, ";");
+    check_useful_span(ident, "unsafe-foreign-mod.rs");
+    TokenStream::new()
+}
+
+// unsafe extern "C++" {}
+#[proc_macro_attribute]
+pub fn expect_unsafe_extern_cpp_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
+    let tokens = &mut input.into_iter();
+    expect(tokens, "unsafe");
+    expect(tokens, "extern");
+    let abi = expect(tokens, "\"C++\"");
+    expect_brace(tokens);
+    check_useful_span(abi, "unsafe-foreign-mod.rs");
+    TokenStream::new()
+}
+
+fn expect(tokens: &mut token_stream::IntoIter, expected: &str) -> TokenTree {
+    match tokens.next() {
+        Some(token) if token.to_string() == expected => token,
+        wrong => panic!("unexpected token: {:?}, expected `{}`", wrong, expected),
+    }
+}
+
+fn expect_brace(tokens: &mut token_stream::IntoIter) -> token_stream::IntoIter {
+    match tokens.next() {
+        Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => {
+            group.stream().into_iter()
+        }
+        wrong => panic!("unexpected token: {:?}, expected `{{`", wrong),
+    }
+}
+
+fn check_useful_span(token: TokenTree, expected_filename: &str) {
+    let span = token.span();
+    assert!(span.start().column < span.end().column);
+
+    let source_path = span.source_file().path();
+    let filename = source_path.components().last().unwrap();
+    assert_eq!(filename, Component::Normal(expected_filename.as_ref()));
+}
diff --git a/tests/ui/proc-macro/auxiliary/make-macro.rs b/tests/ui/proc-macro/auxiliary/make-macro.rs
new file mode 100644
index 00000000000..3c851b6de2a
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/make-macro.rs
@@ -0,0 +1,18 @@
+// force-host
+
+#[macro_export]
+macro_rules! make_it {
+    ($name:ident) => {
+        #[proc_macro]
+        pub fn $name(input: TokenStream) -> TokenStream {
+            println!("Def site: {:?}", Span::def_site());
+            println!("Input: {:?}", input);
+            let new: TokenStream = input.into_iter().map(|mut t| {
+                t.set_span(Span::def_site());
+                t
+            }).collect();
+            println!("Respanned: {:?}", new);
+            new
+        }
+    };
+}
diff --git a/tests/ui/proc-macro/auxiliary/meta-delim.rs b/tests/ui/proc-macro/auxiliary/meta-delim.rs
new file mode 100644
index 00000000000..54e3d785726
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/meta-delim.rs
@@ -0,0 +1,12 @@
+macro_rules! produce_it {
+    ($dollar_one:tt $foo:ident $my_name:ident) => {
+        #[macro_export]
+        macro_rules! meta_delim {
+            ($dollar_one ($dollar_one $my_name:ident)*) => {
+                stringify!($dollar_one ($dollar_one $my_name)*)
+            }
+        }
+    }
+}
+
+produce_it!($my_name name);
diff --git a/tests/ui/proc-macro/auxiliary/meta-macro.rs b/tests/ui/proc-macro/auxiliary/meta-macro.rs
new file mode 100644
index 00000000000..0a9b9887d95
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/meta-macro.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+// edition:2018
+
+#![feature(proc_macro_def_site)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+extern crate make_macro;
+use proc_macro::{TokenStream, Span};
+
+make_macro::make_it!(print_def_site);
+
+#[proc_macro]
+pub fn dummy(input: TokenStream) -> TokenStream { input }
diff --git a/tests/ui/proc-macro/auxiliary/mixed-site-span.rs b/tests/ui/proc-macro/auxiliary/mixed-site-span.rs
new file mode 100644
index 00000000000..c2a49870048
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/mixed-site-span.rs
@@ -0,0 +1,40 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_quote)]
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn proc_macro_rules(input: TokenStream) -> TokenStream {
+    if input.is_empty() {
+        let id = |s| TokenTree::from(Ident::new(s, Span::mixed_site()));
+        let item_def = id("ItemDef");
+        let local_def = id("local_def");
+        let item_use = id("ItemUse");
+        let local_use = id("local_use");
+        let mut single_quote = Punct::new('\'', Spacing::Joint);
+        single_quote.set_span(Span::mixed_site());
+        let label_use: TokenStream = [
+            TokenTree::from(single_quote),
+            id("label_use"),
+        ].iter().cloned().collect();
+        quote!(
+            struct $item_def;
+            let $local_def = 0;
+
+            $item_use; // OK
+            $local_use; // ERROR
+            break $label_use; // ERROR
+        )
+    } else {
+        let mut dollar_crate = input.into_iter().next().unwrap();
+        dollar_crate.set_span(Span::mixed_site());
+        quote!(
+            type A = $dollar_crate::ItemUse;
+        )
+    }
+}
diff --git a/tests/ui/proc-macro/auxiliary/modify-ast.rs b/tests/ui/proc-macro/auxiliary/modify-ast.rs
new file mode 100644
index 00000000000..cc582c1522c
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/modify-ast.rs
@@ -0,0 +1,47 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn assert1(_a: TokenStream, b: TokenStream) -> TokenStream {
+    assert_eq(b.clone(), "pub fn foo() {}".parse().unwrap());
+    b
+}
+
+#[proc_macro_derive(Foo, attributes(foo))]
+pub fn assert2(a: TokenStream) -> TokenStream {
+    assert_eq(a, "pub struct MyStructc { _a: i32, }".parse().unwrap());
+    TokenStream::new()
+}
+
+fn assert_eq(a: TokenStream, b: TokenStream) {
+    let mut a = a.into_iter();
+    let mut b = b.into_iter();
+    for (a, b) in a.by_ref().zip(&mut b) {
+        match (a, b) {
+            (TokenTree::Group(a), TokenTree::Group(b)) => {
+                assert_eq!(a.delimiter(), b.delimiter());
+                assert_eq(a.stream(), b.stream());
+            }
+            (TokenTree::Punct(a), TokenTree::Punct(b)) => {
+                assert_eq!(a.as_char(), b.as_char());
+                assert_eq!(a.spacing(), b.spacing());
+            }
+            (TokenTree::Literal(a), TokenTree::Literal(b)) => {
+                assert_eq!(a.to_string(), b.to_string());
+            }
+            (TokenTree::Ident(a), TokenTree::Ident(b)) => {
+                assert_eq!(a.to_string(), b.to_string());
+            }
+            (a, b) => panic!("{:?} != {:?}", a, b),
+        }
+    }
+
+    assert!(a.next().is_none());
+    assert!(b.next().is_none());
+}
diff --git a/tests/ui/proc-macro/auxiliary/multiple-derives.rs b/tests/ui/proc-macro/auxiliary/multiple-derives.rs
new file mode 100644
index 00000000000..e3f6607b2ae
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/multiple-derives.rs
@@ -0,0 +1,22 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+macro_rules! make_derives {
+    ($($name:ident),*) => {
+        $(
+            #[proc_macro_derive($name)]
+            pub fn $name(input: TokenStream) -> TokenStream {
+                println!("Derive {}: {}", stringify!($name), input);
+                TokenStream::new()
+            }
+        )*
+    }
+}
+
+make_derives!(First, Second, Third, Fourth, Fifth);
diff --git a/tests/ui/proc-macro/auxiliary/multispan.rs b/tests/ui/proc-macro/auxiliary/multispan.rs
new file mode 100644
index 00000000000..c05d15643db
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/multispan.rs
@@ -0,0 +1,37 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
+
+fn parse(input: TokenStream) -> Result<(), Diagnostic> {
+    let mut hi_spans = vec![];
+    for tree in input {
+        if let TokenTree::Ident(ref ident) = tree {
+            if ident.to_string() == "hi" {
+                hi_spans.push(ident.span());
+            }
+        }
+    }
+
+    if !hi_spans.is_empty() {
+        return Err(Span::def_site()
+                       .error("hello to you, too!")
+                       .span_note(hi_spans, "found these 'hi's"));
+    }
+
+    Ok(())
+}
+
+#[proc_macro]
+pub fn hello(input: TokenStream) -> TokenStream {
+    if let Err(diag) = parse(input) {
+        diag.emit();
+    }
+
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/negative-token.rs b/tests/ui/proc-macro/auxiliary/negative-token.rs
new file mode 100644
index 00000000000..8b89f2e3731
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/negative-token.rs
@@ -0,0 +1,18 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn neg_one(_input: TokenStream) -> TokenStream {
+    TokenTree::Literal(Literal::i32_suffixed(-1)).into()
+}
+
+#[proc_macro]
+pub fn neg_one_float(_input: TokenStream) -> TokenStream {
+    TokenTree::Literal(Literal::f32_suffixed(-1.0)).into()
+}
diff --git a/tests/ui/proc-macro/auxiliary/nested-macro-rules.rs b/tests/ui/proc-macro/auxiliary/nested-macro-rules.rs
new file mode 100644
index 00000000000..27676a5cb81
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/nested-macro-rules.rs
@@ -0,0 +1,16 @@
+pub struct FirstStruct;
+
+#[macro_export]
+macro_rules! outer_macro {
+    ($name:ident, $attr_struct_name:ident) => {
+        #[macro_export]
+        macro_rules! inner_macro {
+            ($bang_macro:ident, $attr_macro:ident) => {
+                $bang_macro!($name);
+                #[$attr_macro] struct $attr_struct_name {}
+            }
+        }
+    }
+}
+
+outer_macro!(FirstStruct, FirstAttrStruct);
diff --git a/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs b/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs
new file mode 100644
index 00000000000..ea5ff466570
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs
@@ -0,0 +1,25 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+use proc_macro::{TokenStream, quote};
+
+#[proc_macro_attribute]
+pub fn first_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    let recollected: TokenStream = input.into_iter().collect();
+    println!("First recollected: {:#?}", recollected);
+    quote! {
+        #[second_attr]
+        $recollected
+    }
+}
+
+#[proc_macro_attribute]
+pub fn second_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    let recollected: TokenStream = input.into_iter().collect();
+    println!("Second recollected: {:#?}", recollected);
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/not-joint.rs b/tests/ui/proc-macro/auxiliary/not-joint.rs
new file mode 100644
index 00000000000..e6c09f7628e
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/not-joint.rs
@@ -0,0 +1,30 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn tokens(input: TokenStream) -> TokenStream {
+    assert_nothing_joint(input);
+    TokenStream::new()
+}
+
+#[proc_macro_attribute]
+pub fn nothing(_: TokenStream, input: TokenStream) -> TokenStream {
+    assert_nothing_joint(input);
+    TokenStream::new()
+}
+
+fn assert_nothing_joint(s: TokenStream) {
+    for tt in s {
+        match tt {
+            TokenTree::Group(g) => assert_nothing_joint(g.stream()),
+            TokenTree::Punct(p) => assert_eq!(p.spacing(), Spacing::Alone),
+            _ => {}
+        }
+    }
+}
diff --git a/tests/ui/proc-macro/auxiliary/parent-source-spans.rs b/tests/ui/proc-macro/auxiliary/parent-source-spans.rs
new file mode 100644
index 00000000000..594f1088332
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/parent-source-spans.rs
@@ -0,0 +1,43 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_diagnostic, proc_macro_span)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span};
+
+fn lit_span(tt: TokenTree) -> (Span, String) {
+    match tt {
+        TokenTree::Literal(..) |
+        TokenTree::Group(..) => (tt.span(), tt.to_string().trim().into()),
+        _ => panic!("expected a literal in token tree, got: {:?}", tt)
+    }
+}
+
+#[proc_macro]
+pub fn parent_source_spans(input: TokenStream) -> TokenStream {
+    let mut tokens = input.into_iter();
+    let (sp1, str1) = lit_span(tokens.next().expect("first string"));
+    let _ = tokens.next();
+    let (sp2, str2) = lit_span(tokens.next().expect("second string"));
+
+    sp1.error(format!("first final: {}", str1)).emit();
+    sp2.error(format!("second final: {}", str2)).emit();
+
+    if let (Some(p1), Some(p2)) = (sp1.parent(), sp2.parent()) {
+        p1.error(format!("first parent: {}", str1)).emit();
+        p2.error(format!("second parent: {}", str2)).emit();
+
+        if let (Some(gp1), Some(gp2)) = (p1.parent(), p2.parent()) {
+            gp1.error(format!("first grandparent: {}", str1)).emit();
+            gp2.error(format!("second grandparent: {}", str2)).emit();
+        }
+    }
+
+    sp1.source().error(format!("first source: {}", str1)).emit();
+    sp2.source().error(format!("second source: {}", str2)).emit();
+
+    "ok".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs b/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs
new file mode 100644
index 00000000000..fc15bb9c59d
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/proc-macro-panic.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::{TokenStream, Ident, Span};
+
+#[proc_macro]
+pub fn panic_in_libproc_macro(_: TokenStream) -> TokenStream {
+    Ident::new("", Span::call_site());
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/raw-ident.rs b/tests/ui/proc-macro/auxiliary/raw-ident.rs
new file mode 100644
index 00000000000..9daee21aa17
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/raw-ident.rs
@@ -0,0 +1,35 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::{TokenStream, TokenTree, Ident, Punct, Spacing, Span};
+
+#[proc_macro]
+pub fn make_struct(input: TokenStream) -> TokenStream {
+    match input.into_iter().next().unwrap() {
+        TokenTree::Ident(ident) => {
+            vec![
+                TokenTree::Ident(Ident::new("struct", Span::call_site())),
+                TokenTree::Ident(Ident::new_raw(&ident.to_string(), Span::call_site())),
+                TokenTree::Punct(Punct::new(';', Spacing::Alone))
+            ].into_iter().collect()
+        }
+        _ => panic!()
+    }
+}
+
+#[proc_macro]
+pub fn make_bad_struct(input: TokenStream) -> TokenStream {
+    match input.into_iter().next().unwrap() {
+        TokenTree::Ident(ident) => {
+            vec![
+                TokenTree::Ident(Ident::new_raw("struct", Span::call_site())),
+                TokenTree::Ident(Ident::new(&ident.to_string(), Span::call_site())),
+                TokenTree::Punct(Punct::new(';', Spacing::Alone))
+            ].into_iter().collect()
+        }
+        _ => panic!()
+    }
+}
diff --git a/tests/ui/proc-macro/auxiliary/re-export.rs b/tests/ui/proc-macro/auxiliary/re-export.rs
new file mode 100644
index 00000000000..e8e9c9d3ecb
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/re-export.rs
@@ -0,0 +1,19 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn cause_ice(_: TokenStream) -> TokenStream {
+    "
+        enum IceCause {
+            Variant,
+        }
+
+        pub use IceCause::Variant;
+    ".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/recollect.rs b/tests/ui/proc-macro/auxiliary/recollect.rs
new file mode 100644
index 00000000000..d4494a5aff2
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/recollect.rs
@@ -0,0 +1,12 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn recollect(tokens: TokenStream) -> TokenStream {
+    tokens.into_iter().collect()
+}
diff --git a/tests/ui/proc-macro/auxiliary/resolved-located-at.rs b/tests/ui/proc-macro/auxiliary/resolved-located-at.rs
new file mode 100644
index 00000000000..db660824fbb
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/resolved-located-at.rs
@@ -0,0 +1,31 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_def_site)]
+#![feature(proc_macro_diagnostic)]
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn resolve_located_at(input: TokenStream) -> TokenStream {
+    match &*input.into_iter().collect::<Vec<_>>() {
+        [a, b, ..] => {
+            // The error is reported at input `a`.
+            let mut diag = Diagnostic::new(Level::Error, "expected error");
+            diag.set_spans(Span::def_site().located_at(a.span()));
+            diag.emit();
+
+            // Resolves to `struct S;` at def site, but the error is reported at input `b`.
+            let s = TokenTree::Ident(Ident::new("S", b.span().resolved_at(Span::def_site())));
+            quote!({
+                struct S;
+
+                $s
+            })
+        }
+        _ => panic!("unexpected input"),
+    }
+}
diff --git a/tests/ui/proc-macro/auxiliary/span-api-tests.rs b/tests/ui/proc-macro/auxiliary/span-api-tests.rs
new file mode 100644
index 00000000000..ad1e770a4dc
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/span-api-tests.rs
@@ -0,0 +1,45 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_span)]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+// Re-emits the input tokens by parsing them from strings
+#[proc_macro]
+pub fn reemit(input: TokenStream) -> TokenStream {
+    input.to_string().parse().unwrap()
+}
+
+#[proc_macro]
+pub fn assert_fake_source_file(input: TokenStream) -> TokenStream {
+    for tk in input {
+        let source_file = tk.span().source_file();
+        assert!(!source_file.is_real(), "Source file is real: {:?}", source_file);
+    }
+
+    "".parse().unwrap()
+}
+
+#[proc_macro]
+pub fn assert_source_file(input: TokenStream) -> TokenStream {
+    for tk in input {
+        let source_file = tk.span().source_file();
+        assert!(source_file.is_real(), "Source file is not real: {:?}", source_file);
+    }
+
+    "".parse().unwrap()
+}
+
+#[proc_macro]
+pub fn macro_stringify(input: TokenStream) -> TokenStream {
+    let mut tokens = input.into_iter();
+    let first_span = tokens.next().expect("first token").span();
+    let last_span = tokens.last().map(|x| x.span()).unwrap_or(first_span);
+    let span = first_span.join(last_span).expect("joined span");
+    let src = span.source_text().expect("source_text");
+    TokenTree::Literal(Literal::string(&src)).into()
+}
diff --git a/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs b/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs
new file mode 100644
index 00000000000..49292acfea7
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/span-from-proc-macro.rs
@@ -0,0 +1,49 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_quote)]
+#![feature(proc_macro_internals)] // FIXME - this shouldn't be necessary
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+extern crate custom_quote;
+
+use proc_macro::{quote, TokenStream};
+
+macro_rules! expand_to_quote {
+    () => {
+        quote! {
+            let bang_error: bool = 25;
+        }
+    }
+}
+
+#[proc_macro]
+pub fn error_from_bang(_input: TokenStream) -> TokenStream {
+    expand_to_quote!()
+}
+
+#[proc_macro]
+pub fn other_error_from_bang(_input: TokenStream) -> TokenStream {
+    custom_quote::custom_quote! {
+        my_ident
+    }
+}
+
+#[proc_macro_attribute]
+pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
+    quote! {
+        struct AttributeError {
+            field: MissingType
+        }
+    }
+}
+
+#[proc_macro_derive(ErrorFromDerive)]
+pub fn error_from_derive(_input: TokenStream) -> TokenStream {
+    quote! {
+        enum DeriveError {
+            Variant(OtherMissingType)
+        }
+    }
+}
diff --git a/tests/ui/proc-macro/auxiliary/span-test-macros.rs b/tests/ui/proc-macro/auxiliary/span-test-macros.rs
new file mode 100644
index 00000000000..9a78f0a8955
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/span-test-macros.rs
@@ -0,0 +1,9 @@
+#[macro_export]
+macro_rules! reemit_legacy {
+    ($($tok:tt)*) => ($($tok)*)
+}
+
+#[macro_export]
+macro_rules! say_hello_extern {
+    ($macname:ident) => ( $macname! { "Hello, world!" })
+}
diff --git a/tests/ui/proc-macro/auxiliary/subspan.rs b/tests/ui/proc-macro/auxiliary/subspan.rs
new file mode 100644
index 00000000000..f92adc04023
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/subspan.rs
@@ -0,0 +1,38 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_diagnostic, proc_macro_span)]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
+
+fn parse(input: TokenStream) -> Result<(), Diagnostic> {
+    if let Some(TokenTree::Literal(lit)) = input.into_iter().next() {
+        let mut spans = vec![];
+        let string = lit.to_string();
+        for hi in string.matches("hi") {
+            let index = hi.as_ptr() as usize - string.as_ptr() as usize;
+            let subspan = lit.subspan(index..(index + hi.len())).unwrap();
+            spans.push(subspan);
+        }
+
+        if !spans.is_empty() {
+            Err(Span::call_site().error("found 'hi's").span_note(spans, "here"))
+        } else {
+            Ok(())
+        }
+    } else {
+        Err(Span::call_site().error("invalid input: expected string literal"))
+    }
+}
+
+#[proc_macro]
+pub fn subspan(input: TokenStream) -> TokenStream {
+    if let Err(diag) = parse(input) {
+        diag.emit();
+    }
+
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/test-macros.rs b/tests/ui/proc-macro/auxiliary/test-macros.rs
new file mode 100644
index 00000000000..7a46aee462b
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/test-macros.rs
@@ -0,0 +1,180 @@
+// force-host
+// no-prefer-dynamic
+
+// Proc macros commonly used by tests.
+// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros.
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::{TokenStream, TokenTree};
+
+// Macro that return empty token stream.
+
+#[proc_macro]
+pub fn empty(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
+
+#[proc_macro_attribute]
+pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
+
+#[proc_macro_derive(Empty, attributes(empty_helper))]
+pub fn empty_derive(_: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
+
+// Macro that panics.
+
+#[proc_macro]
+pub fn panic_bang(_: TokenStream) -> TokenStream {
+    panic!("panic-bang");
+}
+
+#[proc_macro_attribute]
+pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+    panic!("panic-attr");
+}
+
+#[proc_macro_derive(Panic, attributes(panic_helper))]
+pub fn panic_derive(_: TokenStream) -> TokenStream {
+    panic!("panic-derive");
+}
+
+// Macros that return the input stream.
+
+#[proc_macro]
+pub fn identity(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(Identity, attributes(identity_helper))]
+pub fn identity_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
+// Macros that iterate and re-collect the input stream.
+
+#[proc_macro]
+pub fn recollect(input: TokenStream) -> TokenStream {
+    input.into_iter().collect()
+}
+
+#[proc_macro_attribute]
+pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+    input.into_iter().collect()
+}
+
+#[proc_macro_derive(Recollect, attributes(recollect_helper))]
+pub fn recollect_derive(input: TokenStream) -> TokenStream {
+    input.into_iter().collect()
+}
+
+// Macros that print their input in the original and re-collected forms (if they differ).
+
+fn print_helper(input: TokenStream, kind: &str) -> TokenStream {
+    print_helper_ext(input, kind, true)
+}
+
+fn deep_recollect(input: TokenStream) -> TokenStream {
+    input.into_iter().map(|tree| {
+        match tree {
+            TokenTree::Group(group) => {
+                let inner = deep_recollect(group.stream());
+                let mut new_group = TokenTree::Group(
+                    proc_macro::Group::new(group.delimiter(), inner)
+                );
+                new_group.set_span(group.span());
+                new_group
+            }
+            _ => tree,
+        }
+    }).collect()
+}
+
+fn print_helper_ext(input: TokenStream, kind: &str, debug: bool) -> TokenStream {
+    let input_display = format!("{}", input);
+    let input_debug = format!("{:#?}", input);
+    let recollected = input.clone().into_iter().collect();
+    let recollected_display = format!("{}", recollected);
+    let recollected_debug = format!("{:#?}", recollected);
+
+    let deep_recollected = deep_recollect(input);
+    let deep_recollected_display = format!("{}", deep_recollected);
+    let deep_recollected_debug = format!("{:#?}", deep_recollected);
+
+
+
+    println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display);
+    if recollected_display != input_display {
+        println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display);
+    }
+
+    if deep_recollected_display != recollected_display {
+        println!("PRINT-{} DEEP-RE-COLLECTED (DISPLAY): {}", kind, deep_recollected_display);
+    }
+
+    if debug {
+        println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug);
+        if recollected_debug != input_debug {
+            println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug);
+        }
+        if deep_recollected_debug != recollected_debug {
+            println!("PRINT-{} DEEP-RE-COLLETED (DEBUG): {}", kind, deep_recollected_debug);
+        }
+    }
+    recollected
+}
+
+#[proc_macro]
+pub fn print_bang(input: TokenStream) -> TokenStream {
+    print_helper(input, "BANG")
+}
+
+#[proc_macro]
+pub fn print_bang_consume(input: TokenStream) -> TokenStream {
+    print_helper(input, "BANG");
+    TokenStream::new()
+}
+
+#[proc_macro_attribute]
+pub fn print_attr(args: TokenStream, input: TokenStream) -> TokenStream {
+    let debug = match &args.into_iter().collect::<Vec<_>>()[..] {
+        [TokenTree::Ident(ident)] if ident.to_string() == "nodebug" => false,
+        _ => true,
+    };
+    print_helper_ext(input, "ATTR", debug)
+}
+
+#[proc_macro_attribute]
+pub fn print_attr_args(args: TokenStream, input: TokenStream) -> TokenStream {
+    print_helper(args, "ATTR_ARGS");
+    input
+}
+
+#[proc_macro_attribute]
+pub fn print_target_and_args(args: TokenStream, input: TokenStream) -> TokenStream {
+    print_helper(args, "ATTR_ARGS");
+    print_helper(input.clone(), "ATTR");
+    input
+}
+
+#[proc_macro_attribute]
+pub fn print_target_and_args_consume(args: TokenStream, input: TokenStream) -> TokenStream {
+    print_helper(args, "ATTR_ARGS");
+    print_helper(input.clone(), "ATTR");
+    TokenStream::new()
+}
+
+#[proc_macro_derive(Print, attributes(print_helper))]
+pub fn print_derive(input: TokenStream) -> TokenStream {
+    print_helper(input, "DERIVE");
+    TokenStream::new()
+}
diff --git a/tests/ui/proc-macro/auxiliary/three-equals.rs b/tests/ui/proc-macro/auxiliary/three-equals.rs
new file mode 100644
index 00000000000..e740e86e5d0
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/three-equals.rs
@@ -0,0 +1,49 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
+
+fn parse(input: TokenStream) -> Result<(), Diagnostic> {
+    let mut count = 0;
+    let mut last_span = Span::def_site();
+    for tree in input {
+        let span = tree.span();
+        if count >= 3 {
+            return Err(span.error(format!("expected EOF, found `{}`.", tree))
+                           .span_note(last_span, "last good input was here")
+                           .help("input must be: `===`"))
+        }
+
+        if let TokenTree::Punct(ref tt) = tree {
+            if tt.as_char() == '=' {
+                count += 1;
+                last_span = span;
+                continue
+            }
+        }
+        return Err(span.error(format!("expected `=`, found `{}`.", tree)));
+    }
+
+    if count < 3 {
+        return Err(Span::def_site()
+                       .error(format!("found {} equal signs, need exactly 3", count))
+                       .help("input must be: `===`"))
+    }
+
+    Ok(())
+}
+
+#[proc_macro]
+pub fn three_equals(input: TokenStream) -> TokenStream {
+    if let Err(diag) = parse(input) {
+        diag.emit();
+        return TokenStream::new();
+    }
+
+    "3".parse().unwrap()
+}
diff --git a/tests/ui/proc-macro/auxiliary/weird-hygiene.rs b/tests/ui/proc-macro/auxiliary/weird-hygiene.rs
new file mode 100644
index 00000000000..338e436df50
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/weird-hygiene.rs
@@ -0,0 +1,48 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Group};
+
+fn find_my_ident(tokens: TokenStream) -> Option<TokenStream> {
+    for token in tokens {
+        if let TokenTree::Ident(ident) = &token {
+            if ident.to_string() == "hidden_ident" {
+                return Some(vec![token].into_iter().collect())
+            }
+        } else if let TokenTree::Group(g) = token {
+            if let Some(stream) = find_my_ident(g.stream()) {
+                return Some(stream)
+            }
+        }
+    }
+    return None;
+}
+
+
+#[proc_macro_derive(WeirdDerive)]
+pub fn weird_derive(item: TokenStream) -> TokenStream {
+    let my_ident = find_my_ident(item).expect("Missing 'my_ident'!");
+    let tokens: TokenStream = "call_it!();".parse().unwrap();
+    let final_call = tokens.into_iter().map(|tree| {
+        if let TokenTree::Group(g) = tree {
+            return Group::new(g.delimiter(), my_ident.clone()).into()
+        } else {
+            return tree
+        }
+    }).collect();
+    final_call
+}
+
+#[proc_macro]
+pub fn recollect(item: TokenStream) -> TokenStream {
+    item.into_iter().collect()
+}
+
+#[proc_macro_attribute]
+pub fn recollect_attr(_attr: TokenStream, mut item: TokenStream) -> TokenStream {
+    item.into_iter().collect()
+}