summaryrefslogtreecommitdiffstats
path: root/src/test/ui/proc-macro
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/test/ui/proc-macro/add-impl.rs14
-rw-r--r--src/test/ui/proc-macro/allowed-attr-stmt-expr.rs78
-rw-r--r--src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout321
-rw-r--r--src/test/ui/proc-macro/ambiguous-builtin-attrs-test.rs20
-rw-r--r--src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr9
-rw-r--r--src/test/ui/proc-macro/ambiguous-builtin-attrs.rs39
-rw-r--r--src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr115
-rw-r--r--src/test/ui/proc-macro/amputate-span.fixed69
-rw-r--r--src/test/ui/proc-macro/amputate-span.rs65
-rw-r--r--src/test/ui/proc-macro/amputate-span.stderr25
-rw-r--r--src/test/ui/proc-macro/append-impl.rs22
-rw-r--r--src/test/ui/proc-macro/attr-args.rs13
-rw-r--r--src/test/ui/proc-macro/attr-cfg.rs27
-rw-r--r--src/test/ui/proc-macro/attr-complex-fn.rs26
-rw-r--r--src/test/ui/proc-macro/attr-complex-fn.stdout171
-rw-r--r--src/test/ui/proc-macro/attr-invalid-exprs.rs28
-rw-r--r--src/test/ui/proc-macro/attr-invalid-exprs.stderr28
-rw-r--r--src/test/ui/proc-macro/attr-on-trait.rs19
-rw-r--r--src/test/ui/proc-macro/attr-stmt-expr-rpass.rs36
-rw-r--r--src/test/ui/proc-macro/attr-stmt-expr.rs66
-rw-r--r--src/test/ui/proc-macro/attr-stmt-expr.stderr21
-rw-r--r--src/test/ui/proc-macro/attr-stmt-expr.stdout274
-rw-r--r--src/test/ui/proc-macro/attribute-after-derive.rs28
-rw-r--r--src/test/ui/proc-macro/attribute-after-derive.stdout192
-rw-r--r--src/test/ui/proc-macro/attribute-spans-preserved.rs10
-rw-r--r--src/test/ui/proc-macro/attribute-spans-preserved.stderr19
-rw-r--r--src/test/ui/proc-macro/attribute-spans-preserved.stdout1
-rw-r--r--src/test/ui/proc-macro/attribute-with-error.rs42
-rw-r--r--src/test/ui/proc-macro/attribute-with-error.stderr35
-rw-r--r--src/test/ui/proc-macro/attribute.rs73
-rw-r--r--src/test/ui/proc-macro/attribute.stderr104
-rw-r--r--src/test/ui/proc-macro/attributes-included.rs22
-rw-r--r--src/test/ui/proc-macro/attributes-included.stderr15
-rw-r--r--src/test/ui/proc-macro/attributes-on-definitions.rs12
-rw-r--r--src/test/ui/proc-macro/attributes-on-definitions.stderr10
-rw-r--r--src/test/ui/proc-macro/attributes-on-modules-fail.rs46
-rw-r--r--src/test/ui/proc-macro/attributes-on-modules-fail.stderr70
-rw-r--r--src/test/ui/proc-macro/attributes-on-modules.rs19
-rw-r--r--src/test/ui/proc-macro/auxiliary/add-impl.rs21
-rw-r--r--src/test/ui/proc-macro/auxiliary/amputate-span.rs14
-rw-r--r--src/test/ui/proc-macro/auxiliary/api/cmp.rs21
-rw-r--r--src/test/ui/proc-macro/auxiliary/api/mod.rs24
-rw-r--r--src/test/ui/proc-macro/auxiliary/api/parse.rs55
-rw-r--r--src/test/ui/proc-macro/auxiliary/append-impl.rs16
-rw-r--r--src/test/ui/proc-macro/auxiliary/assert-span-pos.rs37
-rw-r--r--src/test/ui/proc-macro/auxiliary/attr-args.rs28
-rw-r--r--src/test/ui/proc-macro/auxiliary/attr-cfg.rs21
-rw-r--r--src/test/ui/proc-macro/auxiliary/attr-on-trait.rs15
-rw-r--r--src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs51
-rw-r--r--src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs49
-rw-r--r--src/test/ui/proc-macro/auxiliary/attribute-spans-preserved.rs35
-rw-r--r--src/test/ui/proc-macro/auxiliary/attributes-included.rs150
-rw-r--r--src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs23
-rw-r--r--src/test/ui/proc-macro/auxiliary/bang-macro.rs17
-rw-r--r--src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/builtin-attrs.rs27
-rw-r--r--src/test/ui/proc-macro/auxiliary/call-deprecated.rs19
-rw-r--r--src/test/ui/proc-macro/auxiliary/call-site.rs27
-rw-r--r--src/test/ui/proc-macro/auxiliary/cond_plugin.rs38
-rw-r--r--src/test/ui/proc-macro/auxiliary/count_compound_ops.rs32
-rw-r--r--src/test/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs18
-rw-r--r--src/test/ui/proc-macro/auxiliary/custom-quote.rs32
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-a.rs15
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-atob.rs15
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-attr-cfg.rs14
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs17
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-b.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-bad.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-clona.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-ctod.rs15
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-foo.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs2
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs12
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs15
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-nothing.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-same-struct.rs21
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-two-attrs.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-union.rs18
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs17
-rw-r--r--src/test/ui/proc-macro/auxiliary/derive-unstable.rs14
-rw-r--r--src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs22
-rw-r--r--src/test/ui/proc-macro/auxiliary/double.rs16
-rw-r--r--src/test/ui/proc-macro/auxiliary/duplicate.rs32
-rw-r--r--src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs20
-rw-r--r--src/test/ui/proc-macro/auxiliary/empty-crate.rs5
-rw-r--r--src/test/ui/proc-macro/auxiliary/expand-expr.rs149
-rw-r--r--src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs22
-rw-r--r--src/test/ui/proc-macro/auxiliary/external-crate-var.rs40
-rw-r--r--src/test/ui/proc-macro/auxiliary/first-second.rs20
-rw-r--r--src/test/ui/proc-macro/auxiliary/gen-lifetime-token.rs25
-rw-r--r--src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs23
-rw-r--r--src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs12
-rw-r--r--src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs16
-rw-r--r--src/test/ui/proc-macro/auxiliary/generate-mod.rs58
-rw-r--r--src/test/ui/proc-macro/auxiliary/hygiene_example.rs7
-rw-r--r--src/test/ui/proc-macro/auxiliary/hygiene_example_codegen.rs27
-rw-r--r--src/test/ui/proc-macro/auxiliary/included-file.txt1
-rw-r--r--src/test/ui/proc-macro/auxiliary/invalid-punct-ident.rs28
-rw-r--r--src/test/ui/proc-macro/auxiliary/is-available.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-38586.rs11
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-39889.rs17
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-42708.rs18
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-50061.rs12
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-50493.rs21
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-59191.rs16
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-66286.rs14
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-75801.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-79242.rs16
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-79825.rs14
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-83510.rs19
-rw-r--r--src/test/ui/proc-macro/auxiliary/issue-91800-macro.rs26
-rw-r--r--src/test/ui/proc-macro/auxiliary/lifetimes-rpass.rs26
-rw-r--r--src/test/ui/proc-macro/auxiliary/lifetimes.rs20
-rw-r--r--src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs89
-rw-r--r--src/test/ui/proc-macro/auxiliary/make-macro.rs18
-rw-r--r--src/test/ui/proc-macro/auxiliary/meta-delim.rs12
-rw-r--r--src/test/ui/proc-macro/auxiliary/meta-macro.rs15
-rw-r--r--src/test/ui/proc-macro/auxiliary/mixed-site-span.rs40
-rw-r--r--src/test/ui/proc-macro/auxiliary/modify-ast.rs47
-rw-r--r--src/test/ui/proc-macro/auxiliary/multiple-derives.rs22
-rw-r--r--src/test/ui/proc-macro/auxiliary/multispan.rs37
-rw-r--r--src/test/ui/proc-macro/auxiliary/negative-token.rs18
-rw-r--r--src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs16
-rw-r--r--src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs25
-rw-r--r--src/test/ui/proc-macro/auxiliary/not-joint.rs30
-rw-r--r--src/test/ui/proc-macro/auxiliary/parent-source-spans.rs43
-rw-r--r--src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs13
-rw-r--r--src/test/ui/proc-macro/auxiliary/raw-ident.rs35
-rw-r--r--src/test/ui/proc-macro/auxiliary/recollect.rs12
-rw-r--r--src/test/ui/proc-macro/auxiliary/resolved-located-at.rs31
-rw-r--r--src/test/ui/proc-macro/auxiliary/span-api-tests.rs45
-rw-r--r--src/test/ui/proc-macro/auxiliary/span-from-proc-macro.rs49
-rw-r--r--src/test/ui/proc-macro/auxiliary/span-test-macros.rs9
-rw-r--r--src/test/ui/proc-macro/auxiliary/subspan.rs38
-rw-r--r--src/test/ui/proc-macro/auxiliary/test-macros.rs180
-rw-r--r--src/test/ui/proc-macro/auxiliary/three-equals.rs49
-rw-r--r--src/test/ui/proc-macro/auxiliary/weird-hygiene.rs48
-rw-r--r--src/test/ui/proc-macro/bang-macro.rs9
-rw-r--r--src/test/ui/proc-macro/break-token-spans.rs16
-rw-r--r--src/test/ui/proc-macro/break-token-spans.stderr21
-rw-r--r--src/test/ui/proc-macro/call-deprecated.rs34
-rw-r--r--src/test/ui/proc-macro/call-deprecated.stderr16
-rw-r--r--src/test/ui/proc-macro/call-site.rs10
-rw-r--r--src/test/ui/proc-macro/capture-macro-rules-invoke.rs57
-rw-r--r--src/test/ui/proc-macro/capture-macro-rules-invoke.stdout324
-rw-r--r--src/test/ui/proc-macro/capture-unglued-token.rs20
-rw-r--r--src/test/ui/proc-macro/capture-unglued-token.stdout28
-rw-r--r--src/test/ui/proc-macro/cfg-eval-fail.rs7
-rw-r--r--src/test/ui/proc-macro/cfg-eval-fail.stderr8
-rw-r--r--src/test/ui/proc-macro/cfg-eval-inner.rs39
-rw-r--r--src/test/ui/proc-macro/cfg-eval-inner.stdout247
-rw-r--r--src/test/ui/proc-macro/cfg-eval.rs37
-rw-r--r--src/test/ui/proc-macro/cfg-eval.stdout150
-rw-r--r--src/test/ui/proc-macro/count_compound_ops.rs9
-rw-r--r--src/test/ui/proc-macro/crate-attrs-multiple.rs14
-rw-r--r--src/test/ui/proc-macro/crate-var.rs61
-rw-r--r--src/test/ui/proc-macro/crt-static.rs24
-rw-r--r--src/test/ui/proc-macro/custom-attr-only-one-derive.rs16
-rw-r--r--src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs15
-rw-r--r--src/test/ui/proc-macro/debug/dump-debug-span-debug.rs41
-rw-r--r--src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr166
-rw-r--r--src/test/ui/proc-macro/debug/dump-debug.rs40
-rw-r--r--src/test/ui/proc-macro/debug/dump-debug.stderr166
-rw-r--r--src/test/ui/proc-macro/define-two.rs18
-rw-r--r--src/test/ui/proc-macro/define-two.stderr14
-rw-r--r--src/test/ui/proc-macro/derive-attr-cfg.rs17
-rw-r--r--src/test/ui/proc-macro/derive-b.rs19
-rw-r--r--src/test/ui/proc-macro/derive-bad.rs11
-rw-r--r--src/test/ui/proc-macro/derive-bad.stderr28
-rw-r--r--src/test/ui/proc-macro/derive-expand-order.rs14
-rw-r--r--src/test/ui/proc-macro/derive-expand-order.stdout5
-rw-r--r--src/test/ui/proc-macro/derive-helper-configured.rs18
-rw-r--r--src/test/ui/proc-macro/derive-helper-legacy-limits.rs21
-rw-r--r--src/test/ui/proc-macro/derive-helper-legacy-limits.stderr8
-rw-r--r--src/test/ui/proc-macro/derive-helper-legacy-spurious.rs12
-rw-r--r--src/test/ui/proc-macro/derive-helper-legacy-spurious.stderr22
-rw-r--r--src/test/ui/proc-macro/derive-helper-shadowed.rs16
-rw-r--r--src/test/ui/proc-macro/derive-helper-shadowing-2.rs16
-rw-r--r--src/test/ui/proc-macro/derive-helper-shadowing.rs56
-rw-r--r--src/test/ui/proc-macro/derive-helper-shadowing.stderr89
-rw-r--r--src/test/ui/proc-macro/derive-helper-vs-legacy.rs12
-rw-r--r--src/test/ui/proc-macro/derive-in-mod.rs13
-rw-r--r--src/test/ui/proc-macro/derive-multiple-with-packed.rs11
-rw-r--r--src/test/ui/proc-macro/derive-same-struct.rs15
-rw-r--r--src/test/ui/proc-macro/derive-same-struct.stdout1
-rw-r--r--src/test/ui/proc-macro/derive-still-gated.rs9
-rw-r--r--src/test/ui/proc-macro/derive-still-gated.stderr8
-rw-r--r--src/test/ui/proc-macro/derive-test.rs22
-rw-r--r--src/test/ui/proc-macro/derive-two-attrs.rs15
-rw-r--r--src/test/ui/proc-macro/derive-union.rs17
-rw-r--r--src/test/ui/proc-macro/disappearing-resolution.rs22
-rw-r--r--src/test/ui/proc-macro/disappearing-resolution.stderr26
-rw-r--r--src/test/ui/proc-macro/doc-comment-preserved.rs24
-rw-r--r--src/test/ui/proc-macro/doc-comment-preserved.stdout54
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.rs27
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.stdout80
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-62325.rs26
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-62325.stdout110
-rw-r--r--src/test/ui/proc-macro/dollar-crate.rs40
-rw-r--r--src/test/ui/proc-macro/dollar-crate.stdout240
-rw-r--r--src/test/ui/proc-macro/edition-imports-2018.rs24
-rw-r--r--src/test/ui/proc-macro/empty-crate.rs9
-rw-r--r--src/test/ui/proc-macro/empty-where-clause.rs18
-rw-r--r--src/test/ui/proc-macro/empty-where-clause.stderr21
-rw-r--r--src/test/ui/proc-macro/expand-expr.rs121
-rw-r--r--src/test/ui/proc-macro/expand-expr.stderr55
-rw-r--r--src/test/ui/proc-macro/expand-to-derive.rs34
-rw-r--r--src/test/ui/proc-macro/expand-to-derive.stdout104
-rw-r--r--src/test/ui/proc-macro/expand-to-unstable-2.rs17
-rw-r--r--src/test/ui/proc-macro/expand-to-unstable-2.stderr10
-rw-r--r--src/test/ui/proc-macro/expand-to-unstable.rs14
-rw-r--r--src/test/ui/proc-macro/expand-to-unstable.stderr12
-rw-r--r--src/test/ui/proc-macro/expand-with-a-macro.rs21
-rw-r--r--src/test/ui/proc-macro/export-macro.rs11
-rw-r--r--src/test/ui/proc-macro/export-macro.stderr8
-rw-r--r--src/test/ui/proc-macro/exports.rs15
-rw-r--r--src/test/ui/proc-macro/exports.stderr26
-rw-r--r--src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs37
-rw-r--r--src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout540
-rw-r--r--src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs7
-rw-r--r--src/test/ui/proc-macro/gen-lifetime-token.rs11
-rw-r--r--src/test/ui/proc-macro/gen-macro-rules-hygiene.rs23
-rw-r--r--src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr32
-rw-r--r--src/test/ui/proc-macro/gen-macro-rules.rs13
-rw-r--r--src/test/ui/proc-macro/generate-dollar-ident.rs18
-rw-r--r--src/test/ui/proc-macro/generate-mod.rs33
-rw-r--r--src/test/ui/proc-macro/generate-mod.stderr164
-rw-r--r--src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs13
-rw-r--r--src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr35
-rw-r--r--src/test/ui/proc-macro/helper-attr-blocked-by-import.rs28
-rw-r--r--src/test/ui/proc-macro/hygiene_example.rs16
-rw-r--r--src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs15
-rw-r--r--src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr14
-rw-r--r--src/test/ui/proc-macro/import.rs8
-rw-r--r--src/test/ui/proc-macro/import.stderr9
-rw-r--r--src/test/ui/proc-macro/inert-attribute-order.rs23
-rw-r--r--src/test/ui/proc-macro/inert-attribute-order.stdout7
-rw-r--r--src/test/ui/proc-macro/inner-attr-non-inline-mod.rs18
-rw-r--r--src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr40
-rw-r--r--src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout76
-rw-r--r--src/test/ui/proc-macro/inner-attrs.rs86
-rw-r--r--src/test/ui/proc-macro/inner-attrs.stderr26
-rw-r--r--src/test/ui/proc-macro/inner-attrs.stdout956
-rw-r--r--src/test/ui/proc-macro/input-interpolated.rs29
-rw-r--r--src/test/ui/proc-macro/input-interpolated.stdout59
-rw-r--r--src/test/ui/proc-macro/invalid-attributes.rs26
-rw-r--r--src/test/ui/proc-macro/invalid-attributes.stderr38
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-1.rs8
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-1.stderr10
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-2.rs8
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-2.stderr10
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-3.rs8
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-3.stderr10
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-4.rs12
-rw-r--r--src/test/ui/proc-macro/invalid-punct-ident-4.stderr25
-rw-r--r--src/test/ui/proc-macro/is-available.rs15
-rw-r--r--src/test/ui/proc-macro/issue-36935.rs13
-rw-r--r--src/test/ui/proc-macro/issue-36935.stderr22
-rw-r--r--src/test/ui/proc-macro/issue-37788.rs9
-rw-r--r--src/test/ui/proc-macro/issue-37788.stderr17
-rw-r--r--src/test/ui/proc-macro/issue-38586.rs9
-rw-r--r--src/test/ui/proc-macro/issue-38586.stderr11
-rw-r--r--src/test/ui/proc-macro/issue-39889.rs12
-rw-r--r--src/test/ui/proc-macro/issue-41211.rs16
-rw-r--r--src/test/ui/proc-macro/issue-41211.stderr22
-rw-r--r--src/test/ui/proc-macro/issue-42708.rs26
-rw-r--r--src/test/ui/proc-macro/issue-50061.rs23
-rw-r--r--src/test/ui/proc-macro/issue-50493.rs13
-rw-r--r--src/test/ui/proc-macro/issue-50493.stderr9
-rw-r--r--src/test/ui/proc-macro/issue-53481.rs22
-rw-r--r--src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs10
-rw-r--r--src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr4
-rw-r--r--src/test/ui/proc-macro/issue-66286.rs13
-rw-r--r--src/test/ui/proc-macro/issue-66286.stderr14
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs19
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr91
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout22
-rw-r--r--src/test/ui/proc-macro/issue-75734-pp-paren.rs26
-rw-r--r--src/test/ui/proc-macro/issue-75734-pp-paren.stdout134
-rw-r--r--src/test/ui/proc-macro/issue-75801.rs19
-rw-r--r--src/test/ui/proc-macro/issue-75801.stderr12
-rw-r--r--src/test/ui/proc-macro/issue-75930-derive-cfg.rs74
-rw-r--r--src/test/ui/proc-macro/issue-75930-derive-cfg.stderr27
-rw-r--r--src/test/ui/proc-macro/issue-75930-derive-cfg.stdout1904
-rw-r--r--src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs16
-rw-r--r--src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout62
-rw-r--r--src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs12
-rw-r--r--src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr10
-rw-r--r--src/test/ui/proc-macro/issue-78675-captured-inner-attrs.rs32
-rw-r--r--src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout87
-rw-r--r--src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs34
-rw-r--r--src/test/ui/proc-macro/issue-79825.rs10
-rw-r--r--src/test/ui/proc-macro/issue-80760-empty-stmt.rs26
-rw-r--r--src/test/ui/proc-macro/issue-80760-empty-stmt.stdout14
-rw-r--r--src/test/ui/proc-macro/issue-81007-item-attrs.rs31
-rw-r--r--src/test/ui/proc-macro/issue-81007-item-attrs.stdout99
-rw-r--r--src/test/ui/proc-macro/issue-81543-item-parse-err.rs14
-rw-r--r--src/test/ui/proc-macro/issue-81543-item-parse-err.stderr8
-rw-r--r--src/test/ui/proc-macro/issue-81555.rs15
-rw-r--r--src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs10
-rw-r--r--src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr8
-rw-r--r--src/test/ui/proc-macro/issue-83510.rs11
-rw-r--r--src/test/ui/proc-macro/issue-83510.stderr38
-rw-r--r--src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed12
-rw-r--r--src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs12
-rw-r--r--src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr17
-rw-r--r--src/test/ui/proc-macro/issue-91800.rs16
-rw-r--r--src/test/ui/proc-macro/issue-91800.stderr56
-rw-r--r--src/test/ui/proc-macro/item-error.rs15
-rw-r--r--src/test/ui/proc-macro/item-error.stderr15
-rw-r--r--src/test/ui/proc-macro/keep-expr-tokens.rs24
-rw-r--r--src/test/ui/proc-macro/keep-expr-tokens.stderr15
-rw-r--r--src/test/ui/proc-macro/keep-expr-tokens.stdout46
-rw-r--r--src/test/ui/proc-macro/lifetimes-rpass.rs26
-rw-r--r--src/test/ui/proc-macro/lifetimes.rs9
-rw-r--r--src/test/ui/proc-macro/lifetimes.stderr13
-rw-r--r--src/test/ui/proc-macro/lints_in_proc_macros.rs14
-rw-r--r--src/test/ui/proc-macro/lints_in_proc_macros.stderr11
-rw-r--r--src/test/ui/proc-macro/load-panic-backtrace.rs14
-rw-r--r--src/test/ui/proc-macro/load-panic-backtrace.stderr11
-rw-r--r--src/test/ui/proc-macro/load-panic.rs10
-rw-r--r--src/test/ui/proc-macro/load-panic.stderr10
-rw-r--r--src/test/ui/proc-macro/load-two.rs23
-rw-r--r--src/test/ui/proc-macro/macro-brackets.rs14
-rw-r--r--src/test/ui/proc-macro/macro-brackets.stderr14
-rw-r--r--src/test/ui/proc-macro/macro-crate-multi-decorator.rs41
-rw-r--r--src/test/ui/proc-macro/macro-namespace-reserved-2.rs57
-rw-r--r--src/test/ui/proc-macro/macro-namespace-reserved-2.stderr132
-rw-r--r--src/test/ui/proc-macro/macro-namespace-reserved.rs38
-rw-r--r--src/test/ui/proc-macro/macro-namespace-reserved.stderr47
-rw-r--r--src/test/ui/proc-macro/macro-quote-cond.rs46
-rw-r--r--src/test/ui/proc-macro/macro-rules-derive-cfg.rs31
-rw-r--r--src/test/ui/proc-macro/macro-rules-derive-cfg.stdout171
-rw-r--r--src/test/ui/proc-macro/macro-rules-derive.rs19
-rw-r--r--src/test/ui/proc-macro/macro-rules-derive.stderr14
-rw-r--r--src/test/ui/proc-macro/macro-use-attr.rs12
-rw-r--r--src/test/ui/proc-macro/macro-use-bang.rs9
-rw-r--r--src/test/ui/proc-macro/macros-in-extern-derive.rs6
-rw-r--r--src/test/ui/proc-macro/macros-in-extern-derive.stderr11
-rw-r--r--src/test/ui/proc-macro/macros-in-extern.rs24
-rw-r--r--src/test/ui/proc-macro/macros-in-type.rs11
-rw-r--r--src/test/ui/proc-macro/meta-delim.rs12
-rw-r--r--src/test/ui/proc-macro/meta-macro-hygiene.rs30
-rw-r--r--src/test/ui/proc-macro/meta-macro-hygiene.stdout69
-rw-r--r--src/test/ui/proc-macro/meta-macro.rs14
-rw-r--r--src/test/ui/proc-macro/meta-macro.stdout3
-rw-r--r--src/test/ui/proc-macro/mixed-site-span.rs24
-rw-r--r--src/test/ui/proc-macro/mixed-site-span.stderr34
-rw-r--r--src/test/ui/proc-macro/modify-ast.rs26
-rw-r--r--src/test/ui/proc-macro/module.rs1
-rw-r--r--src/test/ui/proc-macro/module_with_attrs.rs4
-rw-r--r--src/test/ui/proc-macro/multispan.rs25
-rw-r--r--src/test/ui/proc-macro/multispan.stderr93
-rw-r--r--src/test/ui/proc-macro/negative-token.rs11
-rw-r--r--src/test/ui/proc-macro/nested-derive-cfg.rs23
-rw-r--r--src/test/ui/proc-macro/nested-derive-cfg.stdout81
-rw-r--r--src/test/ui/proc-macro/nested-item-spans.rs23
-rw-r--r--src/test/ui/proc-macro/nested-item-spans.stderr19
-rw-r--r--src/test/ui/proc-macro/nested-macro-rules.rs23
-rw-r--r--src/test/ui/proc-macro/nested-macro-rules.stdout46
-rw-r--r--src/test/ui/proc-macro/nested-nonterminal-tokens.rs26
-rw-r--r--src/test/ui/proc-macro/nested-nonterminal-tokens.stdout60
-rw-r--r--src/test/ui/proc-macro/no-macro-use-attr.rs10
-rw-r--r--src/test/ui/proc-macro/no-macro-use-attr.stderr20
-rw-r--r--src/test/ui/proc-macro/no-missing-docs.rs16
-rw-r--r--src/test/ui/proc-macro/nodelim-groups.rs22
-rw-r--r--src/test/ui/proc-macro/nodelim-groups.stdout167
-rw-r--r--src/test/ui/proc-macro/non-root.rs15
-rw-r--r--src/test/ui/proc-macro/non-root.stderr8
-rw-r--r--src/test/ui/proc-macro/nonterminal-expansion.rs37
-rw-r--r--src/test/ui/proc-macro/nonterminal-expansion.stdout42
-rw-r--r--src/test/ui/proc-macro/nonterminal-recollect-attr.rs21
-rw-r--r--src/test/ui/proc-macro/nonterminal-recollect-attr.stdout66
-rw-r--r--src/test/ui/proc-macro/nonterminal-token-hygiene.rs34
-rw-r--r--src/test/ui/proc-macro/nonterminal-token-hygiene.stdout92
-rw-r--r--src/test/ui/proc-macro/not-joint.rs24
-rw-r--r--src/test/ui/proc-macro/out-of-line-mod.rs13
-rw-r--r--src/test/ui/proc-macro/outer/inner.rs1
-rw-r--r--src/test/ui/proc-macro/parent-source-spans.rs53
-rw-r--r--src/test/ui/proc-macro/parent-source-spans.stderr189
-rw-r--r--src/test/ui/proc-macro/pretty-print-tts.rs20
-rw-r--r--src/test/ui/proc-macro/pretty-print-tts.stdout102
-rw-r--r--src/test/ui/proc-macro/proc-macro-attributes.rs22
-rw-r--r--src/test/ui/proc-macro/proc-macro-attributes.stderr130
-rw-r--r--src/test/ui/proc-macro/proc-macro-deprecated-attr.rs16
-rw-r--r--src/test/ui/proc-macro/proc-macro-gates.rs53
-rw-r--r--src/test/ui/proc-macro/proc-macro-gates.stderr91
-rw-r--r--src/test/ui/proc-macro/proc-macro-gates2.rs24
-rw-r--r--src/test/ui/proc-macro/proc-macro-gates2.stderr14
-rw-r--r--src/test/ui/proc-macro/pub-at-crate-root.rs22
-rw-r--r--src/test/ui/proc-macro/pub-at-crate-root.stderr20
-rw-r--r--src/test/ui/proc-macro/quote-debug.rs18
-rw-r--r--src/test/ui/proc-macro/quote-debug.stdout47
-rw-r--r--src/test/ui/proc-macro/raw-ident.rs16
-rw-r--r--src/test/ui/proc-macro/raw-ident.stderr10
-rw-r--r--src/test/ui/proc-macro/reserved-macro-names.rs19
-rw-r--r--src/test/ui/proc-macro/reserved-macro-names.stderr14
-rw-r--r--src/test/ui/proc-macro/resolve-error.rs62
-rw-r--r--src/test/ui/proc-macro/resolve-error.stderr132
-rw-r--r--src/test/ui/proc-macro/resolved-located-at.rs10
-rw-r--r--src/test/ui/proc-macro/resolved-located-at.stderr21
-rw-r--r--src/test/ui/proc-macro/shadow.rs8
-rw-r--r--src/test/ui/proc-macro/shadow.stderr14
-rw-r--r--src/test/ui/proc-macro/signature.rs13
-rw-r--r--src/test/ui/proc-macro/signature.stderr20
-rw-r--r--src/test/ui/proc-macro/smoke.rs20
-rw-r--r--src/test/ui/proc-macro/span-absolute-posititions.rs24
-rw-r--r--src/test/ui/proc-macro/span-absolute-posititions.stderr14
-rw-r--r--src/test/ui/proc-macro/span-api-tests.rs61
-rw-r--r--src/test/ui/proc-macro/span-from-proc-macro.rs17
-rw-r--r--src/test/ui/proc-macro/span-from-proc-macro.stderr62
-rw-r--r--src/test/ui/proc-macro/span-preservation.rs57
-rw-r--r--src/test/ui/proc-macro/span-preservation.stderr72
-rw-r--r--src/test/ui/proc-macro/struct-field-macro.rs18
-rw-r--r--src/test/ui/proc-macro/subspan.rs26
-rw-r--r--src/test/ui/proc-macro/subspan.stderr106
-rw-r--r--src/test/ui/proc-macro/test.rs12
-rw-r--r--src/test/ui/proc-macro/three-equals.rs25
-rw-r--r--src/test/ui/proc-macro/three-equals.stderr49
-rw-r--r--src/test/ui/proc-macro/trailing-plus.rs14
-rw-r--r--src/test/ui/proc-macro/trailing-plus.stdout57
-rw-r--r--src/test/ui/proc-macro/trait-fn-args-2015.rs16
-rw-r--r--src/test/ui/proc-macro/two-crate-types-1.rs7
-rw-r--r--src/test/ui/proc-macro/two-crate-types-1.stderr4
-rw-r--r--src/test/ui/proc-macro/two-crate-types-2.rs3
-rw-r--r--src/test/ui/proc-macro/two-crate-types-2.stderr4
-rw-r--r--src/test/ui/proc-macro/unsafe-foreign-mod.rs14
-rw-r--r--src/test/ui/proc-macro/unsafe-mod.rs13
-rw-r--r--src/test/ui/proc-macro/visibility-path.rs25
-rw-r--r--src/test/ui/proc-macro/visibility-path.stderr14
-rw-r--r--src/test/ui/proc-macro/weird-braces.rs23
-rw-r--r--src/test/ui/proc-macro/weird-braces.stdout524
-rw-r--r--src/test/ui/proc-macro/weird-hygiene.rs46
-rw-r--r--src/test/ui/proc-macro/weird-hygiene.stderr25
434 files changed, 18620 insertions, 0 deletions
diff --git a/src/test/ui/proc-macro/add-impl.rs b/src/test/ui/proc-macro/add-impl.rs
new file mode 100644
index 000000000..ff2897a5e
--- /dev/null
+++ b/src/test/ui/proc-macro/add-impl.rs
@@ -0,0 +1,14 @@
+// run-pass
+// aux-build:add-impl.rs
+
+#[macro_use]
+extern crate add_impl;
+
+#[derive(AddImpl)]
+struct B;
+
+fn main() {
+ B.foo();
+ foo();
+ bar::foo();
+}
diff --git a/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs b/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs
new file mode 100644
index 000000000..25243aeef
--- /dev/null
+++ b/src/test/ui/proc-macro/allowed-attr-stmt-expr.rs
@@ -0,0 +1,78 @@
+// aux-build:attr-stmt-expr.rs
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+// check-pass
+
+#![feature(proc_macro_hygiene)]
+#![feature(stmt_expr_attributes)]
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate attr_stmt_expr;
+extern crate test_macros;
+use attr_stmt_expr::{expect_let, expect_my_macro_stmt, expect_expr, expect_my_macro_expr};
+use test_macros::print_attr;
+
+// We don't use `std::println` so that we avoid loading hygiene
+// information from libstd, which would affect the SyntaxContext ids
+macro_rules! my_macro {
+ ($($tt:tt)*) => { () }
+}
+
+
+fn print_str(string: &'static str) {
+ // macros are handled a bit differently
+ #[expect_my_macro_expr]
+ my_macro!("{}", string)
+}
+
+macro_rules! make_stmt {
+ ($stmt:stmt) => {
+ #[print_attr]
+ #[rustc_dummy]
+ $stmt; // This semicolon is *not* passed to the macro,
+ // since `$stmt` is already a statement.
+ }
+}
+
+macro_rules! second_make_stmt {
+ ($stmt:stmt) => {
+ make_stmt!($stmt);
+ }
+}
+
+// The macro will see a semicolon here
+#[print_attr]
+struct ItemWithSemi;
+
+
+fn main() {
+ make_stmt!(struct Foo {});
+
+ #[print_attr]
+ #[expect_let]
+ let string = "Hello, world!";
+
+ #[print_attr]
+ #[expect_my_macro_stmt]
+ my_macro!("{}", string);
+
+ #[print_attr]
+ second_make_stmt!(#[allow(dead_code)] struct Bar {});
+
+ #[print_attr]
+ #[rustc_dummy]
+ struct Other {};
+
+ // The macro also sees a semicolon,
+ // for consistency with the `ItemWithSemi` case above.
+ #[print_attr]
+ #[rustc_dummy]
+ struct NonBracedStruct;
+
+ #[expect_expr]
+ print_str("string")
+}
diff --git a/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout b/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout
new file mode 100644
index 000000000..091862de3
--- /dev/null
+++ b/src/test/ui/proc-macro/allowed-attr-stmt-expr.stdout
@@ -0,0 +1,321 @@
+PRINT-ATTR INPUT (DISPLAY): struct ItemWithSemi ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/allowed-attr-stmt-expr.rs:49:1: 49:7 (#0),
+ },
+ Ident {
+ ident: "ItemWithSemi",
+ span: $DIR/allowed-attr-stmt-expr.rs:49:8: 49:20 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:49:20: 49:21 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:35:9: 35:10 (#11),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/allowed-attr-stmt-expr.rs:35:11: 35:22 (#11),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:35:10: 35:23 (#11),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/allowed-attr-stmt-expr.rs:53:16: 53:22 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/allowed-attr-stmt-expr.rs:53:23: 53:26 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/allowed-attr-stmt-expr.rs:53:27: 53:29 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:56:5: 56:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "expect_let",
+ span: $DIR/allowed-attr-stmt-expr.rs:56:7: 56:17 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:56:6: 56:18 (#0),
+ },
+ Ident {
+ ident: "let",
+ span: $DIR/allowed-attr-stmt-expr.rs:57:5: 57:8 (#0),
+ },
+ Ident {
+ ident: "string",
+ span: $DIR/allowed-attr-stmt-expr.rs:57:9: 57:15 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:57:16: 57:17 (#0),
+ },
+ Literal {
+ kind: Str,
+ symbol: "Hello, world!",
+ suffix: None,
+ span: $DIR/allowed-attr-stmt-expr.rs:57:18: 57:33 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:57:33: 57:34 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:60:5: 60:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "expect_my_macro_stmt",
+ span: $DIR/allowed-attr-stmt-expr.rs:60:7: 60:27 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:60:6: 60:28 (#0),
+ },
+ Ident {
+ ident: "my_macro",
+ span: $DIR/allowed-attr-stmt-expr.rs:61:5: 61:13 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:61:13: 61:14 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Literal {
+ kind: Str,
+ symbol: "{}",
+ suffix: None,
+ span: $DIR/allowed-attr-stmt-expr.rs:61:15: 61:19 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:61:19: 61:20 (#0),
+ },
+ Ident {
+ ident: "string",
+ span: $DIR/allowed-attr-stmt-expr.rs:61:21: 61:27 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:61:14: 61:28 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:61:28: 61:29 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "second_make_stmt",
+ span: $DIR/allowed-attr-stmt-expr.rs:64:5: 64:21 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:64:21: 64:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:64:23: 64:24 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/allowed-attr-stmt-expr.rs:64:25: 64:30 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "dead_code",
+ span: $DIR/allowed-attr-stmt-expr.rs:64:31: 64:40 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:64:30: 64:41 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:64:24: 64:42 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/allowed-attr-stmt-expr.rs:64:43: 64:49 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/allowed-attr-stmt-expr.rs:64:50: 64:53 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/allowed-attr-stmt-expr.rs:64:54: 64:56 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:64:22: 64:57 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:64:57: 64:58 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:35:9: 35:10 (#32),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/allowed-attr-stmt-expr.rs:35:11: 35:22 (#32),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:35:10: 35:23 (#32),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:64:23: 64:24 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/allowed-attr-stmt-expr.rs:64:25: 64:30 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "dead_code",
+ span: $DIR/allowed-attr-stmt-expr.rs:64:31: 64:40 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:64:30: 64:41 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:64:24: 64:42 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/allowed-attr-stmt-expr.rs:64:43: 64:49 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/allowed-attr-stmt-expr.rs:64:50: 64:53 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/allowed-attr-stmt-expr.rs:64:54: 64:56 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:67:5: 67:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/allowed-attr-stmt-expr.rs:67:7: 67:18 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:67:6: 67:19 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/allowed-attr-stmt-expr.rs:68:5: 68:11 (#0),
+ },
+ Ident {
+ ident: "Other",
+ span: $DIR/allowed-attr-stmt-expr.rs:68:12: 68:17 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/allowed-attr-stmt-expr.rs:68:18: 68:20 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct NonBracedStruct ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:73:5: 73:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/allowed-attr-stmt-expr.rs:73:7: 73:18 (#0),
+ },
+ ],
+ span: $DIR/allowed-attr-stmt-expr.rs:73:6: 73:19 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/allowed-attr-stmt-expr.rs:74:5: 74:11 (#0),
+ },
+ Ident {
+ ident: "NonBracedStruct",
+ span: $DIR/allowed-attr-stmt-expr.rs:74:12: 74:27 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/allowed-attr-stmt-expr.rs:74:27: 74:28 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.rs
new file mode 100644
index 000000000..6a47e50f6
--- /dev/null
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.rs
@@ -0,0 +1,20 @@
+// aux-build:builtin-attrs.rs
+// compile-flags:--test
+
+#![feature(decl_macro, test)]
+
+extern crate test;
+extern crate builtin_attrs;
+use builtin_attrs::{test, bench};
+
+#[test] // OK, shadowed
+fn test() {}
+
+#[bench] // OK, shadowed
+fn bench(b: &mut test::Bencher) {}
+
+fn not_main() {
+ Test;
+ Bench;
+ NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
+}
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr
new file mode 100644
index 000000000..316eb636b
--- /dev/null
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs-test.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `NonExistent` in this scope
+ --> $DIR/ambiguous-builtin-attrs-test.rs:19:5
+ |
+LL | NonExistent;
+ | ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
new file mode 100644
index 000000000..695ea69c8
--- /dev/null
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
@@ -0,0 +1,39 @@
+// edition:2018
+// aux-build:builtin-attrs.rs
+#![feature(decl_macro)] //~ ERROR `feature` is ambiguous
+
+extern crate builtin_attrs;
+use builtin_attrs::*;
+use builtin_attrs::{bench, test};
+
+#[repr(C)] //~ ERROR `repr` is ambiguous
+struct S;
+#[cfg_attr(all(), repr(C))] //~ ERROR `repr` is ambiguous
+struct SCond;
+
+#[test] // OK, shadowed
+fn test() {}
+
+#[bench] // OK, shadowed
+fn bench() {}
+
+fn non_macro_expanded_location<#[repr(C)] T>() {
+ //~^ ERROR `repr` is ambiguous
+ //~| ERROR attribute should be applied to a struct, enum, or union
+ match 0u8 {
+ #[repr(C)]
+ //~^ ERROR `repr` is ambiguous
+ //~| ERROR attribute should be applied to a struct, enum, or union
+ _ => {}
+ }
+}
+
+fn main() {
+ Test;
+ Bench;
+ NonExistent; //~ ERROR cannot find value `NonExistent` in this scope
+}
+
+use deny as allow;
+#[allow(unused)] //~ ERROR `allow` is ambiguous
+fn builtin_renamed() {}
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
new file mode 100644
index 000000000..0f4ddc065
--- /dev/null
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
@@ -0,0 +1,115 @@
+error[E0425]: cannot find value `NonExistent` in this scope
+ --> $DIR/ambiguous-builtin-attrs.rs:34:5
+ |
+LL | NonExistent;
+ | ^^^^^^^^^^^ not found in this scope
+
+error[E0659]: `repr` is ambiguous
+ --> $DIR/ambiguous-builtin-attrs.rs:9:3
+ |
+LL | #[repr(C)]
+ | ^^^^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a builtin attribute
+ = note: `repr` could refer to a built-in attribute
+note: `repr` could also refer to the attribute macro imported here
+ --> $DIR/ambiguous-builtin-attrs.rs:6:5
+ |
+LL | use builtin_attrs::*;
+ | ^^^^^^^^^^^^^^^^
+ = help: use `crate::repr` to refer to this attribute macro unambiguously
+
+error[E0659]: `repr` is ambiguous
+ --> $DIR/ambiguous-builtin-attrs.rs:11:19
+ |
+LL | #[cfg_attr(all(), repr(C))]
+ | ^^^^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a builtin attribute
+ = note: `repr` could refer to a built-in attribute
+note: `repr` could also refer to the attribute macro imported here
+ --> $DIR/ambiguous-builtin-attrs.rs:6:5
+ |
+LL | use builtin_attrs::*;
+ | ^^^^^^^^^^^^^^^^
+ = help: use `crate::repr` to refer to this attribute macro unambiguously
+
+error[E0659]: `repr` is ambiguous
+ --> $DIR/ambiguous-builtin-attrs.rs:20:34
+ |
+LL | fn non_macro_expanded_location<#[repr(C)] T>() {
+ | ^^^^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a builtin attribute
+ = note: `repr` could refer to a built-in attribute
+note: `repr` could also refer to the attribute macro imported here
+ --> $DIR/ambiguous-builtin-attrs.rs:6:5
+ |
+LL | use builtin_attrs::*;
+ | ^^^^^^^^^^^^^^^^
+ = help: use `crate::repr` to refer to this attribute macro unambiguously
+
+error[E0659]: `repr` is ambiguous
+ --> $DIR/ambiguous-builtin-attrs.rs:24:11
+ |
+LL | #[repr(C)]
+ | ^^^^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a builtin attribute
+ = note: `repr` could refer to a built-in attribute
+note: `repr` could also refer to the attribute macro imported here
+ --> $DIR/ambiguous-builtin-attrs.rs:6:5
+ |
+LL | use builtin_attrs::*;
+ | ^^^^^^^^^^^^^^^^
+ = help: use `crate::repr` to refer to this attribute macro unambiguously
+
+error[E0659]: `allow` is ambiguous
+ --> $DIR/ambiguous-builtin-attrs.rs:38:3
+ |
+LL | #[allow(unused)]
+ | ^^^^^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a builtin attribute
+ = note: `allow` could refer to a built-in attribute
+note: `allow` could also refer to the built-in attribute imported here
+ --> $DIR/ambiguous-builtin-attrs.rs:37:5
+ |
+LL | use deny as allow;
+ | ^^^^^^^^^^^^^
+ = help: use `crate::allow` to refer to this built-in attribute unambiguously
+
+error[E0659]: `feature` is ambiguous
+ --> $DIR/ambiguous-builtin-attrs.rs:3:4
+ |
+LL | #![feature(decl_macro)]
+ | ^^^^^^^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a builtin attribute
+ = note: `feature` could refer to a built-in attribute
+note: `feature` could also refer to the attribute macro imported here
+ --> $DIR/ambiguous-builtin-attrs.rs:6:5
+ |
+LL | use builtin_attrs::*;
+ | ^^^^^^^^^^^^^^^^
+ = help: use `crate::feature` to refer to this attribute macro unambiguously
+
+error[E0517]: attribute should be applied to a struct, enum, or union
+ --> $DIR/ambiguous-builtin-attrs.rs:20:39
+ |
+LL | fn non_macro_expanded_location<#[repr(C)] T>() {
+ | ^ - not a struct, enum, or union
+
+error[E0517]: attribute should be applied to a struct, enum, or union
+ --> $DIR/ambiguous-builtin-attrs.rs:24:16
+ |
+LL | #[repr(C)]
+ | ^
+...
+LL | _ => {}
+ | ------- not a struct, enum, or union
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0425, E0517, E0659.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/amputate-span.fixed b/src/test/ui/proc-macro/amputate-span.fixed
new file mode 100644
index 000000000..1afc3501a
--- /dev/null
+++ b/src/test/ui/proc-macro/amputate-span.fixed
@@ -0,0 +1,69 @@
+// aux-build:amputate-span.rs
+// run-rustfix
+// edition:2018
+// compile-flags: --extern amputate_span
+
+// This test has been crafted to ensure the following things:
+//
+// 1. There's a resolution error that prompts the compiler to suggest
+// adding a `use` item.
+//
+// 2. There are no `use` or `extern crate` items in the source
+// code. In fact, there is only one item, the `fn main`
+// declaration.
+//
+// 3. The single `fn main` declaration has an attribute attached to it
+// that just deletes the first token from the given item.
+//
+// You need all of these conditions to hold in order to replicate the
+// scenario that yielded issue 87613, where the compiler's suggestion
+// looks like:
+//
+// ```
+// help: consider importing this struct
+// |
+// 47 | hey */ async use std::process::Command;
+// | ++++++++++++++++++++++++++
+// ```
+//
+// The first condition is necessary to force the compiler issue a
+// suggestion. The second condition is necessary to force the
+// suggestion to be issued at a span associated with the sole
+// `fn`-item of this crate. The third condition is necessary in order
+// to yield the weird state where the associated span of the `fn`-item
+// does not actually cover all of the original source code of the
+// `fn`-item (which is why we are calling it an "amputated" span
+// here).
+//
+// Note that satisfying conditions 2 and 3 requires the use of the
+// `--extern` compile flag.
+//
+// You might ask yourself: What code would do such a thing? The
+// answer is: the #[tokio::main] attribute does *exactly* this (as
+// well as injecting some other code into the `fn main` that it
+// constructs).
+
+use std::process::Command;
+
+#[amputate_span::drop_first_token]
+/* what the
+hey */ async fn main() {
+ Command::new("git"); //~ ERROR [E0433]
+}
+
+// (The /* ... */ comment in the above is not part of the original
+// bug. It is just meant to illustrate one particular facet of the
+// original non-ideal behavior, where we were transcribing the
+// trailing comment as part of the emitted suggestion, for better or
+// for worse.)
+
+#[allow(dead_code)]
+mod inner {
+ use std::process::Command;
+
+#[amputate_span::drop_first_token]
+ /* another interesting
+ case */ async fn foo() {
+ Command::new("git"); //~ ERROR [E0433]
+ }
+}
diff --git a/src/test/ui/proc-macro/amputate-span.rs b/src/test/ui/proc-macro/amputate-span.rs
new file mode 100644
index 000000000..894a06dd5
--- /dev/null
+++ b/src/test/ui/proc-macro/amputate-span.rs
@@ -0,0 +1,65 @@
+// aux-build:amputate-span.rs
+// run-rustfix
+// edition:2018
+// compile-flags: --extern amputate_span
+
+// This test has been crafted to ensure the following things:
+//
+// 1. There's a resolution error that prompts the compiler to suggest
+// adding a `use` item.
+//
+// 2. There are no `use` or `extern crate` items in the source
+// code. In fact, there is only one item, the `fn main`
+// declaration.
+//
+// 3. The single `fn main` declaration has an attribute attached to it
+// that just deletes the first token from the given item.
+//
+// You need all of these conditions to hold in order to replicate the
+// scenario that yielded issue 87613, where the compiler's suggestion
+// looks like:
+//
+// ```
+// help: consider importing this struct
+// |
+// 47 | hey */ async use std::process::Command;
+// | ++++++++++++++++++++++++++
+// ```
+//
+// The first condition is necessary to force the compiler issue a
+// suggestion. The second condition is necessary to force the
+// suggestion to be issued at a span associated with the sole
+// `fn`-item of this crate. The third condition is necessary in order
+// to yield the weird state where the associated span of the `fn`-item
+// does not actually cover all of the original source code of the
+// `fn`-item (which is why we are calling it an "amputated" span
+// here).
+//
+// Note that satisfying conditions 2 and 3 requires the use of the
+// `--extern` compile flag.
+//
+// You might ask yourself: What code would do such a thing? The
+// answer is: the #[tokio::main] attribute does *exactly* this (as
+// well as injecting some other code into the `fn main` that it
+// constructs).
+
+#[amputate_span::drop_first_token]
+/* what the
+hey */ async fn main() {
+ Command::new("git"); //~ ERROR [E0433]
+}
+
+// (The /* ... */ comment in the above is not part of the original
+// bug. It is just meant to illustrate one particular facet of the
+// original non-ideal behavior, where we were transcribing the
+// trailing comment as part of the emitted suggestion, for better or
+// for worse.)
+
+#[allow(dead_code)]
+mod inner {
+ #[amputate_span::drop_first_token]
+ /* another interesting
+ case */ async fn foo() {
+ Command::new("git"); //~ ERROR [E0433]
+ }
+}
diff --git a/src/test/ui/proc-macro/amputate-span.stderr b/src/test/ui/proc-macro/amputate-span.stderr
new file mode 100644
index 000000000..9553ba3da
--- /dev/null
+++ b/src/test/ui/proc-macro/amputate-span.stderr
@@ -0,0 +1,25 @@
+error[E0433]: failed to resolve: use of undeclared type `Command`
+ --> $DIR/amputate-span.rs:49:5
+ |
+LL | Command::new("git");
+ | ^^^^^^^ not found in this scope
+ |
+help: consider importing this struct
+ |
+LL | use std::process::Command;
+ |
+
+error[E0433]: failed to resolve: use of undeclared type `Command`
+ --> $DIR/amputate-span.rs:63:9
+ |
+LL | Command::new("git");
+ | ^^^^^^^ not found in this scope
+ |
+help: consider importing this struct
+ |
+LL | use std::process::Command;
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/proc-macro/append-impl.rs b/src/test/ui/proc-macro/append-impl.rs
new file mode 100644
index 000000000..a49384013
--- /dev/null
+++ b/src/test/ui/proc-macro/append-impl.rs
@@ -0,0 +1,22 @@
+// run-pass
+// aux-build:append-impl.rs
+
+#![allow(warnings)]
+
+#[macro_use]
+extern crate append_impl;
+
+trait Append {
+ fn foo(&self);
+}
+
+#[derive(PartialEq,
+ Append,
+ Eq)]
+struct A {
+ inner: u32,
+}
+
+fn main() {
+ A { inner: 3 }.foo();
+}
diff --git a/src/test/ui/proc-macro/attr-args.rs b/src/test/ui/proc-macro/attr-args.rs
new file mode 100644
index 000000000..764f507ab
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-args.rs
@@ -0,0 +1,13 @@
+// run-pass
+// aux-build:attr-args.rs
+
+#![allow(warnings)]
+
+extern crate attr_args;
+use attr_args::{attr_with_args, identity};
+
+#[attr_with_args(text = "Hello, world!")]
+fn foo() {}
+
+#[identity(fn main() { assert_eq!(foo(), "Hello, world!"); })]
+struct Dummy;
diff --git a/src/test/ui/proc-macro/attr-cfg.rs b/src/test/ui/proc-macro/attr-cfg.rs
new file mode 100644
index 000000000..2aed9e2e8
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-cfg.rs
@@ -0,0 +1,27 @@
+// run-pass
+// aux-build:attr-cfg.rs
+// revisions: foo bar
+
+extern crate attr_cfg;
+use attr_cfg::attr_cfg;
+
+#[attr_cfg]
+fn outer() -> u8 {
+ #[cfg(foo)]
+ fn inner() -> u8 { 1 }
+
+ #[cfg(bar)]
+ fn inner() -> u8 { 2 }
+
+ inner()
+}
+
+#[cfg(foo)]
+fn main() {
+ assert_eq!(outer(), 1);
+}
+
+#[cfg(bar)]
+fn main() {
+ assert_eq!(outer(), 2);
+}
diff --git a/src/test/ui/proc-macro/attr-complex-fn.rs b/src/test/ui/proc-macro/attr-complex-fn.rs
new file mode 100644
index 000000000..47734c94f
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-complex-fn.rs
@@ -0,0 +1,26 @@
+// check-pass
+// compile-flags: -Z span-debug --error-format human
+// aux-build:test-macros.rs
+
+#![feature(stmt_expr_attributes)]
+#![feature(custom_inner_attributes)]
+#![feature(rustc_attrs)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+trait MyTrait<T> {}
+struct MyStruct<const N: bool>;
+
+#[print_attr]
+fn foo<T: MyTrait<MyStruct<{ true }>>>() {}
+
+impl<T> MyTrait<T> for MyStruct<{true}> {
+ #![print_attr]
+ #![rustc_dummy]
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/attr-complex-fn.stdout b/src/test/ui/proc-macro/attr-complex-fn.stdout
new file mode 100644
index 000000000..fc69a13dd
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-complex-fn.stdout
@@ -0,0 +1,171 @@
+PRINT-ATTR INPUT (DISPLAY): fn foo < T : MyTrait < MyStruct < { true } >> > () {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fn",
+ span: $DIR/attr-complex-fn.rs:19:1: 19:3 (#0),
+ },
+ Ident {
+ ident: "foo",
+ span: $DIR/attr-complex-fn.rs:19:4: 19:7 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:19:7: 19:8 (#0),
+ },
+ Ident {
+ ident: "T",
+ span: $DIR/attr-complex-fn.rs:19:8: 19:9 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:19:9: 19:10 (#0),
+ },
+ Ident {
+ ident: "MyTrait",
+ span: $DIR/attr-complex-fn.rs:19:11: 19:18 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:19:18: 19:19 (#0),
+ },
+ Ident {
+ ident: "MyStruct",
+ span: $DIR/attr-complex-fn.rs:19:19: 19:27 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:19:27: 19:28 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "true",
+ span: $DIR/attr-complex-fn.rs:19:30: 19:34 (#0),
+ },
+ ],
+ span: $DIR/attr-complex-fn.rs:19:28: 19:36 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Joint,
+ span: $DIR/attr-complex-fn.rs:19:36: 19:38 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Joint,
+ span: $DIR/attr-complex-fn.rs:19:36: 19:38 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:19:38: 19:39 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/attr-complex-fn.rs:19:39: 19:41 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/attr-complex-fn.rs:19:42: 19:44 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): impl < T > MyTrait < T > for MyStruct < { true } > { #! [rustc_dummy] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "impl",
+ span: $DIR/attr-complex-fn.rs:21:1: 21:5 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:21:5: 21:6 (#0),
+ },
+ Ident {
+ ident: "T",
+ span: $DIR/attr-complex-fn.rs:21:6: 21:7 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:21:7: 21:8 (#0),
+ },
+ Ident {
+ ident: "MyTrait",
+ span: $DIR/attr-complex-fn.rs:21:9: 21:16 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:21:16: 21:17 (#0),
+ },
+ Ident {
+ ident: "T",
+ span: $DIR/attr-complex-fn.rs:21:17: 21:18 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:21:18: 21:19 (#0),
+ },
+ Ident {
+ ident: "for",
+ span: $DIR/attr-complex-fn.rs:21:20: 21:23 (#0),
+ },
+ Ident {
+ ident: "MyStruct",
+ span: $DIR/attr-complex-fn.rs:21:24: 21:32 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:21:32: 21:33 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "true",
+ span: $DIR/attr-complex-fn.rs:21:34: 21:38 (#0),
+ },
+ ],
+ span: $DIR/attr-complex-fn.rs:21:33: 21:39 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:21:39: 21:40 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/attr-complex-fn.rs:23:5: 23:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/attr-complex-fn.rs:23:6: 23:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/attr-complex-fn.rs:23:8: 23:19 (#0),
+ },
+ ],
+ span: $DIR/attr-complex-fn.rs:23:7: 23:20 (#0),
+ },
+ ],
+ span: $DIR/attr-complex-fn.rs:21:41: 24:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.rs b/src/test/ui/proc-macro/attr-invalid-exprs.rs
new file mode 100644
index 000000000..9dcffc340
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-invalid-exprs.rs
@@ -0,0 +1,28 @@
+//! Attributes producing expressions in invalid locations
+
+// aux-build:attr-stmt-expr.rs
+
+#![feature(proc_macro_hygiene)]
+#![feature(stmt_expr_attributes)]
+
+extern crate attr_stmt_expr;
+use attr_stmt_expr::{duplicate, no_output};
+
+fn main() {
+ let _ = #[no_output] "Hello, world!";
+ //~^ ERROR expected expression, found end of macro arguments
+
+ let _ = #[duplicate] "Hello, world!";
+ //~^ ERROR macro expansion ignores token `,` and any following
+
+ let _ = {
+ #[no_output]
+ "Hello, world!"
+ };
+
+ let _ = {
+ #[duplicate]
+ //~^ ERROR macro expansion ignores token `,` and any following
+ "Hello, world!"
+ };
+}
diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.stderr b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
new file mode 100644
index 000000000..bcb54df0e
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
@@ -0,0 +1,28 @@
+error: expected expression, found end of macro arguments
+ --> $DIR/attr-invalid-exprs.rs:12:13
+ |
+LL | let _ = #[no_output] "Hello, world!";
+ | ^^^^^^^^^^^^
+
+error: macro expansion ignores token `,` and any following
+ --> $DIR/attr-invalid-exprs.rs:15:13
+ |
+LL | let _ = #[duplicate] "Hello, world!";
+ | ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
+ | |
+ | caused by the macro expansion here
+ |
+ = note: the usage of `duplicate!` is likely invalid in expression context
+
+error: macro expansion ignores token `,` and any following
+ --> $DIR/attr-invalid-exprs.rs:24:9
+ |
+LL | #[duplicate]
+ | ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
+ | |
+ | caused by the macro expansion here
+ |
+ = note: the usage of `duplicate!` is likely invalid in expression context
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/proc-macro/attr-on-trait.rs b/src/test/ui/proc-macro/attr-on-trait.rs
new file mode 100644
index 000000000..e0edee630
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-on-trait.rs
@@ -0,0 +1,19 @@
+// run-pass
+// aux-build:attr-on-trait.rs
+
+extern crate attr_on_trait;
+
+use attr_on_trait::foo;
+
+trait Foo {
+ #[foo]
+ fn foo() {}
+}
+
+impl Foo for i32 {
+ fn foo(&self) {}
+}
+
+fn main() {
+ 3i32.foo();
+}
diff --git a/src/test/ui/proc-macro/attr-stmt-expr-rpass.rs b/src/test/ui/proc-macro/attr-stmt-expr-rpass.rs
new file mode 100644
index 000000000..16b8fabfc
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-stmt-expr-rpass.rs
@@ -0,0 +1,36 @@
+// run-pass
+// aux-build:attr-stmt-expr-rpass.rs
+
+#![feature(stmt_expr_attributes, proc_macro_hygiene)]
+
+extern crate attr_stmt_expr_rpass as attr_stmt_expr;
+use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr,
+ no_output, noop};
+
+fn print_str(string: &'static str) {
+ // macros are handled a bit differently
+ #[expect_print_expr]
+ println!("{}", string)
+}
+
+fn main() {
+ #[expect_let]
+ let string = "Hello, world!";
+
+ #[expect_print_stmt]
+ println!("{}", string);
+
+ let _: () = {
+ #[no_output]
+ "Hello, world!"
+ };
+
+ let _: &'static str = #[noop] "Hello, world!";
+
+ let _: &'static str = {
+ #[noop] "Hello, world!"
+ };
+
+ #[expect_expr]
+ print_str("string")
+}
diff --git a/src/test/ui/proc-macro/attr-stmt-expr.rs b/src/test/ui/proc-macro/attr-stmt-expr.rs
new file mode 100644
index 000000000..0403684cd
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-stmt-expr.rs
@@ -0,0 +1,66 @@
+// aux-build:attr-stmt-expr.rs
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![feature(proc_macro_hygiene)]
+#![feature(rustc_attrs)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+extern crate test_macros;
+extern crate attr_stmt_expr;
+
+use test_macros::print_attr;
+use attr_stmt_expr::{expect_let, expect_my_macro_stmt, expect_expr, expect_my_macro_expr};
+
+// We don't use `std::println` so that we avoid loading hygiene
+// information from libstd, which would affect the SyntaxContext ids
+macro_rules! my_macro {
+ ($($tt:tt)*) => { () }
+}
+
+fn print_str(string: &'static str) {
+ // macros are handled a bit differently
+ #[expect_my_macro_expr]
+ //~^ ERROR attributes on expressions are experimental
+ //~| HELP add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+ my_macro!("{}", string)
+}
+
+macro_rules! make_stmt {
+ ($stmt:stmt) => {
+ #[print_attr]
+ #[rustc_dummy]
+ $stmt
+ }
+}
+
+macro_rules! second_make_stmt {
+ ($stmt:stmt) => {
+ make_stmt!($stmt);
+ }
+}
+
+fn main() {
+ make_stmt!(struct Foo {});
+
+ #[print_attr]
+ #[expect_let]
+ let string = "Hello, world!";
+
+ #[print_attr]
+ #[expect_my_macro_stmt]
+ my_macro!("{}", string);
+
+ #[print_attr]
+ second_make_stmt!(#[allow(dead_code)] struct Bar {});
+
+ #[print_attr]
+ #[rustc_dummy]
+ struct Other {}
+
+ #[expect_expr]
+ //~^ ERROR attributes on expressions are experimental
+ //~| HELP add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+ print_str("string")
+}
diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stderr b/src/test/ui/proc-macro/attr-stmt-expr.stderr
new file mode 100644
index 000000000..56178259d
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-stmt-expr.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/attr-stmt-expr.rs:24:5
+ |
+LL | #[expect_my_macro_expr]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/attr-stmt-expr.rs:62:5
+ |
+LL | #[expect_expr]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/attr-stmt-expr.stdout b/src/test/ui/proc-macro/attr-stmt-expr.stdout
new file mode 100644
index 000000000..f9b2305c7
--- /dev/null
+++ b/src/test/ui/proc-macro/attr-stmt-expr.stdout
@@ -0,0 +1,274 @@
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Foo {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:33:9: 33:10 (#8),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/attr-stmt-expr.rs:33:11: 33:22 (#8),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:33:10: 33:23 (#8),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/attr-stmt-expr.rs:45:16: 45:22 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/attr-stmt-expr.rs:45:23: 45:26 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/attr-stmt-expr.rs:45:27: 45:29 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:48:5: 48:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "expect_let",
+ span: $DIR/attr-stmt-expr.rs:48:7: 48:17 (#0),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:48:6: 48:18 (#0),
+ },
+ Ident {
+ ident: "let",
+ span: $DIR/attr-stmt-expr.rs:49:5: 49:8 (#0),
+ },
+ Ident {
+ ident: "string",
+ span: $DIR/attr-stmt-expr.rs:49:9: 49:15 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:49:16: 49:17 (#0),
+ },
+ Literal {
+ kind: Str,
+ symbol: "Hello, world!",
+ suffix: None,
+ span: $DIR/attr-stmt-expr.rs:49:18: 49:33 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:49:33: 49:34 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:52:5: 52:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "expect_my_macro_stmt",
+ span: $DIR/attr-stmt-expr.rs:52:7: 52:27 (#0),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:52:6: 52:28 (#0),
+ },
+ Ident {
+ ident: "my_macro",
+ span: $DIR/attr-stmt-expr.rs:53:5: 53:13 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:53:13: 53:14 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Literal {
+ kind: Str,
+ symbol: "{}",
+ suffix: None,
+ span: $DIR/attr-stmt-expr.rs:53:15: 53:19 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:53:19: 53:20 (#0),
+ },
+ Ident {
+ ident: "string",
+ span: $DIR/attr-stmt-expr.rs:53:21: 53:27 (#0),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:53:14: 53:28 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:53:28: 53:29 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "second_make_stmt",
+ span: $DIR/attr-stmt-expr.rs:56:5: 56:21 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:56:21: 56:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:56:23: 56:24 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/attr-stmt-expr.rs:56:25: 56:30 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "dead_code",
+ span: $DIR/attr-stmt-expr.rs:56:31: 56:40 (#0),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:56:30: 56:41 (#0),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:56:24: 56:42 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/attr-stmt-expr.rs:56:43: 56:49 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/attr-stmt-expr.rs:56:50: 56:53 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/attr-stmt-expr.rs:56:54: 56:56 (#0),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:56:22: 56:57 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:56:57: 56:58 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[allow(dead_code)] struct Bar {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:33:9: 33:10 (#29),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/attr-stmt-expr.rs:33:11: 33:22 (#29),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:33:10: 33:23 (#29),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:56:23: 56:24 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/attr-stmt-expr.rs:56:25: 56:30 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "dead_code",
+ span: $DIR/attr-stmt-expr.rs:56:31: 56:40 (#0),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:56:30: 56:41 (#0),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:56:24: 56:42 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/attr-stmt-expr.rs:56:43: 56:49 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/attr-stmt-expr.rs:56:50: 56:53 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/attr-stmt-expr.rs:56:54: 56:56 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct Other {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attr-stmt-expr.rs:59:5: 59:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/attr-stmt-expr.rs:59:7: 59:18 (#0),
+ },
+ ],
+ span: $DIR/attr-stmt-expr.rs:59:6: 59:19 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/attr-stmt-expr.rs:60:5: 60:11 (#0),
+ },
+ Ident {
+ ident: "Other",
+ span: $DIR/attr-stmt-expr.rs:60:12: 60:17 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/attr-stmt-expr.rs:60:18: 60:20 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/attribute-after-derive.rs b/src/test/ui/proc-macro/attribute-after-derive.rs
new file mode 100644
index 000000000..0f0f27bff
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-after-derive.rs
@@ -0,0 +1,28 @@
+// Macro attributes are allowed after `#[derive]` and
+// `#[derive]` fully configures the item for following attributes.
+
+// check-pass
+// compile-flags: -Z span-debug
+// aux-build: test-macros.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+#[print_attr]
+#[derive(Print)]
+struct AttributeDerive {
+ #[cfg(FALSE)]
+ field: u8,
+}
+
+#[derive(Print)]
+#[print_attr]
+struct DeriveAttribute {
+ #[cfg(FALSE)]
+ field: u8,
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/attribute-after-derive.stdout b/src/test/ui/proc-macro/attribute-after-derive.stdout
new file mode 100644
index 000000000..1b17d6047
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-after-derive.stdout
@@ -0,0 +1,192 @@
+PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field : u8, }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:15:1: 15:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "derive",
+ span: $DIR/attribute-after-derive.rs:15:3: 15:9 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "Print",
+ span: $DIR/attribute-after-derive.rs:15:10: 15:15 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:15:9: 15:16 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:15:2: 15:17 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0),
+ },
+ Ident {
+ ident: "AttributeDerive",
+ span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:17:5: 17:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/attribute-after-derive.rs:17:7: 17:10 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:17:10: 17:17 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:17:6: 17:18 (#0),
+ },
+ Ident {
+ ident: "field",
+ span: $DIR/attribute-after-derive.rs:18:5: 18:10 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:18:10: 18:11 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/attribute-after-derive.rs:18:12: 18:14 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:18:14: 18:15 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive {}
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0),
+ },
+ Ident {
+ ident: "AttributeDerive",
+ span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute {}
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:22:1: 22:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_attr",
+ span: $DIR/attribute-after-derive.rs:22:3: 22:13 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:22:2: 22:14 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0),
+ },
+ Ident {
+ ident: "DeriveAttribute",
+ span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field : u8, }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0),
+ },
+ Ident {
+ ident: "DeriveAttribute",
+ span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:24:5: 24:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/attribute-after-derive.rs:24:7: 24:10 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/attribute-after-derive.rs:24:11: 24:16 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:24:10: 24:17 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:24:6: 24:18 (#0),
+ },
+ Ident {
+ ident: "field",
+ span: $DIR/attribute-after-derive.rs:25:5: 25:10 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:25:10: 25:11 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/attribute-after-derive.rs:25:12: 25:14 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:25:14: 25:15 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.rs b/src/test/ui/proc-macro/attribute-spans-preserved.rs
new file mode 100644
index 000000000..c01fce905
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-spans-preserved.rs
@@ -0,0 +1,10 @@
+// aux-build:attribute-spans-preserved.rs
+
+extern crate attribute_spans_preserved as foo;
+
+use foo::foo;
+
+#[ foo ( let y: u32 = "z"; ) ] //~ ERROR: mismatched types
+#[ bar { let x: u32 = "y"; } ] //~ ERROR: mismatched types
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stderr b/src/test/ui/proc-macro/attribute-spans-preserved.stderr
new file mode 100644
index 000000000..193482a42
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-spans-preserved.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+ --> $DIR/attribute-spans-preserved.rs:7:23
+ |
+LL | #[ foo ( let y: u32 = "z"; ) ]
+ | --- ^^^ expected `u32`, found `&str`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/attribute-spans-preserved.rs:8:23
+ |
+LL | #[ bar { let x: u32 = "y"; } ]
+ | --- ^^^ expected `u32`, found `&str`
+ | |
+ | expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stdout b/src/test/ui/proc-macro/attribute-spans-preserved.stdout
new file mode 100644
index 000000000..cf9a97491
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-spans-preserved.stdout
@@ -0,0 +1 @@
+fn main() { let y : u32 = "z" ; { let x : u32 = "y" ; } }
diff --git a/src/test/ui/proc-macro/attribute-with-error.rs b/src/test/ui/proc-macro/attribute-with-error.rs
new file mode 100644
index 000000000..aaa6c07dd
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-with-error.rs
@@ -0,0 +1,42 @@
+// aux-build:test-macros.rs
+
+#![feature(custom_inner_attributes)]
+
+#[macro_use]
+extern crate test_macros;
+
+#[recollect_attr]
+fn test1() {
+ let a: i32 = "foo";
+ //~^ ERROR: mismatched types
+ let b: i32 = "f'oo";
+ //~^ ERROR: mismatched types
+}
+
+fn test2() {
+ #![recollect_attr]
+
+ // FIXME: should have a type error here and assert it works but it doesn't
+}
+
+trait A {
+ // FIXME: should have a #[recollect_attr] attribute here and assert that it works
+ fn foo(&self) {
+ let a: i32 = "foo";
+ //~^ ERROR: mismatched types
+ }
+}
+
+struct B;
+
+impl A for B {
+ #[recollect_attr]
+ fn foo(&self) {
+ let a: i32 = "foo";
+ //~^ ERROR: mismatched types
+ }
+}
+
+#[recollect_attr]
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/attribute-with-error.stderr b/src/test/ui/proc-macro/attribute-with-error.stderr
new file mode 100644
index 000000000..7f3a7e670
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute-with-error.stderr
@@ -0,0 +1,35 @@
+error[E0308]: mismatched types
+ --> $DIR/attribute-with-error.rs:10:18
+ |
+LL | let a: i32 = "foo";
+ | --- ^^^^^ expected `i32`, found `&str`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/attribute-with-error.rs:12:18
+ |
+LL | let b: i32 = "f'oo";
+ | --- ^^^^^^ expected `i32`, found `&str`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/attribute-with-error.rs:25:22
+ |
+LL | let a: i32 = "foo";
+ | --- ^^^^^ expected `i32`, found `&str`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/attribute-with-error.rs:35:22
+ |
+LL | let a: i32 = "foo";
+ | --- ^^^^^ expected `i32`, found `&str`
+ | |
+ | expected due to this
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs
new file mode 100644
index 000000000..5531b3236
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute.rs
@@ -0,0 +1,73 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive] //~ ERROR malformed `proc_macro_derive` attribute
+pub fn foo1(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive = ""] //~ ERROR malformed `proc_macro_derive` attribute
+pub fn foo2(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d3, a, b)]
+//~^ ERROR attribute must have either one or two arguments
+pub fn foo3(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d4, attributes(a), b)]
+//~^ ERROR attribute must have either one or two arguments
+pub fn foo4(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive("a")]
+//~^ ERROR: not a meta item
+pub fn foo5(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d6 = "")]
+//~^ ERROR: must only be one word
+pub fn foo6(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(m::d7)]
+//~^ ERROR: must only be one word
+pub fn foo7(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d8(a))]
+//~^ ERROR: must only be one word
+pub fn foo8(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(self)]
+//~^ ERROR: `self` cannot be a name of derive macro
+pub fn foo9(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(PartialEq)] // OK
+pub fn foo10(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d11, a)]
+//~^ ERROR: second argument must be `attributes`
+//~| ERROR: attribute must be of form: `attributes(foo, bar)`
+pub fn foo11(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d12, attributes)]
+//~^ ERROR: attribute must be of form: `attributes(foo, bar)`
+pub fn foo12(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d13, attributes("a"))]
+//~^ ERROR: not a meta item
+pub fn foo13(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d14, attributes(a = ""))]
+//~^ ERROR: must only be one word
+pub fn foo14(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d15, attributes(m::a))]
+//~^ ERROR: must only be one word
+pub fn foo15(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d16, attributes(a(b)))]
+//~^ ERROR: must only be one word
+pub fn foo16(input: TokenStream) -> TokenStream { input }
+
+#[proc_macro_derive(d17, attributes(self))]
+//~^ ERROR: `self` cannot be a name of derive helper attribute
+pub fn foo17(input: TokenStream) -> TokenStream { input }
diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr
new file mode 100644
index 000000000..021e7cad0
--- /dev/null
+++ b/src/test/ui/proc-macro/attribute.stderr
@@ -0,0 +1,104 @@
+error: malformed `proc_macro_derive` attribute input
+ --> $DIR/attribute.rs:9:1
+ |
+LL | #[proc_macro_derive]
+ | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
+
+error: malformed `proc_macro_derive` attribute input
+ --> $DIR/attribute.rs:12:1
+ |
+LL | #[proc_macro_derive = ""]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
+
+error: attribute must have either one or two arguments
+ --> $DIR/attribute.rs:15:1
+ |
+LL | #[proc_macro_derive(d3, a, b)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: attribute must have either one or two arguments
+ --> $DIR/attribute.rs:19:1
+ |
+LL | #[proc_macro_derive(d4, attributes(a), b)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: not a meta item
+ --> $DIR/attribute.rs:23:21
+ |
+LL | #[proc_macro_derive("a")]
+ | ^^^
+
+error: must only be one word
+ --> $DIR/attribute.rs:27:21
+ |
+LL | #[proc_macro_derive(d6 = "")]
+ | ^^^^^^^
+
+error: must only be one word
+ --> $DIR/attribute.rs:31:21
+ |
+LL | #[proc_macro_derive(m::d7)]
+ | ^^^^^
+
+error: must only be one word
+ --> $DIR/attribute.rs:35:21
+ |
+LL | #[proc_macro_derive(d8(a))]
+ | ^^^^^
+
+error: `self` cannot be a name of derive macro
+ --> $DIR/attribute.rs:39:21
+ |
+LL | #[proc_macro_derive(self)]
+ | ^^^^
+
+error: second argument must be `attributes`
+ --> $DIR/attribute.rs:46:26
+ |
+LL | #[proc_macro_derive(d11, a)]
+ | ^
+
+error: attribute must be of form: `attributes(foo, bar)`
+ --> $DIR/attribute.rs:46:26
+ |
+LL | #[proc_macro_derive(d11, a)]
+ | ^
+
+error: attribute must be of form: `attributes(foo, bar)`
+ --> $DIR/attribute.rs:51:26
+ |
+LL | #[proc_macro_derive(d12, attributes)]
+ | ^^^^^^^^^^
+
+error: not a meta item
+ --> $DIR/attribute.rs:55:37
+ |
+LL | #[proc_macro_derive(d13, attributes("a"))]
+ | ^^^
+
+error: must only be one word
+ --> $DIR/attribute.rs:59:37
+ |
+LL | #[proc_macro_derive(d14, attributes(a = ""))]
+ | ^^^^^^
+
+error: must only be one word
+ --> $DIR/attribute.rs:63:37
+ |
+LL | #[proc_macro_derive(d15, attributes(m::a))]
+ | ^^^^
+
+error: must only be one word
+ --> $DIR/attribute.rs:67:37
+ |
+LL | #[proc_macro_derive(d16, attributes(a(b)))]
+ | ^^^^
+
+error: `self` cannot be a name of derive helper attribute
+ --> $DIR/attribute.rs:71:37
+ |
+LL | #[proc_macro_derive(d17, attributes(self))]
+ | ^^^^
+
+error: aborting due to 17 previous errors
+
diff --git a/src/test/ui/proc-macro/attributes-included.rs b/src/test/ui/proc-macro/attributes-included.rs
new file mode 100644
index 000000000..95e8e10a3
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-included.rs
@@ -0,0 +1,22 @@
+// aux-build:attributes-included.rs
+// check-pass
+
+#![warn(unused)]
+
+extern crate attributes_included;
+
+use attributes_included::*;
+
+#[bar]
+#[inline]
+/// doc
+#[foo]
+#[inline]
+/// doc
+fn foo() {
+ let a: i32 = "foo"; //~ WARN: unused variable
+}
+
+fn main() {
+ foo()
+}
diff --git a/src/test/ui/proc-macro/attributes-included.stderr b/src/test/ui/proc-macro/attributes-included.stderr
new file mode 100644
index 000000000..72c88d5d8
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-included.stderr
@@ -0,0 +1,15 @@
+warning: unused variable: `a`
+ --> $DIR/attributes-included.rs:17:9
+ |
+LL | let a: i32 = "foo";
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+ |
+note: the lint level is defined here
+ --> $DIR/attributes-included.rs:4:9
+ |
+LL | #![warn(unused)]
+ | ^^^^^^
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/proc-macro/attributes-on-definitions.rs b/src/test/ui/proc-macro/attributes-on-definitions.rs
new file mode 100644
index 000000000..c0733c8b4
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-on-definitions.rs
@@ -0,0 +1,12 @@
+// check-pass
+// aux-build:attributes-on-definitions.rs
+
+#![forbid(unsafe_code)]
+
+extern crate attributes_on_definitions;
+
+attributes_on_definitions::with_attrs!();
+//~^ WARN use of deprecated
+// No errors about the use of unstable and unsafe code inside the macro.
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/attributes-on-definitions.stderr b/src/test/ui/proc-macro/attributes-on-definitions.stderr
new file mode 100644
index 000000000..c63dd0011
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-on-definitions.stderr
@@ -0,0 +1,10 @@
+warning: use of deprecated macro `attributes_on_definitions::with_attrs`: test
+ --> $DIR/attributes-on-definitions.rs:8:1
+ |
+LL | attributes_on_definitions::with_attrs!();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(deprecated)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/proc-macro/attributes-on-modules-fail.rs b/src/test/ui/proc-macro/attributes-on-modules-fail.rs
new file mode 100644
index 000000000..6c30e8f4f
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-on-modules-fail.rs
@@ -0,0 +1,46 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[identity_attr]
+mod m {
+ pub struct X;
+
+ type A = Y; //~ ERROR cannot find type `Y` in this scope
+}
+
+struct Y;
+type A = X; //~ ERROR cannot find type `X` in this scope
+
+#[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
+mod n {}
+
+#[empty_attr]
+mod module; //~ ERROR non-inline modules in proc macro input are unstable
+
+#[empty_attr]
+mod outer {
+ mod inner; //~ ERROR non-inline modules in proc macro input are unstable
+
+ mod inner_inline {} // OK
+}
+
+#[derive(Empty)]
+struct S {
+ field: [u8; {
+ #[path = "outer/inner.rs"]
+ mod inner; //~ ERROR non-inline modules in proc macro input are unstable
+ mod inner_inline {} // OK
+ 0
+ }]
+}
+
+#[identity_attr]
+fn f() {
+ #[path = "outer/inner.rs"]
+ mod inner; //~ ERROR non-inline modules in proc macro input are unstable
+ mod inner_inline {} // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/attributes-on-modules-fail.stderr b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr
new file mode 100644
index 000000000..bb6cbb698
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-on-modules-fail.stderr
@@ -0,0 +1,70 @@
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
+ --> $DIR/attributes-on-modules-fail.rs:16:1
+ |
+LL | #[derive(Copy)]
+ | ^^^^^^^^^^^^^^^ not applicable here
+LL | mod n {}
+ | -------- not a `struct`, `enum` or `union`
+
+error[E0658]: non-inline modules in proc macro input are unstable
+ --> $DIR/attributes-on-modules-fail.rs:20:1
+ |
+LL | mod module;
+ | ^^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: non-inline modules in proc macro input are unstable
+ --> $DIR/attributes-on-modules-fail.rs:24:5
+ |
+LL | mod inner;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: non-inline modules in proc macro input are unstable
+ --> $DIR/attributes-on-modules-fail.rs:33:9
+ |
+LL | mod inner;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: non-inline modules in proc macro input are unstable
+ --> $DIR/attributes-on-modules-fail.rs:42:5
+ |
+LL | mod inner;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0412]: cannot find type `Y` in this scope
+ --> $DIR/attributes-on-modules-fail.rs:10:14
+ |
+LL | type A = Y;
+ | ^ not found in this scope
+ |
+help: consider importing this struct
+ |
+LL | use Y;
+ |
+
+error[E0412]: cannot find type `X` in this scope
+ --> $DIR/attributes-on-modules-fail.rs:14:10
+ |
+LL | type A = X;
+ | ^ not found in this scope
+ |
+help: consider importing this struct
+ |
+LL | use m::X;
+ |
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0412, E0658, E0774.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/proc-macro/attributes-on-modules.rs b/src/test/ui/proc-macro/attributes-on-modules.rs
new file mode 100644
index 000000000..6c73b0bf1
--- /dev/null
+++ b/src/test/ui/proc-macro/attributes-on-modules.rs
@@ -0,0 +1,19 @@
+// check-pass
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[identity_attr]
+mod m {
+ pub struct S;
+}
+
+#[identity_attr]
+fn f() {
+ mod m {}
+}
+
+fn main() {
+ let s = m::S;
+}
diff --git a/src/test/ui/proc-macro/auxiliary/add-impl.rs b/src/test/ui/proc-macro/auxiliary/add-impl.rs
new file mode 100644
index 000000000..741e64875
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/amputate-span.rs b/src/test/ui/proc-macro/auxiliary/amputate-span.rs
new file mode 100644
index 000000000..1a82119ae
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/api/cmp.rs b/src/test/ui/proc-macro/auxiliary/api/cmp.rs
new file mode 100644
index 000000000..5784a6e5d
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/api/mod.rs b/src/test/ui/proc-macro/auxiliary/api/mod.rs
new file mode 100644
index 000000000..739c25132
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs
new file mode 100644
index 000000000..27391f831
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/append-impl.rs b/src/test/ui/proc-macro/auxiliary/append-impl.rs
new file mode 100644
index 000000000..b032b1337
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/assert-span-pos.rs b/src/test/ui/proc-macro/auxiliary/assert-span-pos.rs
new file mode 100644
index 000000000..455c5c7c3
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/attr-args.rs b/src/test/ui/proc-macro/auxiliary/attr-args.rs
new file mode 100644
index 000000000..5f76a4484
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/attr-cfg.rs b/src/test/ui/proc-macro/auxiliary/attr-cfg.rs
new file mode 100644
index 000000000..2f0054cc1
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/attr-on-trait.rs b/src/test/ui/proc-macro/auxiliary/attr-on-trait.rs
new file mode 100644
index 000000000..3787b8eec
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs
new file mode 100644
index 000000000..5b386b46b
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/src/test/ui/proc-macro/auxiliary/attr-stmt-expr.rs
new file mode 100644
index 000000000..4d6dc06b4
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/attribute-spans-preserved.rs b/src/test/ui/proc-macro/auxiliary/attribute-spans-preserved.rs
new file mode 100644
index 000000000..4d3279584
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/attributes-included.rs b/src/test/ui/proc-macro/auxiliary/attributes-included.rs
new file mode 100644
index 000000000..a5eb40b28
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs
new file mode 100644
index 000000000..93a339840
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/bang-macro.rs b/src/test/ui/proc-macro/auxiliary/bang-macro.rs
new file mode 100644
index 000000000..ff0002282
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs b/src/test/ui/proc-macro/auxiliary/bang_proc_macro2.rs
new file mode 100644
index 000000000..fcaaba602
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/builtin-attrs.rs b/src/test/ui/proc-macro/auxiliary/builtin-attrs.rs
new file mode 100644
index 000000000..6edafae39
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/call-deprecated.rs b/src/test/ui/proc-macro/auxiliary/call-deprecated.rs
new file mode 100644
index 000000000..2f484809a
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/call-site.rs b/src/test/ui/proc-macro/auxiliary/call-site.rs
new file mode 100644
index 000000000..e64a5a343
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/cond_plugin.rs b/src/test/ui/proc-macro/auxiliary/cond_plugin.rs
new file mode 100644
index 000000000..8d3c4ec23
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/count_compound_ops.rs b/src/test/ui/proc-macro/auxiliary/count_compound_ops.rs
new file mode 100644
index 000000000..3a656d648
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs b/src/test/ui/proc-macro/auxiliary/custom-attr-only-one-derive.rs
new file mode 100644
index 000000000..41f73f596
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/custom-quote.rs b/src/test/ui/proc-macro/auxiliary/custom-quote.rs
new file mode 100644
index 000000000..3b7811748
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-a.rs b/src/test/ui/proc-macro/auxiliary/derive-a.rs
new file mode 100644
index 000000000..79a3864bf
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-atob.rs b/src/test/ui/proc-macro/auxiliary/derive-atob.rs
new file mode 100644
index 000000000..207b7fd32
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-attr-cfg.rs b/src/test/ui/proc-macro/auxiliary/derive-attr-cfg.rs
new file mode 100644
index 000000000..e7e9634e0
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs b/src/test/ui/proc-macro/auxiliary/derive-b-rpass.rs
new file mode 100644
index 000000000..641a95f78
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-b.rs b/src/test/ui/proc-macro/auxiliary/derive-b.rs
new file mode 100644
index 000000000..e7ab6c072
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-bad.rs b/src/test/ui/proc-macro/auxiliary/derive-bad.rs
new file mode 100644
index 000000000..90bb9b1ba
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-clona.rs b/src/test/ui/proc-macro/auxiliary/derive-clona.rs
new file mode 100644
index 000000000..4a35c9d0d
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-ctod.rs b/src/test/ui/proc-macro/auxiliary/derive-ctod.rs
new file mode 100644
index 000000000..2efe5a913
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-foo.rs b/src/test/ui/proc-macro/auxiliary/derive-foo.rs
new file mode 100644
index 000000000..3ea027d4f
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs
new file mode 100644
index 000000000..ab532da29
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs
@@ -0,0 +1,2 @@
+#[macro_export]
+macro_rules! empty_helper { () => () }
diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing-2.rs
new file mode 100644
index 000000000..370a1a279
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs
new file mode 100644
index 000000000..41d3a1846
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-nothing.rs b/src/test/ui/proc-macro/auxiliary/derive-nothing.rs
new file mode 100644
index 000000000..b6d1e133a
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-same-struct.rs b/src/test/ui/proc-macro/auxiliary/derive-same-struct.rs
new file mode 100644
index 000000000..7598d632c
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-two-attrs.rs b/src/test/ui/proc-macro/auxiliary/derive-two-attrs.rs
new file mode 100644
index 000000000..a6f0eec12
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-union.rs b/src/test/ui/proc-macro/auxiliary/derive-union.rs
new file mode 100644
index 000000000..05883170c
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable-2.rs
new file mode 100644
index 000000000..eac21b049
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/derive-unstable.rs b/src/test/ui/proc-macro/auxiliary/derive-unstable.rs
new file mode 100644
index 000000000..2ccd3f882
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs
new file mode 100644
index 000000000..bdcdb7922
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/double.rs b/src/test/ui/proc-macro/auxiliary/double.rs
new file mode 100644
index 000000000..99eb4e375
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/duplicate.rs b/src/test/ui/proc-macro/auxiliary/duplicate.rs
new file mode 100644
index 000000000..b8f82b46f
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs b/src/test/ui/proc-macro/auxiliary/edition-imports-2015.rs
new file mode 100644
index 000000000..27c59b805
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/empty-crate.rs b/src/test/ui/proc-macro/auxiliary/empty-crate.rs
new file mode 100644
index 000000000..1cf7534b2
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/expand-expr.rs b/src/test/ui/proc-macro/auxiliary/expand-expr.rs
new file mode 100644
index 000000000..5463e79d7
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/expand-expr.rs
@@ -0,0 +1,149 @@
+// 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();
+ loop {
+ match iter.next() {
+ Some(TokenTree::Punct(ref p)) if p.as_char() == ',' => break,
+ Some(tt) => expected_tts.push(tt),
+ None => panic!("expected comma"),
+ }
+ }
+
+ 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);
+
+ 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/src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs b/src/test/ui/proc-macro/auxiliary/expand-with-a-macro.rs
new file mode 100644
index 000000000..d779d57af
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/external-crate-var.rs b/src/test/ui/proc-macro/auxiliary/external-crate-var.rs
new file mode 100644
index 000000000..4319e9212
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/first-second.rs b/src/test/ui/proc-macro/auxiliary/first-second.rs
new file mode 100644
index 000000000..6331608fb
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/gen-lifetime-token.rs b/src/test/ui/proc-macro/auxiliary/gen-lifetime-token.rs
new file mode 100644
index 000000000..d1a1c584f
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs
new file mode 100644
index 000000000..548fefe76
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs
new file mode 100644
index 000000000..d4b67d6b0
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs b/src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs
new file mode 100644
index 000000000..3f3e12eed
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/generate-mod.rs b/src/test/ui/proc-macro/auxiliary/generate-mod.rs
new file mode 100644
index 000000000..e950f7d62
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/hygiene_example.rs b/src/test/ui/proc-macro/auxiliary/hygiene_example.rs
new file mode 100644
index 000000000..f7e7e0b57
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/hygiene_example_codegen.rs b/src/test/ui/proc-macro/auxiliary/hygiene_example_codegen.rs
new file mode 100644
index 000000000..2bd4d3336
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/included-file.txt b/src/test/ui/proc-macro/auxiliary/included-file.txt
new file mode 100644
index 000000000..b4720047d
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/included-file.txt
@@ -0,0 +1 @@
+Included file contents
diff --git a/src/test/ui/proc-macro/auxiliary/invalid-punct-ident.rs b/src/test/ui/proc-macro/auxiliary/invalid-punct-ident.rs
new file mode 100644
index 000000000..518dfd0d6
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/is-available.rs b/src/test/ui/proc-macro/auxiliary/is-available.rs
new file mode 100644
index 000000000..03f5265e3
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-38586.rs b/src/test/ui/proc-macro/auxiliary/issue-38586.rs
new file mode 100644
index 000000000..f3a19081c
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-39889.rs b/src/test/ui/proc-macro/auxiliary/issue-39889.rs
new file mode 100644
index 000000000..e7af66da7
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-42708.rs b/src/test/ui/proc-macro/auxiliary/issue-42708.rs
new file mode 100644
index 000000000..dae05204b
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-50061.rs b/src/test/ui/proc-macro/auxiliary/issue-50061.rs
new file mode 100644
index 000000000..f5fe8cabb
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-50493.rs b/src/test/ui/proc-macro/auxiliary/issue-50493.rs
new file mode 100644
index 000000000..f72024948
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-59191.rs b/src/test/ui/proc-macro/auxiliary/issue-59191.rs
new file mode 100644
index 000000000..d9ee77067
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-66286.rs b/src/test/ui/proc-macro/auxiliary/issue-66286.rs
new file mode 100644
index 000000000..6217f1c7e
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-75801.rs b/src/test/ui/proc-macro/auxiliary/issue-75801.rs
new file mode 100644
index 000000000..d6c031d7d
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-79242.rs b/src/test/ui/proc-macro/auxiliary/issue-79242.rs
new file mode 100644
index 000000000..e586980f0
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-79825.rs b/src/test/ui/proc-macro/auxiliary/issue-79825.rs
new file mode 100644
index 000000000..930891b1d
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-83510.rs b/src/test/ui/proc-macro/auxiliary/issue-83510.rs
new file mode 100644
index 000000000..1d6ef3914
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/issue-91800-macro.rs b/src/test/ui/proc-macro/auxiliary/issue-91800-macro.rs
new file mode 100644
index 000000000..958a8bed9
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/lifetimes-rpass.rs b/src/test/ui/proc-macro/auxiliary/lifetimes-rpass.rs
new file mode 100644
index 000000000..4e5d22e6e
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/lifetimes.rs b/src/test/ui/proc-macro/auxiliary/lifetimes.rs
new file mode 100644
index 000000000..212164dd2
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs b/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs
new file mode 100644
index 000000000..c72306c3d
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/make-macro.rs b/src/test/ui/proc-macro/auxiliary/make-macro.rs
new file mode 100644
index 000000000..3c851b6de
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/meta-delim.rs b/src/test/ui/proc-macro/auxiliary/meta-delim.rs
new file mode 100644
index 000000000..54e3d7857
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/meta-macro.rs b/src/test/ui/proc-macro/auxiliary/meta-macro.rs
new file mode 100644
index 000000000..0a9b9887d
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/mixed-site-span.rs b/src/test/ui/proc-macro/auxiliary/mixed-site-span.rs
new file mode 100644
index 000000000..c2a498700
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/modify-ast.rs b/src/test/ui/proc-macro/auxiliary/modify-ast.rs
new file mode 100644
index 000000000..cc582c152
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/multiple-derives.rs b/src/test/ui/proc-macro/auxiliary/multiple-derives.rs
new file mode 100644
index 000000000..e3f6607b2
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/multispan.rs b/src/test/ui/proc-macro/auxiliary/multispan.rs
new file mode 100644
index 000000000..c05d15643
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/negative-token.rs b/src/test/ui/proc-macro/auxiliary/negative-token.rs
new file mode 100644
index 000000000..8b89f2e37
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/nested-macro-rules.rs
new file mode 100644
index 000000000..27676a5cb
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs b/src/test/ui/proc-macro/auxiliary/nonterminal-recollect-attr.rs
new file mode 100644
index 000000000..ea5ff4665
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/not-joint.rs b/src/test/ui/proc-macro/auxiliary/not-joint.rs
new file mode 100644
index 000000000..e6c09f762
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/parent-source-spans.rs b/src/test/ui/proc-macro/auxiliary/parent-source-spans.rs
new file mode 100644
index 000000000..594f10883
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs b/src/test/ui/proc-macro/auxiliary/proc-macro-panic.rs
new file mode 100644
index 000000000..fc15bb9c5
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/raw-ident.rs b/src/test/ui/proc-macro/auxiliary/raw-ident.rs
new file mode 100644
index 000000000..9daee21aa
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/recollect.rs b/src/test/ui/proc-macro/auxiliary/recollect.rs
new file mode 100644
index 000000000..d4494a5af
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/resolved-located-at.rs b/src/test/ui/proc-macro/auxiliary/resolved-located-at.rs
new file mode 100644
index 000000000..db660824f
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/span-api-tests.rs b/src/test/ui/proc-macro/auxiliary/span-api-tests.rs
new file mode 100644
index 000000000..ad1e770a4
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/span-from-proc-macro.rs b/src/test/ui/proc-macro/auxiliary/span-from-proc-macro.rs
new file mode 100644
index 000000000..49292acfe
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/span-test-macros.rs b/src/test/ui/proc-macro/auxiliary/span-test-macros.rs
new file mode 100644
index 000000000..9a78f0a89
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/subspan.rs b/src/test/ui/proc-macro/auxiliary/subspan.rs
new file mode 100644
index 000000000..f92adc040
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/test-macros.rs b/src/test/ui/proc-macro/auxiliary/test-macros.rs
new file mode 100644
index 000000000..7a46aee46
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/three-equals.rs b/src/test/ui/proc-macro/auxiliary/three-equals.rs
new file mode 100644
index 000000000..e740e86e5
--- /dev/null
+++ b/src/test/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/src/test/ui/proc-macro/auxiliary/weird-hygiene.rs b/src/test/ui/proc-macro/auxiliary/weird-hygiene.rs
new file mode 100644
index 000000000..338e436df
--- /dev/null
+++ b/src/test/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()
+}
diff --git a/src/test/ui/proc-macro/bang-macro.rs b/src/test/ui/proc-macro/bang-macro.rs
new file mode 100644
index 000000000..928107913
--- /dev/null
+++ b/src/test/ui/proc-macro/bang-macro.rs
@@ -0,0 +1,9 @@
+// run-pass
+// aux-build:bang-macro.rs
+
+extern crate bang_macro;
+use bang_macro::rewrite;
+
+fn main() {
+ assert_eq!(rewrite!("Hello, world!"), "NOT Hello, world!");
+}
diff --git a/src/test/ui/proc-macro/break-token-spans.rs b/src/test/ui/proc-macro/break-token-spans.rs
new file mode 100644
index 000000000..59dc3b504
--- /dev/null
+++ b/src/test/ui/proc-macro/break-token-spans.rs
@@ -0,0 +1,16 @@
+// aux-build:test-macros.rs
+// Regression test for issues #68489 and #70987
+// Tests that we properly break tokens in `probably_equal_for_proc_macro`
+// See #72306
+//
+// Note that the weird spacing in this example is critical
+// for testing the issue.
+
+extern crate test_macros;
+
+#[test_macros::recollect_attr]
+fn repro() {
+ f :: < Vec < _ > > ( ) ; //~ ERROR cannot find
+ let a: Option<Option<u8>>= true; //~ ERROR mismatched
+}
+fn main() {}
diff --git a/src/test/ui/proc-macro/break-token-spans.stderr b/src/test/ui/proc-macro/break-token-spans.stderr
new file mode 100644
index 000000000..0a0322b8a
--- /dev/null
+++ b/src/test/ui/proc-macro/break-token-spans.stderr
@@ -0,0 +1,21 @@
+error[E0425]: cannot find function `f` in this scope
+ --> $DIR/break-token-spans.rs:13:5
+ |
+LL | f :: < Vec < _ > > ( ) ;
+ | ^ not found in this scope
+
+error[E0308]: mismatched types
+ --> $DIR/break-token-spans.rs:14:32
+ |
+LL | let a: Option<Option<u8>>= true;
+ | ------------------ ^^^^ expected enum `Option`, found `bool`
+ | |
+ | expected due to this
+ |
+ = note: expected enum `Option<Option<u8>>`
+ found type `bool`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/call-deprecated.rs b/src/test/ui/proc-macro/call-deprecated.rs
new file mode 100644
index 000000000..b92cc2363
--- /dev/null
+++ b/src/test/ui/proc-macro/call-deprecated.rs
@@ -0,0 +1,34 @@
+// check-pass
+// aux-build:call-deprecated.rs
+
+extern crate call_deprecated;
+
+// These first two `#[allow(deprecated)]` attributes
+// do nothing, since the AST nodes for `First` and `Second`
+// haven't been been assigned a `NodeId`.
+// See #63221 for a discussion about how we should
+// handle the interaction of 'inert' attributes and
+// proc-macro attributes.
+
+#[allow(deprecated)]
+#[call_deprecated::attr] //~ WARN use of deprecated macro
+struct First;
+
+#[allow(deprecated)]
+#[call_deprecated::attr_remove] //~ WARN use of deprecated macro
+struct Second;
+
+#[allow(deprecated)]
+mod bar {
+ #[allow(deprecated)]
+ #[call_deprecated::attr]
+ struct Third;
+
+ #[allow(deprecated)]
+ #[call_deprecated::attr_remove]
+ struct Fourth;
+}
+
+
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/call-deprecated.stderr b/src/test/ui/proc-macro/call-deprecated.stderr
new file mode 100644
index 000000000..3506f9a16
--- /dev/null
+++ b/src/test/ui/proc-macro/call-deprecated.stderr
@@ -0,0 +1,16 @@
+warning: use of deprecated macro `call_deprecated::attr`: test
+ --> $DIR/call-deprecated.rs:14:3
+ |
+LL | #[call_deprecated::attr]
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(deprecated)]` on by default
+
+warning: use of deprecated macro `call_deprecated::attr_remove`: test
+ --> $DIR/call-deprecated.rs:18:3
+ |
+LL | #[call_deprecated::attr_remove]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/proc-macro/call-site.rs b/src/test/ui/proc-macro/call-site.rs
new file mode 100644
index 000000000..12c77250c
--- /dev/null
+++ b/src/test/ui/proc-macro/call-site.rs
@@ -0,0 +1,10 @@
+// check-pass
+// aux-build:call-site.rs
+
+extern crate call_site;
+
+fn main() {
+ let x1 = 10;
+ call_site::check!(let x2 = x1;);
+ let x6 = x5;
+}
diff --git a/src/test/ui/proc-macro/capture-macro-rules-invoke.rs b/src/test/ui/proc-macro/capture-macro-rules-invoke.rs
new file mode 100644
index 000000000..de008a370
--- /dev/null
+++ b/src/test/ui/proc-macro/capture-macro-rules-invoke.rs
@@ -0,0 +1,57 @@
+// aux-build:test-macros.rs
+// check-pass
+// compile-flags: -Z span-debug
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate test_macros;
+use test_macros::{print_bang, print_bang_consume};
+
+macro_rules! test_matchers {
+ ($expr:expr, $block:block, $stmt:stmt, $ty:ty, $ident:ident, $lifetime:lifetime,
+ $meta:meta, $path:path, $vis:vis, $tt:tt, $lit:literal) => {
+ print_bang_consume!($expr, $block, $stmt, $ty, $ident,
+ $lifetime, $meta, $path, $vis, $tt, $lit)
+ }
+}
+
+macro_rules! use_expr {
+ ($expr:expr) => {
+ print_bang!($expr)
+ }
+}
+
+macro_rules! use_pat {
+ ($pat:pat) => {
+ print_bang!($pat)
+ }
+}
+
+#[allow(dead_code)]
+struct Foo;
+impl Foo {
+ #[allow(dead_code)]
+ fn use_self(self) {
+ drop(use_expr!(self));
+ test_matchers!(
+ 1 + 1,
+ { "a" },
+ let a = 1,
+ String,
+ my_name,
+ 'a,
+ my_val = 30,
+ std::option::Option,
+ pub(in some::path),
+ [ a b c ],
+ -30
+ );
+ }
+
+ fn with_pat(use_pat!((a, b)): (u32, u32)) {
+ let _ = (a, b);
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout
new file mode 100644
index 000000000..4de8746a1
--- /dev/null
+++ b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout
@@ -0,0 +1,324 @@
+PRINT-BANG INPUT (DISPLAY): self
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "self",
+ span: $DIR/capture-macro-rules-invoke.rs:36:24: 36:28 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:21:21: 21:26 (#4),
+ },
+]
+PRINT-BANG INPUT (DISPLAY): 1 + 1, { "a" }, let a = 1;, String, my_name, 'a, my_val = 30,
+std::option::Option, pub(in some::path) , [a b c], -30
+PRINT-BANG RE-COLLECTED (DISPLAY): 1 + 1, { "a" }, let a = 1, String, my_name, 'a, my_val = 30,
+std :: option :: Option, pub(in some :: path), [a b c], - 30
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/capture-macro-rules-invoke.rs:38:13: 38:14 (#0),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:38:15: 38:16 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/capture-macro-rules-invoke.rs:38:17: 38:18 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:14:29: 14:34 (#8),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:14:34: 14:35 (#8),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Literal {
+ kind: Str,
+ symbol: "a",
+ suffix: None,
+ span: $DIR/capture-macro-rules-invoke.rs:39:15: 39:18 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:39:13: 39:20 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:14:36: 14:42 (#8),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:14:42: 14:43 (#8),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "let",
+ span: $DIR/capture-macro-rules-invoke.rs:40:13: 40:16 (#0),
+ },
+ Ident {
+ ident: "a",
+ span: $DIR/capture-macro-rules-invoke.rs:40:17: 40:18 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:40:19: 40:20 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/capture-macro-rules-invoke.rs:40:21: 40:22 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:14:44: 14:49 (#8),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:14:49: 14:50 (#8),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "String",
+ span: $DIR/capture-macro-rules-invoke.rs:41:13: 41:19 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:14:51: 14:54 (#8),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:14:54: 14:55 (#8),
+ },
+ Ident {
+ ident: "my_name",
+ span: $DIR/capture-macro-rules-invoke.rs:42:13: 42:20 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:14:62: 14:63 (#8),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Punct {
+ ch: '\'',
+ spacing: Joint,
+ span: $DIR/capture-macro-rules-invoke.rs:43:13: 43:15 (#0),
+ },
+ Ident {
+ ident: "a",
+ span: $DIR/capture-macro-rules-invoke.rs:43:13: 43:15 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:15:29: 15:38 (#8),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:15:38: 15:39 (#8),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "my_val",
+ span: $DIR/capture-macro-rules-invoke.rs:44:13: 44:19 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:44:20: 44:21 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "30",
+ suffix: None,
+ span: $DIR/capture-macro-rules-invoke.rs:44:22: 44:24 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:15:40: 15:45 (#8),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:15:45: 15:46 (#8),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "std",
+ span: $DIR/capture-macro-rules-invoke.rs:45:13: 45:16 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/capture-macro-rules-invoke.rs:45:16: 45:18 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:45:16: 45:18 (#0),
+ },
+ Ident {
+ ident: "option",
+ span: $DIR/capture-macro-rules-invoke.rs:45:18: 45:24 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/capture-macro-rules-invoke.rs:45:24: 45:26 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:45:24: 45:26 (#0),
+ },
+ Ident {
+ ident: "Option",
+ span: $DIR/capture-macro-rules-invoke.rs:45:26: 45:32 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:15:47: 15:52 (#8),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:15:52: 15:53 (#8),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "pub",
+ span: $DIR/capture-macro-rules-invoke.rs:46:13: 46:16 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "in",
+ span: $DIR/capture-macro-rules-invoke.rs:46:17: 46:19 (#0),
+ },
+ Ident {
+ ident: "some",
+ span: $DIR/capture-macro-rules-invoke.rs:46:20: 46:24 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/capture-macro-rules-invoke.rs:46:24: 46:26 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:46:24: 46:26 (#0),
+ },
+ Ident {
+ ident: "path",
+ span: $DIR/capture-macro-rules-invoke.rs:46:26: 46:30 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:46:16: 46:31 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:15:54: 15:58 (#8),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:15:58: 15:59 (#8),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "a",
+ span: $DIR/capture-macro-rules-invoke.rs:47:15: 47:16 (#0),
+ },
+ Ident {
+ ident: "b",
+ span: $DIR/capture-macro-rules-invoke.rs:47:17: 47:18 (#0),
+ },
+ Ident {
+ ident: "c",
+ span: $DIR/capture-macro-rules-invoke.rs:47:19: 47:20 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:47:13: 47:22 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:15:63: 15:64 (#8),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Punct {
+ ch: '-',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:48:13: 48:14 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "30",
+ suffix: None,
+ span: $DIR/capture-macro-rules-invoke.rs:48:14: 48:16 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:15:65: 15:69 (#8),
+ },
+]
+PRINT-BANG INPUT (DISPLAY): (a, b)
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "a",
+ span: $DIR/capture-macro-rules-invoke.rs:52:27: 52:28 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/capture-macro-rules-invoke.rs:52:28: 52:29 (#0),
+ },
+ Ident {
+ ident: "b",
+ span: $DIR/capture-macro-rules-invoke.rs:52:30: 52:31 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:52:26: 52:32 (#0),
+ },
+ ],
+ span: $DIR/capture-macro-rules-invoke.rs:27:21: 27:25 (#12),
+ },
+]
diff --git a/src/test/ui/proc-macro/capture-unglued-token.rs b/src/test/ui/proc-macro/capture-unglued-token.rs
new file mode 100644
index 000000000..727b77977
--- /dev/null
+++ b/src/test/ui/proc-macro/capture-unglued-token.rs
@@ -0,0 +1,20 @@
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+// check-pass
+
+// Tests that we properly handle parsing a nonterminal
+// where we have two consecutive angle brackets (one inside
+// the nonterminal, and one outside)
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+extern crate test_macros;
+
+macro_rules! trailing_angle {
+ (Option<$field:ty>) => {
+ test_macros::print_bang_consume!($field);
+ }
+}
+
+trailing_angle!(Option<Vec<u8>>);
+fn main() {}
diff --git a/src/test/ui/proc-macro/capture-unglued-token.stdout b/src/test/ui/proc-macro/capture-unglued-token.stdout
new file mode 100644
index 000000000..7e6b54033
--- /dev/null
+++ b/src/test/ui/proc-macro/capture-unglued-token.stdout
@@ -0,0 +1,28 @@
+PRINT-BANG INPUT (DISPLAY): Vec<u8>
+PRINT-BANG RE-COLLECTED (DISPLAY): Vec < u8 >
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "Vec",
+ span: $DIR/capture-unglued-token.rs:19:24: 19:27 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/capture-unglued-token.rs:19:27: 19:28 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/capture-unglued-token.rs:19:28: 19:30 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/capture-unglued-token.rs:19:30: 19:31 (#0),
+ },
+ ],
+ span: $DIR/capture-unglued-token.rs:15:42: 15:48 (#4),
+ },
+]
diff --git a/src/test/ui/proc-macro/cfg-eval-fail.rs b/src/test/ui/proc-macro/cfg-eval-fail.rs
new file mode 100644
index 000000000..a259aa2e6
--- /dev/null
+++ b/src/test/ui/proc-macro/cfg-eval-fail.rs
@@ -0,0 +1,7 @@
+#![feature(cfg_eval)]
+#![feature(stmt_expr_attributes)]
+
+fn main() {
+ let _ = #[cfg_eval] #[cfg(FALSE)] 0;
+ //~^ ERROR removing an expression is not supported in this position
+}
diff --git a/src/test/ui/proc-macro/cfg-eval-fail.stderr b/src/test/ui/proc-macro/cfg-eval-fail.stderr
new file mode 100644
index 000000000..df8b6d5f3
--- /dev/null
+++ b/src/test/ui/proc-macro/cfg-eval-fail.stderr
@@ -0,0 +1,8 @@
+error: removing an expression is not supported in this position
+ --> $DIR/cfg-eval-fail.rs:5:25
+ |
+LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0;
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/cfg-eval-inner.rs b/src/test/ui/proc-macro/cfg-eval-inner.rs
new file mode 100644
index 000000000..5fd3ca0d1
--- /dev/null
+++ b/src/test/ui/proc-macro/cfg-eval-inner.rs
@@ -0,0 +1,39 @@
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+// check-pass
+
+#![feature(cfg_eval)]
+#![feature(custom_inner_attributes)]
+#![feature(stmt_expr_attributes)]
+#![feature(rustc_attrs)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+struct Foo<T>(T);
+
+impl Foo<[u8; {
+ #![cfg_attr(not(FALSE), rustc_dummy(cursed_inner))]
+ #![allow(unused)]
+ struct Inner {
+ field: [u8; {
+ #![cfg_attr(not(FALSE), rustc_dummy(another_cursed_inner))]
+ 1
+ }]
+ }
+
+ 0
+}]> {
+ #![cfg_eval]
+ #![print_attr]
+ #![cfg_attr(not(FALSE), rustc_dummy(evaluated_attr))]
+
+ fn bar() {
+ #[cfg(FALSE)] let a = 1;
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/cfg-eval-inner.stdout b/src/test/ui/proc-macro/cfg-eval-inner.stdout
new file mode 100644
index 000000000..9d25def58
--- /dev/null
+++ b/src/test/ui/proc-macro/cfg-eval-inner.stdout
@@ -0,0 +1,247 @@
+PRINT-ATTR INPUT (DISPLAY): impl Foo <
+[u8 ;
+{
+ #! [rustc_dummy(cursed_inner)] #! [allow(unused)] struct Inner
+ { field : [u8 ; { #! [rustc_dummy(another_cursed_inner)] 1 }] } 0
+}] > { #! [rustc_dummy(evaluated_attr)] fn bar() {} }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "impl",
+ span: $DIR/cfg-eval-inner.rs:18:1: 18:5 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/cfg-eval-inner.rs:18:6: 18:9 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:18:9: 18:10 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "u8",
+ span: $DIR/cfg-eval-inner.rs:18:11: 18:13 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:18:13: 18:14 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:19:5: 19:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:19:6: 19:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/cfg-eval-inner.rs:19:29: 19:40 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "cursed_inner",
+ span: $DIR/cfg-eval-inner.rs:19:41: 19:53 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:19:40: 19:54 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:19:5: 19:6 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/cfg-eval-inner.rs:20:5: 20:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:20:6: 20:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/cfg-eval-inner.rs:20:8: 20:13 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "unused",
+ span: $DIR/cfg-eval-inner.rs:20:14: 20:20 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:20:13: 20:21 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:20:7: 20:22 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/cfg-eval-inner.rs:21:5: 21:11 (#0),
+ },
+ Ident {
+ ident: "Inner",
+ span: $DIR/cfg-eval-inner.rs:21:12: 21:17 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "field",
+ span: $DIR/cfg-eval-inner.rs:22:9: 22:14 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:22:14: 22:15 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "u8",
+ span: $DIR/cfg-eval-inner.rs:22:17: 22:19 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:22:19: 22:20 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:23:13: 23:14 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:23:14: 23:15 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/cfg-eval-inner.rs:23:37: 23:48 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "another_cursed_inner",
+ span: $DIR/cfg-eval-inner.rs:23:49: 23:69 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:23:48: 23:70 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:23:13: 23:14 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/cfg-eval-inner.rs:24:13: 24:14 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:22:21: 25:10 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:22:16: 25:11 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:21:18: 26:6 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/cfg-eval-inner.rs:28:5: 28:6 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:18:15: 29:2 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:18:10: 29:3 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:29:3: 29:4 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:32:5: 32:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/cfg-eval-inner.rs:32:6: 32:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/cfg-eval-inner.rs:32:29: 32:40 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "evaluated_attr",
+ span: $DIR/cfg-eval-inner.rs:32:41: 32:55 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:32:40: 32:56 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:32:5: 32:6 (#0),
+ },
+ Ident {
+ ident: "fn",
+ span: $DIR/cfg-eval-inner.rs:34:5: 34:7 (#0),
+ },
+ Ident {
+ ident: "bar",
+ span: $DIR/cfg-eval-inner.rs:34:8: 34:11 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/cfg-eval-inner.rs:34:11: 34:13 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/cfg-eval-inner.rs:34:14: 36:6 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval-inner.rs:29:5: 37:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/cfg-eval.rs b/src/test/ui/proc-macro/cfg-eval.rs
new file mode 100644
index 000000000..fa6d015e4
--- /dev/null
+++ b/src/test/ui/proc-macro/cfg-eval.rs
@@ -0,0 +1,37 @@
+// check-pass
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+
+#![feature(cfg_eval)]
+#![feature(proc_macro_hygiene)]
+#![feature(stmt_expr_attributes)]
+#![feature(rustc_attrs)]
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+#[cfg_eval]
+#[print_attr]
+struct S1 {
+ #[cfg(FALSE)]
+ field_false: u8,
+ #[cfg(all(/*true*/))]
+ #[cfg_attr(FALSE, unknown_attr)]
+ #[cfg_attr(all(/*true*/), allow())]
+ field_true: u8,
+}
+
+#[cfg_eval]
+#[cfg(FALSE)]
+struct S2 {}
+
+fn main() {
+ // Subtle - we need a trailing comma after the '1' - otherwise, `#[cfg_eval]` will
+ // turn this into `(#[cfg(all())] 1)`, which is a parenthesized expression, not a tuple
+ // expression. `#[cfg]` is not supported inside parenthesized expressions, so this will
+ // produce an error when attribute collection runs.
+ let _ = #[cfg_eval] #[print_attr] #[cfg_attr(not(FALSE), rustc_dummy)]
+ (#[cfg(FALSE)] 0, #[cfg(all(/*true*/))] 1,);
+}
diff --git a/src/test/ui/proc-macro/cfg-eval.stdout b/src/test/ui/proc-macro/cfg-eval.stdout
new file mode 100644
index 000000000..6732caf08
--- /dev/null
+++ b/src/test/ui/proc-macro/cfg-eval.stdout
@@ -0,0 +1,150 @@
+PRINT-ATTR INPUT (DISPLAY): struct S1 { #[cfg(all())] #[allow()] field_true : u8, }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/cfg-eval.rs:17:1: 17:7 (#0),
+ },
+ Ident {
+ ident: "S1",
+ span: $DIR/cfg-eval.rs:17:8: 17:10 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/cfg-eval.rs:20:5: 20:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/cfg-eval.rs:20:7: 20:10 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "all",
+ span: $DIR/cfg-eval.rs:20:11: 20:14 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/cfg-eval.rs:20:14: 20:24 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval.rs:20:10: 20:25 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval.rs:20:6: 20:26 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/cfg-eval.rs:22:5: 22:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/cfg-eval.rs:22:31: 22:36 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/cfg-eval.rs:22:36: 22:38 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval.rs:22:5: 22:6 (#0),
+ },
+ Ident {
+ ident: "field_true",
+ span: $DIR/cfg-eval.rs:23:5: 23:15 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/cfg-eval.rs:23:15: 23:16 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/cfg-eval.rs:23:17: 23:19 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/cfg-eval.rs:23:19: 23:20 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval.rs:17:11: 24:2 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] (#[cfg(all())] 1,)
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/cfg-eval.rs:35:39: 35:40 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/cfg-eval.rs:35:62: 35:73 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval.rs:35:39: 35:40 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/cfg-eval.rs:36:23: 36:24 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/cfg-eval.rs:36:25: 36:28 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "all",
+ span: $DIR/cfg-eval.rs:36:29: 36:32 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/cfg-eval.rs:36:32: 36:42 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval.rs:36:28: 36:43 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval.rs:36:24: 36:44 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/cfg-eval.rs:36:45: 36:46 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/cfg-eval.rs:36:46: 36:47 (#0),
+ },
+ ],
+ span: $DIR/cfg-eval.rs:36:5: 36:48 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/count_compound_ops.rs b/src/test/ui/proc-macro/count_compound_ops.rs
new file mode 100644
index 000000000..2cb871844
--- /dev/null
+++ b/src/test/ui/proc-macro/count_compound_ops.rs
@@ -0,0 +1,9 @@
+// run-pass
+// aux-build:count_compound_ops.rs
+
+extern crate count_compound_ops;
+use count_compound_ops::count_compound_ops;
+
+fn main() {
+ assert_eq!(count_compound_ops!(foo<=>bar <<<! -baz ++), 4);
+}
diff --git a/src/test/ui/proc-macro/crate-attrs-multiple.rs b/src/test/ui/proc-macro/crate-attrs-multiple.rs
new file mode 100644
index 000000000..29a0eca41
--- /dev/null
+++ b/src/test/ui/proc-macro/crate-attrs-multiple.rs
@@ -0,0 +1,14 @@
+// Multiple custom crate-level attributes, both inert and active.
+
+// check-pass
+// aux-crate:test_macros=test-macros.rs
+
+#![feature(custom_inner_attributes)]
+#![feature(prelude_import)]
+
+#![test_macros::identity_attr]
+#![rustfmt::skip]
+#![test_macros::identity_attr]
+#![rustfmt::skip]
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/crate-var.rs b/src/test/ui/proc-macro/crate-var.rs
new file mode 100644
index 000000000..c0518e4b0
--- /dev/null
+++ b/src/test/ui/proc-macro/crate-var.rs
@@ -0,0 +1,61 @@
+// run-pass
+// aux-build:double.rs
+// aux-build:external-crate-var.rs
+
+#![allow(unused)]
+
+#[macro_use]
+extern crate double;
+#[macro_use]
+extern crate external_crate_var;
+
+struct Foo;
+
+trait Trait {
+ const CONST: u32;
+ type Assoc;
+}
+
+impl Trait for Foo {
+ const CONST: u32 = 0;
+ type Assoc = Foo;
+}
+
+macro_rules! local { () => {
+ // derive_Double outputs secondary copies of each definition
+ // to test what the proc_macro sees.
+ mod bar {
+ #[derive(Double)]
+ struct Bar($crate::Foo);
+ }
+
+ mod qself {
+ #[derive(Double)]
+ struct QSelf(<::Foo as $crate::Trait>::Assoc);
+ }
+
+ mod qself_recurse {
+ #[derive(Double)]
+ struct QSelfRecurse(<<$crate::Foo as $crate::Trait>::Assoc as $crate::Trait>::Assoc);
+ }
+
+ mod qself_in_const {
+ #[derive(Double)]
+ #[repr(u32)]
+ enum QSelfInConst {
+ Variant = <::Foo as $crate::Trait>::CONST,
+ }
+ }
+} }
+
+mod local {
+ local!();
+}
+
+// and now repeat the above tests, using a macro defined in another crate
+
+mod external {
+ external!{}
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/crt-static.rs b/src/test/ui/proc-macro/crt-static.rs
new file mode 100644
index 000000000..8c1a9dc80
--- /dev/null
+++ b/src/test/ui/proc-macro/crt-static.rs
@@ -0,0 +1,24 @@
+// Test proc-macro crate can be built without additional RUSTFLAGS
+// on musl target
+// override -Ctarget-feature=-crt-static from compiletest
+// compile-flags: --crate-type proc-macro -Ctarget-feature=
+// ignore-wasm32
+// ignore-sgx no support for proc-macro crate type
+// build-pass
+#![crate_type = "proc-macro"]
+
+// FIXME: This don't work when crate-type is specified by attribute
+// `#![crate_type = "proc-macro"]`, not by `--crate-type=proc-macro`
+// command line flag. This is beacuse the list of `cfg` symbols is generated
+// before attributes are parsed. See rustc_interface::util::add_configuration
+#[cfg(target_feature = "crt-static")]
+compile_error!("crt-static is enabled");
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Foo)]
+pub fn derive_foo(input: TokenStream) -> TokenStream {
+ input
+}
diff --git a/src/test/ui/proc-macro/custom-attr-only-one-derive.rs b/src/test/ui/proc-macro/custom-attr-only-one-derive.rs
new file mode 100644
index 000000000..2cd5b4873
--- /dev/null
+++ b/src/test/ui/proc-macro/custom-attr-only-one-derive.rs
@@ -0,0 +1,16 @@
+// run-pass
+// aux-build:custom-attr-only-one-derive.rs
+
+#![feature(rust_2018_preview)]
+
+#[macro_use]
+extern crate custom_attr_only_one_derive;
+
+#[derive(Bar, Foo)]
+#[custom = "test"]
+pub enum A {
+ B,
+ C,
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs b/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs
new file mode 100644
index 000000000..56ad0612f
--- /dev/null
+++ b/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![crate_name = "macro_dump_debug"]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn dump_debug(tokens: TokenStream) -> TokenStream {
+ eprintln!("{:?}", tokens);
+ eprintln!("{:#?}", tokens);
+ TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs b/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs
new file mode 100644
index 000000000..fd34eb974
--- /dev/null
+++ b/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs
@@ -0,0 +1,41 @@
+// run-pass
+// aux-build:macro-dump-debug.rs
+// compile-flags: -Z span-debug
+
+extern crate macro_dump_debug;
+use macro_dump_debug::dump_debug;
+
+dump_debug! {
+ ident // ident
+ r#ident // raw ident
+ , // alone punct
+ ==> // joint punct
+ () // empty group
+ [_] // nonempty group
+
+ // unsuffixed literals
+ 0
+ 1.0
+ "S"
+ b"B"
+ r"R"
+ r##"R"##
+ br"BR"
+ br##"BR"##
+ 'C'
+ b'B'
+
+ // suffixed literals
+ 0q
+ 1.0q
+ "S"q
+ b"B"q
+ r"R"q
+ r##"R"##q
+ br"BR"q
+ br##"BR"##q
+ 'C'q
+ b'B'q
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr
new file mode 100644
index 000000000..2c05bdbc4
--- /dev/null
+++ b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr
@@ -0,0 +1,166 @@
+TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0) }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0) }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0) }], span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0) }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0) }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0) }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0) }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0) }]
+TokenStream [
+ Ident {
+ ident: "ident",
+ span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0),
+ },
+ Ident {
+ ident: "r#ident",
+ span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "_",
+ span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0),
+ },
+ ],
+ span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0),
+ },
+ Literal {
+ kind: Float,
+ symbol: "1.0",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0),
+ },
+ Literal {
+ kind: Str,
+ symbol: "S",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0),
+ },
+ Literal {
+ kind: ByteStr,
+ symbol: "B",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0),
+ },
+ Literal {
+ kind: StrRaw(0),
+ symbol: "R",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0),
+ },
+ Literal {
+ kind: StrRaw(2),
+ symbol: "R",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0),
+ },
+ Literal {
+ kind: ByteStrRaw(0),
+ symbol: "BR",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0),
+ },
+ Literal {
+ kind: ByteStrRaw(2),
+ symbol: "BR",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0),
+ },
+ Literal {
+ kind: Char,
+ symbol: "C",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0),
+ },
+ Literal {
+ kind: Byte,
+ symbol: "B",
+ suffix: None,
+ span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0),
+ },
+ Literal {
+ kind: Float,
+ symbol: "1.0",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0),
+ },
+ Literal {
+ kind: Str,
+ symbol: "S",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0),
+ },
+ Literal {
+ kind: ByteStr,
+ symbol: "B",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0),
+ },
+ Literal {
+ kind: StrRaw(0),
+ symbol: "R",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0),
+ },
+ Literal {
+ kind: StrRaw(2),
+ symbol: "R",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0),
+ },
+ Literal {
+ kind: ByteStrRaw(0),
+ symbol: "BR",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0),
+ },
+ Literal {
+ kind: ByteStrRaw(2),
+ symbol: "BR",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0),
+ },
+ Literal {
+ kind: Char,
+ symbol: "C",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0),
+ },
+ Literal {
+ kind: Byte,
+ symbol: "B",
+ suffix: Some("q"),
+ span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/debug/dump-debug.rs b/src/test/ui/proc-macro/debug/dump-debug.rs
new file mode 100644
index 000000000..0ed36b690
--- /dev/null
+++ b/src/test/ui/proc-macro/debug/dump-debug.rs
@@ -0,0 +1,40 @@
+// run-pass
+// aux-build:macro-dump-debug.rs
+
+extern crate macro_dump_debug;
+use macro_dump_debug::dump_debug;
+
+dump_debug! {
+ ident // ident
+ r#ident // raw ident
+ , // alone punct
+ ==> // joint punct
+ () // empty group
+ [_] // nonempty group
+
+ // unsuffixed literals
+ 0
+ 1.0
+ "S"
+ b"B"
+ r"R"
+ r##"R"##
+ br"BR"
+ br##"BR"##
+ 'C'
+ b'B'
+
+ // suffixed literals
+ 0q
+ 1.0q
+ "S"q
+ b"B"q
+ r"R"q
+ r##"R"##q
+ br"BR"q
+ br##"BR"##q
+ 'C'q
+ b'B'q
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/debug/dump-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug.stderr
new file mode 100644
index 000000000..0aedefd4e
--- /dev/null
+++ b/src/test/ui/proc-macro/debug/dump-debug.stderr
@@ -0,0 +1,166 @@
+TokenStream [Ident { ident: "ident", span: #0 bytes(130..135) }, Ident { ident: "r#ident", span: #0 bytes(151..158) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(176..177) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(205..206) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(230..232) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(258..259) }], span: #0 bytes(257..260) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(315..316) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(321..324) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(329..332) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(337..341) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(346..350) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(355..363) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(368..374) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(379..389) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(394..397) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(402..406) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(437..439) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(444..448) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(453..457) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(462..467) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(472..477) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(482..491) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(496..503) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(508..519) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(524..528) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(533..538) }]
+TokenStream [
+ Ident {
+ ident: "ident",
+ span: #0 bytes(130..135),
+ },
+ Ident {
+ ident: "r#ident",
+ span: #0 bytes(151..158),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: #0 bytes(176..177),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: #0 bytes(203..205),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: #0 bytes(203..205),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: #0 bytes(205..206),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: #0 bytes(230..232),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "_",
+ span: #0 bytes(258..259),
+ },
+ ],
+ span: #0 bytes(257..260),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #0 bytes(315..316),
+ },
+ Literal {
+ kind: Float,
+ symbol: "1.0",
+ suffix: None,
+ span: #0 bytes(321..324),
+ },
+ Literal {
+ kind: Str,
+ symbol: "S",
+ suffix: None,
+ span: #0 bytes(329..332),
+ },
+ Literal {
+ kind: ByteStr,
+ symbol: "B",
+ suffix: None,
+ span: #0 bytes(337..341),
+ },
+ Literal {
+ kind: StrRaw(0),
+ symbol: "R",
+ suffix: None,
+ span: #0 bytes(346..350),
+ },
+ Literal {
+ kind: StrRaw(2),
+ symbol: "R",
+ suffix: None,
+ span: #0 bytes(355..363),
+ },
+ Literal {
+ kind: ByteStrRaw(0),
+ symbol: "BR",
+ suffix: None,
+ span: #0 bytes(368..374),
+ },
+ Literal {
+ kind: ByteStrRaw(2),
+ symbol: "BR",
+ suffix: None,
+ span: #0 bytes(379..389),
+ },
+ Literal {
+ kind: Char,
+ symbol: "C",
+ suffix: None,
+ span: #0 bytes(394..397),
+ },
+ Literal {
+ kind: Byte,
+ symbol: "B",
+ suffix: None,
+ span: #0 bytes(402..406),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: Some("q"),
+ span: #0 bytes(437..439),
+ },
+ Literal {
+ kind: Float,
+ symbol: "1.0",
+ suffix: Some("q"),
+ span: #0 bytes(444..448),
+ },
+ Literal {
+ kind: Str,
+ symbol: "S",
+ suffix: Some("q"),
+ span: #0 bytes(453..457),
+ },
+ Literal {
+ kind: ByteStr,
+ symbol: "B",
+ suffix: Some("q"),
+ span: #0 bytes(462..467),
+ },
+ Literal {
+ kind: StrRaw(0),
+ symbol: "R",
+ suffix: Some("q"),
+ span: #0 bytes(472..477),
+ },
+ Literal {
+ kind: StrRaw(2),
+ symbol: "R",
+ suffix: Some("q"),
+ span: #0 bytes(482..491),
+ },
+ Literal {
+ kind: ByteStrRaw(0),
+ symbol: "BR",
+ suffix: Some("q"),
+ span: #0 bytes(496..503),
+ },
+ Literal {
+ kind: ByteStrRaw(2),
+ symbol: "BR",
+ suffix: Some("q"),
+ span: #0 bytes(508..519),
+ },
+ Literal {
+ kind: Char,
+ symbol: "C",
+ suffix: Some("q"),
+ span: #0 bytes(524..528),
+ },
+ Literal {
+ kind: Byte,
+ symbol: "B",
+ suffix: Some("q"),
+ span: #0 bytes(533..538),
+ },
+]
diff --git a/src/test/ui/proc-macro/define-two.rs b/src/test/ui/proc-macro/define-two.rs
new file mode 100644
index 000000000..b2184eae3
--- /dev/null
+++ b/src/test/ui/proc-macro/define-two.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(A)]
+pub fn foo(input: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_derive(A)] //~ ERROR the name `A` is defined multiple times
+pub fn bar(input: TokenStream) -> TokenStream {
+ input
+}
diff --git a/src/test/ui/proc-macro/define-two.stderr b/src/test/ui/proc-macro/define-two.stderr
new file mode 100644
index 000000000..bf1bd8427
--- /dev/null
+++ b/src/test/ui/proc-macro/define-two.stderr
@@ -0,0 +1,14 @@
+error[E0428]: the name `A` is defined multiple times
+ --> $DIR/define-two.rs:15:21
+ |
+LL | #[proc_macro_derive(A)]
+ | - previous definition of the macro `A` here
+...
+LL | #[proc_macro_derive(A)]
+ | ^ `A` redefined here
+ |
+ = note: `A` must be defined only once in the macro namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/proc-macro/derive-attr-cfg.rs b/src/test/ui/proc-macro/derive-attr-cfg.rs
new file mode 100644
index 000000000..394774628
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-attr-cfg.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![allow(dead_code)]
+// aux-build:derive-attr-cfg.rs
+
+extern crate derive_attr_cfg;
+use derive_attr_cfg::Foo;
+
+#[derive(Foo)]
+#[foo]
+struct S {
+ #[cfg(any())]
+ x: i32
+}
+
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/derive-b.rs b/src/test/ui/proc-macro/derive-b.rs
new file mode 100644
index 000000000..a026c2bd7
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-b.rs
@@ -0,0 +1,19 @@
+// run-pass
+// aux-build:derive-b-rpass.rs
+
+extern crate derive_b_rpass as derive_b;
+
+#[derive(Debug, PartialEq, derive_b::B, Eq, Copy, Clone)]
+#[cfg_attr(all(), B[arbitrary tokens])]
+struct B {
+ #[C]
+ a: u64
+}
+
+fn main() {
+ B { a: 3 };
+ assert_eq!(B { a: 3 }, B { a: 3 });
+ let b = B { a: 3 };
+ let _d = b;
+ let _e = b;
+}
diff --git a/src/test/ui/proc-macro/derive-bad.rs b/src/test/ui/proc-macro/derive-bad.rs
new file mode 100644
index 000000000..cb5188b5f
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-bad.rs
@@ -0,0 +1,11 @@
+// aux-build:derive-bad.rs
+
+#[macro_use]
+extern crate derive_bad;
+
+#[derive(A)]
+//~^ ERROR proc-macro derive produced unparseable tokens
+//~| ERROR expected `:`, found `}`
+struct A; //~ ERROR the name `A` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-bad.stderr b/src/test/ui/proc-macro/derive-bad.stderr
new file mode 100644
index 000000000..ae48141fb
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-bad.stderr
@@ -0,0 +1,28 @@
+error: expected `:`, found `}`
+ --> $DIR/derive-bad.rs:6:10
+ |
+LL | #[derive(A)]
+ | ^ expected `:`
+ |
+ = note: this error originates in the derive macro `A` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: proc-macro derive produced unparseable tokens
+ --> $DIR/derive-bad.rs:6:10
+ |
+LL | #[derive(A)]
+ | ^
+
+error[E0428]: the name `A` is defined multiple times
+ --> $DIR/derive-bad.rs:9:1
+ |
+LL | #[derive(A)]
+ | - previous definition of the type `A` here
+...
+LL | struct A;
+ | ^^^^^^^^^ `A` redefined here
+ |
+ = note: `A` must be defined only once in the type namespace of this module
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/proc-macro/derive-expand-order.rs b/src/test/ui/proc-macro/derive-expand-order.rs
new file mode 100644
index 000000000..0cf1ceb91
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-expand-order.rs
@@ -0,0 +1,14 @@
+// run-pass
+// aux-build:multiple-derives.rs
+
+extern crate multiple_derives;
+
+use multiple_derives::*;
+
+#[derive(First)]
+#[derive(Second)]
+#[derive(Third, Fourth)]
+#[derive(Fifth)]
+pub struct Foo {}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-expand-order.stdout b/src/test/ui/proc-macro/derive-expand-order.stdout
new file mode 100644
index 000000000..dffbbf149
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-expand-order.stdout
@@ -0,0 +1,5 @@
+Derive First: #[derive(Second)] #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo {}
+Derive Second: #[derive(Third, Fourth)] #[derive(Fifth)] pub struct Foo {}
+Derive Third: #[derive(Fifth)] pub struct Foo {}
+Derive Fourth: #[derive(Fifth)] pub struct Foo {}
+Derive Fifth: pub struct Foo {}
diff --git a/src/test/ui/proc-macro/derive-helper-configured.rs b/src/test/ui/proc-macro/derive-helper-configured.rs
new file mode 100644
index 000000000..243cf685e
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-configured.rs
@@ -0,0 +1,18 @@
+// Derive helpers are resolved successfully inside `cfg_attr`.
+
+// check-pass
+// compile-flats:--cfg TRUE
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[cfg_attr(TRUE, empty_helper)]
+#[derive(Empty)]
+#[cfg_attr(TRUE, empty_helper)]
+struct S {
+ #[cfg_attr(TRUE, empty_helper)]
+ field: u8,
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-helper-legacy-limits.rs b/src/test/ui/proc-macro/derive-helper-legacy-limits.rs
new file mode 100644
index 000000000..ca904900d
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-legacy-limits.rs
@@ -0,0 +1,21 @@
+// Support for legacy derive helpers is limited and heuristic-based
+// (that's exactly the reason why they are deprecated).
+
+// edition:2018
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+use derive as my_derive;
+
+#[my_derive(Empty)]
+#[empty_helper] // OK
+struct S1;
+
+// Legacy helper detection doesn't see through `derive` renaming.
+#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope
+#[my_derive(Empty)]
+struct S2;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-helper-legacy-limits.stderr b/src/test/ui/proc-macro/derive-helper-legacy-limits.stderr
new file mode 100644
index 000000000..186f38a00
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-legacy-limits.stderr
@@ -0,0 +1,8 @@
+error: cannot find attribute `empty_helper` in this scope
+ --> $DIR/derive-helper-legacy-limits.rs:17:3
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/derive-helper-legacy-spurious.rs b/src/test/ui/proc-macro/derive-helper-legacy-spurious.rs
new file mode 100644
index 000000000..4a7e48eed
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-legacy-spurious.rs
@@ -0,0 +1,12 @@
+// aux-build:test-macros.rs
+
+#![dummy] //~ ERROR cannot find attribute `dummy` in this scope
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Empty)] //~ ERROR cannot determine resolution for the attribute macro `derive`
+#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope
+struct Foo {}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-helper-legacy-spurious.stderr b/src/test/ui/proc-macro/derive-helper-legacy-spurious.stderr
new file mode 100644
index 000000000..fd1ed8a3d
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-legacy-spurious.stderr
@@ -0,0 +1,22 @@
+error: cannot find attribute `dummy` in this scope
+ --> $DIR/derive-helper-legacy-spurious.rs:3:4
+ |
+LL | #![dummy]
+ | ^^^^^
+
+error: cannot determine resolution for the attribute macro `derive`
+ --> $DIR/derive-helper-legacy-spurious.rs:8:3
+ |
+LL | #[derive(Empty)]
+ | ^^^^^^
+ |
+ = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot find attribute `empty_helper` in this scope
+ --> $DIR/derive-helper-legacy-spurious.rs:9:3
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/proc-macro/derive-helper-shadowed.rs b/src/test/ui/proc-macro/derive-helper-shadowed.rs
new file mode 100644
index 000000000..e299454e0
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-shadowed.rs
@@ -0,0 +1,16 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// aux-build:test-macros.rs
+// aux-build:derive-helper-shadowed-2.rs
+
+#[macro_use]
+extern crate test_macros;
+#[macro_use(empty_helper)]
+extern crate derive_helper_shadowed_2;
+
+macro_rules! empty_helper { () => () }
+
+#[derive(Empty)]
+#[empty_helper] // OK
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-helper-shadowing-2.rs b/src/test/ui/proc-macro/derive-helper-shadowing-2.rs
new file mode 100644
index 000000000..5204d72b9
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-shadowing-2.rs
@@ -0,0 +1,16 @@
+// If a derive macro introduces a helper attribute with the same name as that macro,
+// then make sure that it's usable without ambiguities.
+
+// check-pass
+// aux-build:derive-helper-shadowing-2.rs
+
+#[macro_use]
+extern crate derive_helper_shadowing_2;
+
+#[derive(same_name)]
+struct S {
+ #[same_name] // OK, no ambiguity, derive helpers have highest priority
+ field: u8,
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs
new file mode 100644
index 000000000..80d982d25
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs
@@ -0,0 +1,56 @@
+// edition:2018
+// aux-build:test-macros.rs
+// aux-build:derive-helper-shadowing.rs
+
+#[macro_use]
+extern crate test_macros;
+#[macro_use]
+extern crate derive_helper_shadowing;
+
+use test_macros::empty_attr as empty_helper;
+
+macro_rules! gen_helper_use {
+ () => {
+ #[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope
+ struct W;
+ }
+}
+
+#[empty_helper] //~ ERROR `empty_helper` is ambiguous
+ //~| WARN derive helper attribute is used before it is introduced
+ //~| WARN this was previously accepted
+#[derive(Empty)]
+struct S {
+ #[empty_helper] // OK, no ambiguity, derive helpers have highest priority
+ field: [u8; {
+ use empty_helper; //~ ERROR `empty_helper` is ambiguous
+
+ #[empty_helper] // OK, no ambiguity, derive helpers have highest priority
+ struct U;
+
+ mod inner {
+ // OK, no ambiguity, the non-helper attribute is not in scope here, only the helper.
+ #[empty_helper]
+ struct V;
+
+ gen_helper_use!();
+
+ #[derive(GenHelperUse)] //~ ERROR cannot find attribute `empty_helper` in this scope
+ struct Owo;
+
+ use empty_helper as renamed;
+ #[renamed] //~ ERROR cannot use a derive helper attribute through an import
+ struct Wow;
+ }
+
+ 0
+ }]
+}
+
+// OK, no ambiguity, only the non-helper attribute is in scope.
+#[empty_helper]
+struct Z;
+
+fn main() {
+ let s = S { field: [] };
+}
diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr
new file mode 100644
index 000000000..d8287eb73
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr
@@ -0,0 +1,89 @@
+error: cannot use a derive helper attribute through an import
+ --> $DIR/derive-helper-shadowing.rs:42:15
+ |
+LL | #[renamed]
+ | ^^^^^^^
+ |
+note: the derive helper attribute imported here
+ --> $DIR/derive-helper-shadowing.rs:41:17
+ |
+LL | use empty_helper as renamed;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find attribute `empty_helper` in this scope
+ --> $DIR/derive-helper-shadowing.rs:38:22
+ |
+LL | #[derive(GenHelperUse)]
+ | ^^^^^^^^^^^^
+ |
+ = note: consider importing this attribute macro:
+ empty_helper
+ = note: this error originates in the derive macro `GenHelperUse` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot find attribute `empty_helper` in this scope
+ --> $DIR/derive-helper-shadowing.rs:14:11
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^
+...
+LL | gen_helper_use!();
+ | ----------------- in this macro invocation
+ |
+ = note: consider importing this attribute macro:
+ crate::empty_helper
+ = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0659]: `empty_helper` is ambiguous
+ --> $DIR/derive-helper-shadowing.rs:26:13
+ |
+LL | use empty_helper;
+ | ^^^^^^^^^^^^ ambiguous name
+ |
+ = note: ambiguous because of multiple potential import sources
+note: `empty_helper` could refer to the derive helper attribute defined here
+ --> $DIR/derive-helper-shadowing.rs:22:10
+ |
+LL | #[derive(Empty)]
+ | ^^^^^
+note: `empty_helper` could also refer to the attribute macro imported here
+ --> $DIR/derive-helper-shadowing.rs:10:5
+ |
+LL | use test_macros::empty_attr as empty_helper;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
+
+error[E0659]: `empty_helper` is ambiguous
+ --> $DIR/derive-helper-shadowing.rs:19:3
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a derive helper attribute
+note: `empty_helper` could refer to the derive helper attribute defined here
+ --> $DIR/derive-helper-shadowing.rs:22:10
+ |
+LL | #[derive(Empty)]
+ | ^^^^^
+note: `empty_helper` could also refer to the attribute macro imported here
+ --> $DIR/derive-helper-shadowing.rs:10:5
+ |
+LL | use test_macros::empty_attr as empty_helper;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
+
+warning: derive helper attribute is used before it is introduced
+ --> $DIR/derive-helper-shadowing.rs:19:3
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^
+...
+LL | #[derive(Empty)]
+ | ----- the attribute is introduced here
+ |
+ = note: `#[warn(legacy_derive_helpers)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/proc-macro/derive-helper-vs-legacy.rs b/src/test/ui/proc-macro/derive-helper-vs-legacy.rs
new file mode 100644
index 000000000..98836bcb8
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-helper-vs-legacy.rs
@@ -0,0 +1,12 @@
+// check-pass
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Empty)]
+#[empty_helper] // OK, this is both derive helper and legacy derive helper
+#[derive(Empty)]
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-in-mod.rs b/src/test/ui/proc-macro/derive-in-mod.rs
new file mode 100644
index 000000000..8b5d4e9d0
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-in-mod.rs
@@ -0,0 +1,13 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// aux-build:test-macros.rs
+
+extern crate test_macros;
+
+mod inner {
+ use test_macros::Empty;
+
+ #[derive(Empty)]
+ struct S;
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-multiple-with-packed.rs b/src/test/ui/proc-macro/derive-multiple-with-packed.rs
new file mode 100644
index 000000000..23578aa0e
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-multiple-with-packed.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#[derive(Clone, Copy)]
+#[derive(Debug)] // OK, even if `Copy` is in the different `#[derive]`
+#[derive(PartialEq)] // OK too
+#[repr(packed)]
+struct CacheRecordHeader {
+ field: u64,
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-same-struct.rs b/src/test/ui/proc-macro/derive-same-struct.rs
new file mode 100644
index 000000000..528b0f22a
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-same-struct.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+#![allow(path_statements)]
+#![allow(dead_code)]
+// aux-build:derive-same-struct.rs
+
+#[macro_use]
+extern crate derive_same_struct;
+
+#[derive(AToB)]
+struct A;
+
+fn main() {
+ C;
+}
diff --git a/src/test/ui/proc-macro/derive-same-struct.stdout b/src/test/ui/proc-macro/derive-same-struct.stdout
new file mode 100644
index 000000000..7478d9741
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-same-struct.stdout
@@ -0,0 +1 @@
+input1: "struct A ;"
diff --git a/src/test/ui/proc-macro/derive-still-gated.rs b/src/test/ui/proc-macro/derive-still-gated.rs
new file mode 100644
index 000000000..3f8d6f071
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-still-gated.rs
@@ -0,0 +1,9 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive_Empty] //~ ERROR cannot find attribute `derive_Empty` in this scope
+struct A;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr
new file mode 100644
index 000000000..99289fdfe
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-still-gated.stderr
@@ -0,0 +1,8 @@
+error: cannot find attribute `derive_Empty` in this scope
+ --> $DIR/derive-still-gated.rs:6:3
+ |
+LL | #[derive_Empty]
+ | ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/derive-test.rs b/src/test/ui/proc-macro/derive-test.rs
new file mode 100644
index 000000000..b81e38432
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-test.rs
@@ -0,0 +1,22 @@
+// run-pass
+// no-prefer-dynamic
+// compile-flags: --test
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+// ```
+// assert!(true);
+// ```
+#[proc_macro_derive(Foo)]
+pub fn derive_foo(_input: TokenStream) -> TokenStream {
+ "".parse().unwrap()
+}
+
+#[test]
+pub fn test_derive() {
+ assert!(true);
+}
diff --git a/src/test/ui/proc-macro/derive-two-attrs.rs b/src/test/ui/proc-macro/derive-two-attrs.rs
new file mode 100644
index 000000000..08225b8e3
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-two-attrs.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+#![allow(dead_code)]
+// aux-build:derive-two-attrs.rs
+
+extern crate derive_two_attrs as foo;
+
+use foo::A;
+
+#[derive(A)]
+#[b]
+#[b]
+struct B;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/derive-union.rs b/src/test/ui/proc-macro/derive-union.rs
new file mode 100644
index 000000000..e83eee093
--- /dev/null
+++ b/src/test/ui/proc-macro/derive-union.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![allow(unused_variables)]
+// aux-build:derive-union.rs
+
+#[macro_use]
+extern crate derive_union;
+
+#[repr(C)]
+#[derive(UnionTest)]
+union Test {
+ a: u8,
+}
+
+fn main() {
+ let t = Test { a: 0 };
+}
diff --git a/src/test/ui/proc-macro/disappearing-resolution.rs b/src/test/ui/proc-macro/disappearing-resolution.rs
new file mode 100644
index 000000000..50f04b1ea
--- /dev/null
+++ b/src/test/ui/proc-macro/disappearing-resolution.rs
@@ -0,0 +1,22 @@
+// Regression test for issue #64803 (initial attribute resolution can disappear later).
+
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+mod m {
+ use test_macros::Empty;
+}
+use m::Empty; //~ ERROR derive macro import `Empty` is private
+
+// To resolve `empty_helper` we need to resolve `Empty`.
+// During initial resolution `use m::Empty` introduces no entries, so we proceed to `macro_use`,
+// successfully resolve `Empty` from there, and then resolve `empty_helper` as its helper.
+// During validation `use m::Empty` introduces a `Res::Err` stub, so `Empty` resolves to it,
+// and `empty_helper` can no longer be resolved.
+#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope
+#[derive(Empty)]
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/disappearing-resolution.stderr b/src/test/ui/proc-macro/disappearing-resolution.stderr
new file mode 100644
index 000000000..5b969549a
--- /dev/null
+++ b/src/test/ui/proc-macro/disappearing-resolution.stderr
@@ -0,0 +1,26 @@
+error: cannot find attribute `empty_helper` in this scope
+ --> $DIR/disappearing-resolution.rs:18:3
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^
+
+error[E0603]: derive macro import `Empty` is private
+ --> $DIR/disappearing-resolution.rs:11:8
+ |
+LL | use m::Empty;
+ | ^^^^^ private derive macro import
+ |
+note: the derive macro import `Empty` is defined here...
+ --> $DIR/disappearing-resolution.rs:9:9
+ |
+LL | use test_macros::Empty;
+ | ^^^^^^^^^^^^^^^^^^
+note: ...and refers to the derive macro `Empty` which is defined here
+ --> $DIR/auxiliary/test-macros.rs:25:1
+ |
+LL | pub fn empty_derive(_: TokenStream) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider importing it directly
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/proc-macro/doc-comment-preserved.rs b/src/test/ui/proc-macro/doc-comment-preserved.rs
new file mode 100644
index 000000000..ed8ca99bd
--- /dev/null
+++ b/src/test/ui/proc-macro/doc-comment-preserved.rs
@@ -0,0 +1,24 @@
+// check-pass
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+print_bang! {
+
+/**
+*******
+* DOC *
+* DOC *
+* DOC *
+*******
+*/
+pub struct S;
+
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/doc-comment-preserved.stdout b/src/test/ui/proc-macro/doc-comment-preserved.stdout
new file mode 100644
index 000000000..f4160d7da
--- /dev/null
+++ b/src/test/ui/proc-macro/doc-comment-preserved.stdout
@@ -0,0 +1,54 @@
+PRINT-BANG INPUT (DISPLAY): /**
+*******
+* DOC *
+* DOC *
+* DOC *
+*******
+*/
+ pub struct S ;
+PRINT-BANG RE-COLLECTED (DISPLAY): #[doc = "\n*******\n* DOC *\n* DOC *\n* DOC *\n*******\n"] pub struct S ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "doc",
+ span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0),
+ },
+ Literal {
+ kind: Str,
+ symbol: "\n*******\n* DOC *\n* DOC *\n* DOC *\n*******\n",
+ suffix: None,
+ span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0),
+ },
+ ],
+ span: $DIR/doc-comment-preserved.rs:13:1: 19:3 (#0),
+ },
+ Ident {
+ ident: "pub",
+ span: $DIR/doc-comment-preserved.rs:20:1: 20:4 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/doc-comment-preserved.rs:20:5: 20:11 (#0),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/doc-comment-preserved.rs:20:12: 20:13 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/doc-comment-preserved.rs:20:13: 20:14 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.rs b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
new file mode 100644
index 000000000..27bfa099f
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
@@ -0,0 +1,27 @@
+// check-pass
+// edition:2018
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+type S = u8;
+
+macro_rules! m {
+ () => {
+ print_bang! {
+ struct M($crate::S);
+ }
+
+ #[print_attr]
+ struct A($crate::S);
+ };
+}
+
+m!();
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
new file mode 100644
index 000000000..c0c9ed72c
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
@@ -0,0 +1,80 @@
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/dollar-crate-issue-57089.rs:17:13: 17:19 (#4),
+ },
+ Ident {
+ ident: "M",
+ span: $DIR/dollar-crate-issue-57089.rs:17:20: 17:21 (#4),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/dollar-crate-issue-57089.rs:17:22: 17:28 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/dollar-crate-issue-57089.rs:17:28: 17:30 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/dollar-crate-issue-57089.rs:17:28: 17:30 (#4),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/dollar-crate-issue-57089.rs:17:30: 17:31 (#4),
+ },
+ ],
+ span: $DIR/dollar-crate-issue-57089.rs:17:21: 17:32 (#4),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/dollar-crate-issue-57089.rs:17:32: 17:33 (#4),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/dollar-crate-issue-57089.rs:21:9: 21:15 (#4),
+ },
+ Ident {
+ ident: "A",
+ span: $DIR/dollar-crate-issue-57089.rs:21:16: 21:17 (#4),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/dollar-crate-issue-57089.rs:21:18: 21:24 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/dollar-crate-issue-57089.rs:21:24: 21:26 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/dollar-crate-issue-57089.rs:21:24: 21:26 (#4),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/dollar-crate-issue-57089.rs:21:26: 21:27 (#4),
+ },
+ ],
+ span: $DIR/dollar-crate-issue-57089.rs:21:17: 21:28 (#4),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/dollar-crate-issue-57089.rs:21:28: 21:29 (#4),
+ },
+]
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.rs b/src/test/ui/proc-macro/dollar-crate-issue-62325.rs
new file mode 100644
index 000000000..d828fb9fd
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.rs
@@ -0,0 +1,26 @@
+// check-pass
+// edition:2018
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+// aux-build:dollar-crate-external.rs
+
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+extern crate dollar_crate_external;
+
+type S = u8;
+
+macro_rules! m { () => {
+ #[print_attr]
+ struct A(identity!($crate::S));
+}}
+
+m!();
+
+dollar_crate_external::issue_62325!();
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
new file mode 100644
index 000000000..e6148a687
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
@@ -0,0 +1,110 @@
+PRINT-ATTR INPUT (DISPLAY): struct A(identity! ($crate :: S)) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/dollar-crate-issue-62325.rs:19:5: 19:11 (#4),
+ },
+ Ident {
+ ident: "A",
+ span: $DIR/dollar-crate-issue-62325.rs:19:12: 19:13 (#4),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "identity",
+ span: $DIR/dollar-crate-issue-62325.rs:19:14: 19:22 (#4),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/dollar-crate-issue-62325.rs:19:22: 19:23 (#4),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/dollar-crate-issue-62325.rs:19:24: 19:30 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/dollar-crate-issue-62325.rs:19:30: 19:32 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/dollar-crate-issue-62325.rs:19:30: 19:32 (#4),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/dollar-crate-issue-62325.rs:19:32: 19:33 (#4),
+ },
+ ],
+ span: $DIR/dollar-crate-issue-62325.rs:19:23: 19:34 (#4),
+ },
+ ],
+ span: $DIR/dollar-crate-issue-62325.rs:19:13: 19:35 (#4),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/dollar-crate-issue-62325.rs:19:35: 19:36 (#4),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): struct B(identity! ($crate :: S)) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:5: 21:11 (#12),
+ },
+ Ident {
+ ident: "B",
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:12: 21:13 (#12),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "identity",
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:14: 21:22 (#12),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:22: 21:23 (#12),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:24: 21:30 (#12),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:30: 21:32 (#12),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:30: 21:32 (#12),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:32: 21:33 (#12),
+ },
+ ],
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:23: 21:34 (#12),
+ },
+ ],
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:13: 21:35 (#12),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:35: 21:36 (#12),
+ },
+]
diff --git a/src/test/ui/proc-macro/dollar-crate.rs b/src/test/ui/proc-macro/dollar-crate.rs
new file mode 100644
index 000000000..ac27dfa1a
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate.rs
@@ -0,0 +1,40 @@
+// check-pass
+// edition:2018
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+// aux-build:dollar-crate-external.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+extern crate dollar_crate_external;
+
+type S = u8;
+
+mod local {
+ macro_rules! local {
+ () => {
+ print_bang! {
+ struct M($crate::S);
+ }
+
+ #[print_attr]
+ struct A($crate::S);
+
+ #[derive(Print)]
+ struct D($crate::S);
+ };
+ }
+
+ local!();
+}
+
+mod external {
+ use crate::dollar_crate_external;
+
+ dollar_crate_external::external!();
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout
new file mode 100644
index 000000000..d01fcb9d0
--- /dev/null
+++ b/src/test/ui/proc-macro/dollar-crate.stdout
@@ -0,0 +1,240 @@
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/dollar-crate.rs:20:17: 20:23 (#4),
+ },
+ Ident {
+ ident: "M",
+ span: $DIR/dollar-crate.rs:20:24: 20:25 (#4),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/dollar-crate.rs:20:26: 20:32 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/dollar-crate.rs:20:32: 20:34 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/dollar-crate.rs:20:32: 20:34 (#4),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/dollar-crate.rs:20:34: 20:35 (#4),
+ },
+ ],
+ span: $DIR/dollar-crate.rs:20:25: 20:36 (#4),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/dollar-crate.rs:20:36: 20:37 (#4),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/dollar-crate.rs:24:13: 24:19 (#4),
+ },
+ Ident {
+ ident: "A",
+ span: $DIR/dollar-crate.rs:24:20: 24:21 (#4),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/dollar-crate.rs:24:22: 24:28 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/dollar-crate.rs:24:28: 24:30 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/dollar-crate.rs:24:28: 24:30 (#4),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/dollar-crate.rs:24:30: 24:31 (#4),
+ },
+ ],
+ span: $DIR/dollar-crate.rs:24:21: 24:32 (#4),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/dollar-crate.rs:24:32: 24:33 (#4),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ;
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/dollar-crate.rs:27:13: 27:19 (#4),
+ },
+ Ident {
+ ident: "D",
+ span: $DIR/dollar-crate.rs:27:20: 27:21 (#4),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/dollar-crate.rs:27:22: 27:28 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/dollar-crate.rs:27:28: 27:30 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/dollar-crate.rs:27:28: 27:30 (#4),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/dollar-crate.rs:27:30: 27:31 (#4),
+ },
+ ],
+ span: $DIR/dollar-crate.rs:27:21: 27:32 (#4),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/dollar-crate.rs:27:32: 27:33 (#4),
+ },
+]
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:13: 7:19 (#15),
+ },
+ Ident {
+ ident: "M",
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:20: 7:21 (#15),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:22: 7:28 (#15),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:28: 7:30 (#15),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:28: 7:30 (#15),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:30: 7:31 (#15),
+ },
+ ],
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:21: 7:32 (#15),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:32: 7:33 (#15),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:9: 11:15 (#15),
+ },
+ Ident {
+ ident: "A",
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:16: 11:17 (#15),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:18: 11:24 (#15),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:24: 11:26 (#15),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:24: 11:26 (#15),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:26: 11:27 (#15),
+ },
+ ],
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:17: 11:28 (#15),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:28: 11:29 (#15),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ;
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:9: 14:15 (#15),
+ },
+ Ident {
+ ident: "D",
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:16: 14:17 (#15),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "$crate",
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:18: 14:24 (#15),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:24: 14:26 (#15),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:24: 14:26 (#15),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:26: 14:27 (#15),
+ },
+ ],
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:17: 14:28 (#15),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:28: 14:29 (#15),
+ },
+]
diff --git a/src/test/ui/proc-macro/edition-imports-2018.rs b/src/test/ui/proc-macro/edition-imports-2018.rs
new file mode 100644
index 000000000..5a77cd4ef
--- /dev/null
+++ b/src/test/ui/proc-macro/edition-imports-2018.rs
@@ -0,0 +1,24 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2018
+// aux-build:edition-imports-2015.rs
+
+#[macro_use]
+extern crate edition_imports_2015;
+
+mod import {
+ pub struct Path;
+}
+mod absolute {
+ pub struct Path;
+}
+
+mod check {
+ #[derive(Derive2015)] // OK
+ struct S;
+
+ fn check() {
+ Path;
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/empty-crate.rs b/src/test/ui/proc-macro/empty-crate.rs
new file mode 100644
index 000000000..3e54c9fee
--- /dev/null
+++ b/src/test/ui/proc-macro/empty-crate.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+#![allow(unused_imports)]
+// aux-build:empty-crate.rs
+
+#[macro_use]
+extern crate empty_crate;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/empty-where-clause.rs b/src/test/ui/proc-macro/empty-where-clause.rs
new file mode 100644
index 000000000..719555c09
--- /dev/null
+++ b/src/test/ui/proc-macro/empty-where-clause.rs
@@ -0,0 +1,18 @@
+// aux-build:test-macros.rs
+
+extern crate test_macros;
+use test_macros::recollect_attr;
+
+#[recollect_attr]
+struct FieldStruct where {
+ field: MissingType1 //~ ERROR cannot find
+}
+
+#[recollect_attr]
+struct TupleStruct(MissingType2) where; //~ ERROR cannot find
+
+enum MyEnum where {
+ Variant(MissingType3) //~ ERROR cannot find
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/empty-where-clause.stderr b/src/test/ui/proc-macro/empty-where-clause.stderr
new file mode 100644
index 000000000..192a2b30f
--- /dev/null
+++ b/src/test/ui/proc-macro/empty-where-clause.stderr
@@ -0,0 +1,21 @@
+error[E0412]: cannot find type `MissingType1` in this scope
+ --> $DIR/empty-where-clause.rs:8:12
+ |
+LL | field: MissingType1
+ | ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `MissingType2` in this scope
+ --> $DIR/empty-where-clause.rs:12:20
+ |
+LL | struct TupleStruct(MissingType2) where;
+ | ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `MissingType3` in this scope
+ --> $DIR/empty-where-clause.rs:15:13
+ |
+LL | Variant(MissingType3)
+ | ^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/proc-macro/expand-expr.rs b/src/test/ui/proc-macro/expand-expr.rs
new file mode 100644
index 000000000..d1146d970
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-expr.rs
@@ -0,0 +1,121 @@
+// aux-build:expand-expr.rs
+
+extern crate expand_expr;
+
+use expand_expr::{
+ check_expand_expr_file, echo_pm, expand_expr_fail, expand_expr_is, recursive_expand,
+};
+
+// Check builtin macros can be expanded.
+
+expand_expr_is!(11u32, line!());
+expand_expr_is!(24u32, column!());
+
+expand_expr_is!("Hello, World!", concat!("Hello, ", "World", "!"));
+expand_expr_is!("int10floats5.3booltrue", concat!("int", 10, "floats", 5.3, "bool", true));
+expand_expr_is!("Hello", concat!(r##"Hello"##));
+
+expand_expr_is!("Included file contents\n", include_str!("auxiliary/included-file.txt"));
+expand_expr_is!(b"Included file contents\n", include_bytes!("auxiliary/included-file.txt"));
+
+expand_expr_is!(
+ "contents: Included file contents\n",
+ concat!("contents: ", include_str!("auxiliary/included-file.txt"))
+);
+
+// Correct value is checked for multiple sources.
+check_expand_expr_file!(file!());
+
+expand_expr_is!("hello", stringify!(hello));
+expand_expr_is!("10 + 20", stringify!(10 + 20));
+
+macro_rules! echo_tts {
+ ($($t:tt)*) => { $($t)* }; //~ ERROR: expected expression, found `$`
+}
+
+macro_rules! echo_lit {
+ ($l:literal) => {
+ $l
+ };
+}
+
+macro_rules! echo_expr {
+ ($e:expr) => {
+ $e
+ };
+}
+
+macro_rules! simple_lit {
+ ($l:literal) => {
+ expand_expr_is!($l, $l);
+ expand_expr_is!($l, echo_lit!($l));
+ expand_expr_is!($l, echo_expr!($l));
+ expand_expr_is!($l, echo_tts!($l));
+ expand_expr_is!($l, echo_pm!($l));
+ const _: () = {
+ macro_rules! mac {
+ () => {
+ $l
+ };
+ }
+ expand_expr_is!($l, mac!());
+ expand_expr_is!($l, echo_expr!(mac!()));
+ expand_expr_is!($l, echo_tts!(mac!()));
+ expand_expr_is!($l, echo_pm!(mac!()));
+ };
+ };
+}
+
+simple_lit!("Hello, World");
+simple_lit!('c');
+simple_lit!(b'c');
+simple_lit!(10);
+simple_lit!(10.0);
+simple_lit!(10.0f64);
+simple_lit!(-3.14159);
+simple_lit!(-3.5e10);
+simple_lit!(0xFEED);
+simple_lit!(-0xFEED);
+simple_lit!(0b0100);
+simple_lit!(-0b0100);
+simple_lit!("string");
+simple_lit!(r##"raw string"##);
+simple_lit!(b"byte string");
+simple_lit!(br##"raw byte string"##);
+simple_lit!(true);
+simple_lit!(false);
+
+// Ensure char escapes aren't normalized by expansion
+simple_lit!("\u{0}");
+simple_lit!("\0");
+simple_lit!("\x00");
+simple_lit!('\u{0}');
+simple_lit!('\0');
+simple_lit!('\x00');
+simple_lit!(b"\x00");
+simple_lit!(b"\0");
+simple_lit!(b'\x00');
+simple_lit!(b'\0');
+
+// Extra tokens after the string literal aren't ignored
+expand_expr_fail!("string"; hello); //~ ERROR: expected one of `.`, `?`, or an operator, found `;`
+
+// Invalid expressions produce errors in addition to returning `Err(())`.
+expand_expr_fail!($); //~ ERROR: expected expression, found `$`
+expand_expr_fail!(echo_tts!($));
+expand_expr_fail!(echo_pm!($)); //~ ERROR: expected expression, found `$`
+
+// We get errors reported and recover during macro expansion if the macro
+// doesn't produce a valid expression.
+expand_expr_is!("string", echo_tts!("string"; hello)); //~ ERROR: macro expansion ignores token `hello` and any following
+expand_expr_is!("string", echo_pm!("string"; hello)); //~ ERROR: macro expansion ignores token `;` and any following
+
+// For now, fail if a non-literal expression is expanded.
+expand_expr_fail!(arbitrary_expression() + "etc");
+expand_expr_fail!(echo_tts!(arbitrary_expression() + "etc"));
+expand_expr_fail!(echo_expr!(arbitrary_expression() + "etc"));
+expand_expr_fail!(echo_pm!(arbitrary_expression() + "etc"));
+
+const _: u32 = recursive_expand!(); //~ ERROR: recursion limit reached while expanding `recursive_expand!`
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/expand-expr.stderr b/src/test/ui/proc-macro/expand-expr.stderr
new file mode 100644
index 000000000..8dc2d0cfc
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-expr.stderr
@@ -0,0 +1,55 @@
+error: expected one of `.`, `?`, or an operator, found `;`
+ --> $DIR/expand-expr.rs:101:27
+ |
+LL | expand_expr_fail!("string"; hello);
+ | ^ expected one of `.`, `?`, or an operator
+
+error: expected expression, found `$`
+ --> $DIR/expand-expr.rs:104:19
+ |
+LL | expand_expr_fail!($);
+ | ^ expected expression
+
+error: expected expression, found `$`
+ --> $DIR/expand-expr.rs:33:23
+ |
+LL | ($($t:tt)*) => { $($t)* };
+ | ^^^^ expected expression
+
+error: expected expression, found `$`
+ --> $DIR/expand-expr.rs:106:28
+ |
+LL | expand_expr_fail!(echo_pm!($));
+ | ^ expected expression
+
+error: macro expansion ignores token `hello` and any following
+ --> $DIR/expand-expr.rs:110:47
+ |
+LL | expand_expr_is!("string", echo_tts!("string"; hello));
+ | --------------------^^^^^-- help: you might be missing a semicolon here: `;`
+ | |
+ | caused by the macro expansion here
+ |
+ = note: the usage of `echo_tts!` is likely invalid in expression context
+
+error: macro expansion ignores token `;` and any following
+ --> $DIR/expand-expr.rs:111:44
+ |
+LL | expand_expr_is!("string", echo_pm!("string"; hello));
+ | -----------------^-------- help: you might be missing a semicolon here: `;`
+ | |
+ | caused by the macro expansion here
+ |
+ = note: the usage of `echo_pm!` is likely invalid in expression context
+
+error: recursion limit reached while expanding `recursive_expand!`
+ --> $DIR/expand-expr.rs:119:16
+ |
+LL | const _: u32 = recursive_expand!();
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`expand_expr`)
+ = note: this error originates in the macro `recursive_expand` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/proc-macro/expand-to-derive.rs b/src/test/ui/proc-macro/expand-to-derive.rs
new file mode 100644
index 000000000..ff2876e84
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-derive.rs
@@ -0,0 +1,34 @@
+// check-pass
+// compile-flags: -Z span-debug --error-format human
+// aux-build:test-macros.rs
+
+#![feature(rustc_attrs)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! expand_to_derive {
+ ($item:item) => {
+ #[derive(Print)]
+ struct Foo {
+ #[cfg(FALSE)] removed: bool,
+ field: [bool; {
+ $item
+ 0
+ }]
+ }
+ };
+}
+
+expand_to_derive! {
+ #[cfg_attr(not(FALSE), rustc_dummy)]
+ struct Inner {
+ #[cfg(FALSE)] removed_inner_field: bool,
+ other_inner_field: u8,
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/expand-to-derive.stdout b/src/test/ui/proc-macro/expand-to-derive.stdout
new file mode 100644
index 000000000..a6437982a
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-derive.stdout
@@ -0,0 +1,104 @@
+PRINT-DERIVE INPUT (DISPLAY): struct Foo
+{
+ field :
+ [bool ; { #[rustc_dummy] struct Inner { other_inner_field : u8, } 0 }]
+}
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/expand-to-derive.rs:16:9: 16:15 (#4),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/expand-to-derive.rs:16:16: 16:19 (#4),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "field",
+ span: $DIR/expand-to-derive.rs:18:13: 18:18 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/expand-to-derive.rs:18:18: 18:19 (#4),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "bool",
+ span: $DIR/expand-to-derive.rs:18:21: 18:25 (#4),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/expand-to-derive.rs:18:25: 18:26 (#4),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/expand-to-derive.rs:27:28: 27:39 (#0),
+ },
+ ],
+ span: $DIR/expand-to-derive.rs:27:5: 27:6 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/expand-to-derive.rs:28:5: 28:11 (#0),
+ },
+ Ident {
+ ident: "Inner",
+ span: $DIR/expand-to-derive.rs:28:12: 28:17 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "other_inner_field",
+ span: $DIR/expand-to-derive.rs:30:9: 30:26 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/expand-to-derive.rs:30:26: 30:27 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/expand-to-derive.rs:30:28: 30:30 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/expand-to-derive.rs:30:30: 30:31 (#0),
+ },
+ ],
+ span: $DIR/expand-to-derive.rs:28:18: 31:6 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/expand-to-derive.rs:20:17: 20:18 (#4),
+ },
+ ],
+ span: $DIR/expand-to-derive.rs:18:27: 21:14 (#4),
+ },
+ ],
+ span: $DIR/expand-to-derive.rs:18:20: 21:15 (#4),
+ },
+ ],
+ span: $DIR/expand-to-derive.rs:16:20: 22:10 (#4),
+ },
+]
diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.rs b/src/test/ui/proc-macro/expand-to-unstable-2.rs
new file mode 100644
index 000000000..4160e5418
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-unstable-2.rs
@@ -0,0 +1,17 @@
+// aux-build:derive-unstable-2.rs
+
+#![feature(register_attr)]
+
+#![register_attr(rustc_foo)]
+
+#[macro_use]
+extern crate derive_unstable_2;
+
+#[derive(Unstable)]
+//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
+
+struct A;
+
+fn main() {
+ foo();
+}
diff --git a/src/test/ui/proc-macro/expand-to-unstable-2.stderr b/src/test/ui/proc-macro/expand-to-unstable-2.stderr
new file mode 100644
index 000000000..8b16ffb76
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-unstable-2.stderr
@@ -0,0 +1,10 @@
+error: attributes starting with `rustc` are reserved for use by the `rustc` compiler
+ --> $DIR/expand-to-unstable-2.rs:10:10
+ |
+LL | #[derive(Unstable)]
+ | ^^^^^^^^
+ |
+ = note: this error originates in the derive macro `Unstable` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/expand-to-unstable.rs b/src/test/ui/proc-macro/expand-to-unstable.rs
new file mode 100644
index 000000000..0825c1a8e
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-unstable.rs
@@ -0,0 +1,14 @@
+// aux-build:derive-unstable.rs
+
+#![allow(warnings)]
+
+#[macro_use]
+extern crate derive_unstable;
+
+#[derive(Unstable)]
+//~^ ERROR: use of unstable library feature
+struct A;
+
+fn main() {
+ unsafe { foo(); }
+}
diff --git a/src/test/ui/proc-macro/expand-to-unstable.stderr b/src/test/ui/proc-macro/expand-to-unstable.stderr
new file mode 100644
index 000000000..b27dcd7e6
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-to-unstable.stderr
@@ -0,0 +1,12 @@
+error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+ --> $DIR/expand-to-unstable.rs:8:10
+ |
+LL | #[derive(Unstable)]
+ | ^^^^^^^^
+ |
+ = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable
+ = note: this error originates in the derive macro `Unstable` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/expand-with-a-macro.rs b/src/test/ui/proc-macro/expand-with-a-macro.rs
new file mode 100644
index 000000000..21a4547d1
--- /dev/null
+++ b/src/test/ui/proc-macro/expand-with-a-macro.rs
@@ -0,0 +1,21 @@
+// run-pass
+// needs-unwind
+// aux-build:expand-with-a-macro.rs
+
+// ignore-wasm32-bare compiled with panic=abort by default
+
+#![deny(warnings)]
+
+#[macro_use]
+extern crate expand_with_a_macro;
+
+use std::panic;
+
+#[derive(A)]
+struct A;
+
+fn main() {
+ assert!(panic::catch_unwind(|| {
+ A.a();
+ }).is_err());
+}
diff --git a/src/test/ui/proc-macro/export-macro.rs b/src/test/ui/proc-macro/export-macro.rs
new file mode 100644
index 000000000..ad69fe5ee
--- /dev/null
+++ b/src/test/ui/proc-macro/export-macro.rs
@@ -0,0 +1,11 @@
+// error-pattern: cannot export macro_rules! macros from a `proc-macro` crate
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+#[macro_export]
+macro_rules! foo {
+ ($e:expr) => ($e)
+}
diff --git a/src/test/ui/proc-macro/export-macro.stderr b/src/test/ui/proc-macro/export-macro.stderr
new file mode 100644
index 000000000..36a6a9bb3
--- /dev/null
+++ b/src/test/ui/proc-macro/export-macro.stderr
@@ -0,0 +1,8 @@
+error: cannot export macro_rules! macros from a `proc-macro` crate type currently
+ --> $DIR/export-macro.rs:9:1
+ |
+LL | macro_rules! foo {
+ | ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/exports.rs b/src/test/ui/proc-macro/exports.rs
new file mode 100644
index 000000000..a40c15908
--- /dev/null
+++ b/src/test/ui/proc-macro/exports.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![allow(warnings)]
+
+pub fn a() {} //~ ERROR: cannot export any items
+pub struct B; //~ ERROR: cannot export any items
+pub enum C {} //~ ERROR: cannot export any items
+pub mod d {} //~ ERROR: cannot export any items
+
+mod e {}
+struct F;
+enum G {}
+fn h() {}
diff --git a/src/test/ui/proc-macro/exports.stderr b/src/test/ui/proc-macro/exports.stderr
new file mode 100644
index 000000000..7b23d08f2
--- /dev/null
+++ b/src/test/ui/proc-macro/exports.stderr
@@ -0,0 +1,26 @@
+error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
+ --> $DIR/exports.rs:7:1
+ |
+LL | pub fn a() {}
+ | ^^^^^^^^^^
+
+error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
+ --> $DIR/exports.rs:8:1
+ |
+LL | pub struct B;
+ | ^^^^^^^^^^^^^
+
+error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
+ --> $DIR/exports.rs:9:1
+ |
+LL | pub enum C {}
+ | ^^^^^^^^^^
+
+error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
+ --> $DIR/exports.rs:10:1
+ |
+LL | pub mod d {}
+ | ^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs
new file mode 100644
index 000000000..d4067a335
--- /dev/null
+++ b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs
@@ -0,0 +1,37 @@
+// check-pass
+// aux-build:test-macros.rs
+
+#![feature(decl_macro)]
+#![feature(stmt_expr_attributes)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro mac {
+ (expr $expr:expr) => {
+ #[derive(Print)]
+ enum E {
+ V = { let _ = $expr; 0 },
+ }
+ },
+ (stmt $stmt:stmt) => {
+ #[derive(Print)]
+ enum E {
+ V = { let _ = { $stmt }; 0 },
+ }
+ },
+}
+
+const PATH: u8 = 2;
+
+fn main() {
+ mac!(expr #[allow(warnings)] 0);
+ mac!(stmt 0);
+ mac!(stmt {});
+ mac!(stmt PATH);
+ mac!(stmt 0 + 1);
+ mac!(stmt PATH + 1);
+}
diff --git a/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout
new file mode 100644
index 000000000..686d53e88
--- /dev/null
+++ b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout
@@ -0,0 +1,540 @@
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0 ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = #[allow(warnings)] #[allow(warnings)] 0 ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: #4 bytes(299..303),
+ },
+ Ident {
+ ident: "E",
+ span: #4 bytes(304..305),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "V",
+ span: #4 bytes(320..321),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #4 bytes(322..323),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "let",
+ span: #4 bytes(326..329),
+ },
+ Ident {
+ ident: "_",
+ span: #4 bytes(330..331),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #4 bytes(332..333),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: #0 bytes(541..542),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: #0 bytes(543..548),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "warnings",
+ span: #0 bytes(549..557),
+ },
+ ],
+ span: #0 bytes(548..558),
+ },
+ ],
+ span: #0 bytes(542..559),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: #0 bytes(541..542),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: #0 bytes(543..548),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "warnings",
+ span: #0 bytes(549..557),
+ },
+ ],
+ span: #0 bytes(548..558),
+ },
+ ],
+ span: #0 bytes(542..559),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #0 bytes(560..561),
+ },
+ ],
+ span: #4 bytes(334..339),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: #4 bytes(339..340),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #4 bytes(341..342),
+ },
+ ],
+ span: #4 bytes(324..344),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: #4 bytes(344..345),
+ },
+ ],
+ span: #4 bytes(306..355),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: #8 bytes(423..427),
+ },
+ Ident {
+ ident: "E",
+ span: #8 bytes(428..429),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "V",
+ span: #8 bytes(444..445),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #8 bytes(446..447),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "let",
+ span: #8 bytes(450..453),
+ },
+ Ident {
+ ident: "_",
+ span: #8 bytes(454..455),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #8 bytes(456..457),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #0 bytes(578..579),
+ },
+ ],
+ span: #8 bytes(460..465),
+ },
+ ],
+ span: #8 bytes(458..467),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: #8 bytes(467..468),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #8 bytes(469..470),
+ },
+ ],
+ span: #8 bytes(448..472),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: #8 bytes(472..473),
+ },
+ ],
+ span: #8 bytes(430..483),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { {} } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: #12 bytes(423..427),
+ },
+ Ident {
+ ident: "E",
+ span: #12 bytes(428..429),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "V",
+ span: #12 bytes(444..445),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #12 bytes(446..447),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "let",
+ span: #12 bytes(450..453),
+ },
+ Ident {
+ ident: "_",
+ span: #12 bytes(454..455),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #12 bytes(456..457),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: #0 bytes(596..598),
+ },
+ ],
+ span: #12 bytes(460..465),
+ },
+ ],
+ span: #12 bytes(458..467),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: #12 bytes(467..468),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #12 bytes(469..470),
+ },
+ ],
+ span: #12 bytes(448..472),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: #12 bytes(472..473),
+ },
+ ],
+ span: #12 bytes(430..483),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: #16 bytes(423..427),
+ },
+ Ident {
+ ident: "E",
+ span: #16 bytes(428..429),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "V",
+ span: #16 bytes(444..445),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #16 bytes(446..447),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "let",
+ span: #16 bytes(450..453),
+ },
+ Ident {
+ ident: "_",
+ span: #16 bytes(454..455),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #16 bytes(456..457),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "PATH",
+ span: #0 bytes(615..619),
+ },
+ ],
+ span: #16 bytes(460..465),
+ },
+ ],
+ span: #16 bytes(458..467),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: #16 bytes(467..468),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #16 bytes(469..470),
+ },
+ ],
+ span: #16 bytes(448..472),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: #16 bytes(472..473),
+ },
+ ],
+ span: #16 bytes(430..483),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 + 1 } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: #20 bytes(423..427),
+ },
+ Ident {
+ ident: "E",
+ span: #20 bytes(428..429),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "V",
+ span: #20 bytes(444..445),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #20 bytes(446..447),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "let",
+ span: #20 bytes(450..453),
+ },
+ Ident {
+ ident: "_",
+ span: #20 bytes(454..455),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #20 bytes(456..457),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #0 bytes(636..637),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: #0 bytes(638..639),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: #0 bytes(640..641),
+ },
+ ],
+ span: #20 bytes(460..465),
+ },
+ ],
+ span: #20 bytes(458..467),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: #20 bytes(467..468),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #20 bytes(469..470),
+ },
+ ],
+ span: #20 bytes(448..472),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: #20 bytes(472..473),
+ },
+ ],
+ span: #20 bytes(430..483),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH + 1 } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: #24 bytes(423..427),
+ },
+ Ident {
+ ident: "E",
+ span: #24 bytes(428..429),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "V",
+ span: #24 bytes(444..445),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #24 bytes(446..447),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "let",
+ span: #24 bytes(450..453),
+ },
+ Ident {
+ ident: "_",
+ span: #24 bytes(454..455),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #24 bytes(456..457),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "PATH",
+ span: #0 bytes(658..662),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: #0 bytes(663..664),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: #0 bytes(665..666),
+ },
+ ],
+ span: #24 bytes(460..465),
+ },
+ ],
+ span: #24 bytes(458..467),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: #24 bytes(467..468),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #24 bytes(469..470),
+ },
+ ],
+ span: #24 bytes(448..472),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: #24 bytes(472..473),
+ },
+ ],
+ span: #24 bytes(430..483),
+ },
+]
diff --git a/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs b/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs
new file mode 100644
index 000000000..a6e64e1b1
--- /dev/null
+++ b/src/test/ui/proc-macro/extern-prelude-extern-crate-proc-macro.rs
@@ -0,0 +1,7 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// edition:2018
+
+extern crate proc_macro;
+use proc_macro::TokenStream; // OK
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/gen-lifetime-token.rs b/src/test/ui/proc-macro/gen-lifetime-token.rs
new file mode 100644
index 000000000..588bd2b76
--- /dev/null
+++ b/src/test/ui/proc-macro/gen-lifetime-token.rs
@@ -0,0 +1,11 @@
+// run-pass
+// aux-build:gen-lifetime-token.rs
+
+extern crate gen_lifetime_token as bar;
+
+bar::bar!();
+
+fn main() {
+ let x: &'static i32 = FOO;
+ assert_eq!(*x, 1);
+}
diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs
new file mode 100644
index 000000000..195bda82e
--- /dev/null
+++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs
@@ -0,0 +1,23 @@
+// `macro_rules` items produced by transparent macros have correct hygiene in basic cases.
+// Local variables and labels are hygienic, items are not hygienic.
+// `$crate` refers to the crate that defines `macro_rules` and not the outer transparent macro.
+
+// aux-build:gen-macro-rules-hygiene.rs
+
+#[macro_use]
+extern crate gen_macro_rules_hygiene;
+
+struct ItemUse;
+
+gen_macro_rules!();
+//~^ ERROR use of undeclared label `'label_use`
+//~| ERROR cannot find value `local_use` in this scope
+
+fn main() {
+ 'label_use: loop {
+ let local_use = 1;
+ generated!();
+ ItemDef; // OK
+ local_def; //~ ERROR cannot find value `local_def` in this scope
+ }
+}
diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr
new file mode 100644
index 000000000..6060f872f
--- /dev/null
+++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr
@@ -0,0 +1,32 @@
+error[E0426]: use of undeclared label `'label_use`
+ --> $DIR/gen-macro-rules-hygiene.rs:12:1
+ |
+LL | gen_macro_rules!();
+ | ^^^^^^^^^^^^^^^^^^ undeclared label `'label_use`
+...
+LL | generated!();
+ | ------------ in this macro invocation
+ |
+ = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0425]: cannot find value `local_use` in this scope
+ --> $DIR/gen-macro-rules-hygiene.rs:12:1
+ |
+LL | gen_macro_rules!();
+ | ^^^^^^^^^^^^^^^^^^ not found in this scope
+...
+LL | generated!();
+ | ------------ in this macro invocation
+ |
+ = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0425]: cannot find value `local_def` in this scope
+ --> $DIR/gen-macro-rules-hygiene.rs:21:9
+ |
+LL | local_def;
+ | ^^^^^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0425, E0426.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/gen-macro-rules.rs b/src/test/ui/proc-macro/gen-macro-rules.rs
new file mode 100644
index 000000000..13ad27f93
--- /dev/null
+++ b/src/test/ui/proc-macro/gen-macro-rules.rs
@@ -0,0 +1,13 @@
+// Derive macros can generate `macro_rules` items, regression test for issue #63651.
+
+// check-pass
+// aux-build:gen-macro-rules.rs
+
+extern crate gen_macro_rules as repro;
+
+#[derive(repro::repro)]
+pub struct S;
+
+m!(); // OK
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/generate-dollar-ident.rs b/src/test/ui/proc-macro/generate-dollar-ident.rs
new file mode 100644
index 000000000..b838be9fb
--- /dev/null
+++ b/src/test/ui/proc-macro/generate-dollar-ident.rs
@@ -0,0 +1,18 @@
+// Proc macros can generate token sequence `$ IDENT`
+// without it being recognized as an unknown macro variable.
+
+// check-pass
+// aux-build:generate-dollar-ident.rs
+
+extern crate generate_dollar_ident;
+use generate_dollar_ident::*;
+
+macro_rules! black_hole {
+ ($($tt:tt)*) => {};
+}
+
+black_hole!($var);
+
+dollar_ident!(black_hole);
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/generate-mod.rs b/src/test/ui/proc-macro/generate-mod.rs
new file mode 100644
index 000000000..471f317ed
--- /dev/null
+++ b/src/test/ui/proc-macro/generate-mod.rs
@@ -0,0 +1,33 @@
+// Modules generated by transparent proc macros still acts as barriers for names (issue #50504).
+
+// aux-build:generate-mod.rs
+
+extern crate generate_mod;
+
+struct FromOutside;
+
+generate_mod::check!(); //~ ERROR cannot find type `FromOutside` in this scope
+ //~| ERROR cannot find type `Outer` in this scope
+
+#[generate_mod::check_attr] //~ ERROR cannot find type `FromOutside` in this scope
+ //~| ERROR cannot find type `OuterAttr` in this scope
+struct S;
+
+#[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope
+ //~| ERROR cannot find type `OuterDerive` in this scope
+ //~| WARN this was previously accepted
+ //~| WARN this was previously accepted
+struct Z;
+
+fn inner_block() {
+ #[derive(generate_mod::CheckDerive)] //~ ERROR cannot find type `FromOutside` in this scope
+ //~| ERROR cannot find type `OuterDerive` in this scope
+ //~| WARN this was previously accepted
+ //~| WARN this was previously accepted
+ struct InnerZ;
+}
+
+#[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+struct W;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr
new file mode 100644
index 000000000..f1a167e37
--- /dev/null
+++ b/src/test/ui/proc-macro/generate-mod.stderr
@@ -0,0 +1,164 @@
+error[E0412]: cannot find type `FromOutside` in this scope
+ --> $DIR/generate-mod.rs:9:1
+ |
+LL | generate_mod::check!();
+ | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+ |
+ = note: consider importing this struct:
+ FromOutside
+ = note: this error originates in the macro `generate_mod::check` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0412]: cannot find type `Outer` in this scope
+ --> $DIR/generate-mod.rs:9:1
+ |
+LL | generate_mod::check!();
+ | ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+ |
+ = note: consider importing this struct:
+ Outer
+ = note: this error originates in the macro `generate_mod::check` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0412]: cannot find type `FromOutside` in this scope
+ --> $DIR/generate-mod.rs:12:1
+ |
+LL | #[generate_mod::check_attr]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+ |
+ = note: consider importing this struct:
+ FromOutside
+ = note: this error originates in the attribute macro `generate_mod::check_attr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0412]: cannot find type `OuterAttr` in this scope
+ --> $DIR/generate-mod.rs:12:1
+ |
+LL | #[generate_mod::check_attr]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+ |
+ = note: consider importing this struct:
+ OuterAttr
+ = note: this error originates in the attribute macro `generate_mod::check_attr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot find type `FromOutside` in this scope
+ --> $DIR/generate-mod.rs:16:10
+ |
+LL | #[derive(generate_mod::CheckDerive)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot find type `OuterDerive` in this scope
+ --> $DIR/generate-mod.rs:16:10
+ |
+LL | #[derive(generate_mod::CheckDerive)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot find type `FromOutside` in this scope
+ --> $DIR/generate-mod.rs:23:14
+ |
+LL | #[derive(generate_mod::CheckDerive)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot find type `OuterDerive` in this scope
+ --> $DIR/generate-mod.rs:23:14
+ |
+LL | #[derive(generate_mod::CheckDerive)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
+Future incompatibility report: Future breakage diagnostic:
+error: cannot find type `FromOutside` in this scope
+ --> $DIR/generate-mod.rs:16:10
+ |
+LL | #[derive(generate_mod::CheckDerive)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: cannot find type `OuterDerive` in this scope
+ --> $DIR/generate-mod.rs:16:10
+ |
+LL | #[derive(generate_mod::CheckDerive)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: cannot find type `FromOutside` in this scope
+ --> $DIR/generate-mod.rs:23:14
+ |
+LL | #[derive(generate_mod::CheckDerive)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+error: cannot find type `OuterDerive` in this scope
+ --> $DIR/generate-mod.rs:23:14
+ |
+LL | #[derive(generate_mod::CheckDerive)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: cannot find type `FromOutside` in this scope
+ --> $DIR/generate-mod.rs:30:10
+ |
+LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+note: the lint level is defined here
+ --> $DIR/generate-mod.rs:30:10
+ |
+LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: cannot find type `OuterDeriveLint` in this scope
+ --> $DIR/generate-mod.rs:30:10
+ |
+LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+ |
+note: the lint level is defined here
+ --> $DIR/generate-mod.rs:30:10
+ |
+LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs
new file mode 100644
index 000000000..40c42d82f
--- /dev/null
+++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs
@@ -0,0 +1,13 @@
+// aux-build:test-macros.rs
+
+#[macro_use(Empty)]
+extern crate test_macros;
+use test_macros::empty_attr as empty_helper;
+
+#[empty_helper] //~ ERROR `empty_helper` is ambiguous
+ //~| WARN derive helper attribute is used before it is introduced
+ //~| WARN this was previously accepted
+#[derive(Empty)]
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr
new file mode 100644
index 000000000..45b014c4b
--- /dev/null
+++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr
@@ -0,0 +1,35 @@
+error[E0659]: `empty_helper` is ambiguous
+ --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a derive helper attribute
+note: `empty_helper` could refer to the derive helper attribute defined here
+ --> $DIR/helper-attr-blocked-by-import-ambig.rs:10:10
+ |
+LL | #[derive(Empty)]
+ | ^^^^^
+note: `empty_helper` could also refer to the attribute macro imported here
+ --> $DIR/helper-attr-blocked-by-import-ambig.rs:5:5
+ |
+LL | use test_macros::empty_attr as empty_helper;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
+
+warning: derive helper attribute is used before it is introduced
+ --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:3
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^
+...
+LL | #[derive(Empty)]
+ | ----- the attribute is introduced here
+ |
+ = note: `#[warn(legacy_derive_helpers)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs b/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs
new file mode 100644
index 000000000..2e20a3de6
--- /dev/null
+++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs
@@ -0,0 +1,28 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// aux-build:test-macros.rs
+
+#[macro_use(Empty)]
+extern crate test_macros;
+
+use self::one::*;
+use self::two::*;
+
+mod empty_helper {}
+
+mod one {
+ use empty_helper;
+
+ #[derive(Empty)]
+ #[empty_helper]
+ struct One;
+}
+
+mod two {
+ use empty_helper;
+
+ #[derive(Empty)]
+ #[empty_helper]
+ struct Two;
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/hygiene_example.rs b/src/test/ui/proc-macro/hygiene_example.rs
new file mode 100644
index 000000000..346ed1207
--- /dev/null
+++ b/src/test/ui/proc-macro/hygiene_example.rs
@@ -0,0 +1,16 @@
+// check-pass
+// aux-build:hygiene_example_codegen.rs
+// aux-build:hygiene_example.rs
+
+extern crate hygiene_example;
+use hygiene_example::hello;
+
+fn main() {
+ mod hygiene_example {} // no conflict with `extern crate hygiene_example;` from the proc macro
+ macro_rules! format { () => {} } // does not interfere with `format!` from the proc macro
+ macro_rules! hello_helper { () => {} } // similarly does not intefere with the proc macro
+
+ let string = "world"; // no conflict with `string` from the proc macro
+ hello!(string);
+ hello!(string);
+}
diff --git a/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs
new file mode 100644
index 000000000..4efd9e952
--- /dev/null
+++ b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.rs
@@ -0,0 +1,15 @@
+extern crate proc_macro;
+
+#[proc_macro_derive(Foo)]
+//~^ ERROR: only usable with crates of the `proc-macro` crate type
+pub fn foo(a: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ a
+}
+
+// Issue #37590
+#[proc_macro_derive(Foo)]
+//~^ ERROR: the `#[proc_macro_derive]` attribute may only be used on bare functions
+pub struct Foo {
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr
new file mode 100644
index 000000000..c0930ab71
--- /dev/null
+++ b/src/test/ui/proc-macro/illegal-proc-macro-derive-use.stderr
@@ -0,0 +1,14 @@
+error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
+ --> $DIR/illegal-proc-macro-derive-use.rs:3:1
+ |
+LL | #[proc_macro_derive(Foo)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute may only be used on bare functions
+ --> $DIR/illegal-proc-macro-derive-use.rs:10:1
+ |
+LL | #[proc_macro_derive(Foo)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/import.rs b/src/test/ui/proc-macro/import.rs
new file mode 100644
index 000000000..d1b1ff350
--- /dev/null
+++ b/src/test/ui/proc-macro/import.rs
@@ -0,0 +1,8 @@
+// aux-build:test-macros.rs
+
+extern crate test_macros;
+
+use test_macros::empty_derive;
+//~^ ERROR: unresolved import `test_macros::empty_derive`
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/import.stderr b/src/test/ui/proc-macro/import.stderr
new file mode 100644
index 000000000..aae621193
--- /dev/null
+++ b/src/test/ui/proc-macro/import.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `test_macros::empty_derive`
+ --> $DIR/import.rs:5:5
+ |
+LL | use test_macros::empty_derive;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ no `empty_derive` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/proc-macro/inert-attribute-order.rs b/src/test/ui/proc-macro/inert-attribute-order.rs
new file mode 100644
index 000000000..f80796756
--- /dev/null
+++ b/src/test/ui/proc-macro/inert-attribute-order.rs
@@ -0,0 +1,23 @@
+// Order of inert attributes, both built-in and custom is preserved during expansion.
+
+// check-pass
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+/// 1
+#[rustfmt::attr2]
+#[doc = "3"]
+#[print_attr(nodebug)]
+#[doc = "4"]
+#[rustfmt::attr5]
+/// 6
+#[print_attr(nodebug)]
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/inert-attribute-order.stdout b/src/test/ui/proc-macro/inert-attribute-order.stdout
new file mode 100644
index 000000000..cc2155459
--- /dev/null
+++ b/src/test/ui/proc-macro/inert-attribute-order.stdout
@@ -0,0 +1,7 @@
+PRINT-ATTR INPUT (DISPLAY): /// 1
+#[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] #[rustfmt :: attr5] /// 6
+#[print_attr(nodebug)] struct S ;
+PRINT-ATTR RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"]
+#[rustfmt :: attr5] #[doc = " 6"] #[print_attr(nodebug)] struct S ;
+PRINT-ATTR INPUT (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"]
+#[rustfmt :: attr5] #[doc = " 6"] struct S ;
diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.rs b/src/test/ui/proc-macro/inner-attr-non-inline-mod.rs
new file mode 100644
index 000000000..30c2666df
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Z span-debug
+// error-pattern:custom inner attributes are unstable
+// error-pattern:inner macro attributes are unstable
+// error-pattern:this was previously accepted
+// aux-build:test-macros.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+#[deny(unused_attributes)]
+mod module_with_attrs;
+//~^ ERROR non-inline modules in proc macro input are unstable
+//~| ERROR custom inner attributes are unstable
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr
new file mode 100644
index 000000000..4286896df
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr
@@ -0,0 +1,40 @@
+error[E0658]: inner macro attributes are unstable
+ --> $DIR/module_with_attrs.rs:4:4
+ |
+LL | #![print_attr]
+ | ^^^^^^^^^^
+ |
+ = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
+ = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
+
+error[E0658]: non-inline modules in proc macro input are unstable
+ --> $DIR/inner-attr-non-inline-mod.rs:14:1
+ |
+LL | mod module_with_attrs;
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: custom inner attributes are unstable
+ --> $DIR/inner-attr-non-inline-mod.rs:14:1
+ |
+LL | mod module_with_attrs;
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
+ = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
+
+error: custom inner attributes are unstable
+ --> $DIR/module_with_attrs.rs:3:4
+ |
+LL | #![rustfmt::skip]
+ | ^^^^^^^^^^^^^
+ |
+ = note: `#[deny(soft_unstable)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout
new file mode 100644
index 000000000..6261d82e2
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stdout
@@ -0,0 +1,76 @@
+PRINT-ATTR INPUT (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #! [rustfmt :: skip] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "deny",
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "unused_attributes",
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ ],
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ ],
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Ident {
+ ident: "mod",
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Ident {
+ ident: "module_with_attrs",
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustfmt",
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Joint,
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ Ident {
+ ident: "skip",
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ ],
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+ ],
+ span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/inner-attrs.rs b/src/test/ui/proc-macro/inner-attrs.rs
new file mode 100644
index 000000000..2e3c704da
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attrs.rs
@@ -0,0 +1,86 @@
+// compile-flags: -Z span-debug --error-format human
+// aux-build:test-macros.rs
+// edition:2018
+
+#![feature(custom_inner_attributes)]
+#![feature(proc_macro_hygiene)]
+#![feature(stmt_expr_attributes)]
+#![feature(rustc_attrs)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+#[print_target_and_args(first)]
+#[print_target_and_args(second)]
+fn foo() {
+ #![print_target_and_args(third)]
+ #![print_target_and_args(fourth)]
+}
+
+#[print_target_and_args(mod_first)]
+#[print_target_and_args(mod_second)]
+mod inline_mod {
+ #![print_target_and_args(mod_third)]
+ #![print_target_and_args(mod_fourth)]
+}
+
+struct MyStruct {
+ field: bool
+}
+
+#[derive(Print)]
+struct MyDerivePrint {
+ field: [u8; {
+ match true {
+ _ => {
+ #![cfg_attr(not(FALSE), rustc_dummy(third))]
+ true
+ }
+ };
+ 0
+ }]
+}
+
+fn bar() {
+ #[print_target_and_args(tuple_attrs)] (
+ 3, 4, {
+ #![cfg_attr(not(FALSE), rustc_dummy(innermost))]
+ 5
+ }
+ );
+
+ #[print_target_and_args(tuple_attrs)] (
+ 3, 4, {
+ #![cfg_attr(not(FALSE), rustc_dummy(innermost))]
+ 5
+ }
+ );
+
+ for _ in &[true] {
+ #![print_attr] //~ ERROR expected non-macro inner attribute
+ }
+
+ let _ = {
+ #![print_attr] //~ ERROR expected non-macro inner attribute
+ };
+
+ let _ = async {
+ #![print_attr] //~ ERROR expected non-macro inner attribute
+ };
+
+ {
+ #![print_attr] //~ ERROR expected non-macro inner attribute
+ };
+}
+
+
+extern {
+ fn weird_extern() {
+ #![print_target_and_args_consume(tenth)]
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/inner-attrs.stderr b/src/test/ui/proc-macro/inner-attrs.stderr
new file mode 100644
index 000000000..4da8751ef
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attrs.stderr
@@ -0,0 +1,26 @@
+error: expected non-macro inner attribute, found attribute macro `print_attr`
+ --> $DIR/inner-attrs.rs:63:12
+ |
+LL | #![print_attr]
+ | ^^^^^^^^^^ not a non-macro inner attribute
+
+error: expected non-macro inner attribute, found attribute macro `print_attr`
+ --> $DIR/inner-attrs.rs:67:12
+ |
+LL | #![print_attr]
+ | ^^^^^^^^^^ not a non-macro inner attribute
+
+error: expected non-macro inner attribute, found attribute macro `print_attr`
+ --> $DIR/inner-attrs.rs:71:12
+ |
+LL | #![print_attr]
+ | ^^^^^^^^^^ not a non-macro inner attribute
+
+error: expected non-macro inner attribute, found attribute macro `print_attr`
+ --> $DIR/inner-attrs.rs:75:12
+ |
+LL | #![print_attr]
+ | ^^^^^^^^^^ not a non-macro inner attribute
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/proc-macro/inner-attrs.stdout b/src/test/ui/proc-macro/inner-attrs.stdout
new file mode 100644
index 000000000..eaa8882d6
--- /dev/null
+++ b/src/test/ui/proc-macro/inner-attrs.stdout
@@ -0,0 +1,956 @@
+PRINT-ATTR_ARGS INPUT (DISPLAY): first
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "first",
+ span: $DIR/inner-attrs.rs:16:25: 16:30 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second)] fn foo()
+{ #! [print_target_and_args(third)] #! [print_target_and_args(fourth)] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:17:1: 17:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:17:3: 17:24 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "second",
+ span: $DIR/inner-attrs.rs:17:25: 17:31 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:17:24: 17:32 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:17:2: 17:33 (#0),
+ },
+ Ident {
+ ident: "fn",
+ span: $DIR/inner-attrs.rs:18:1: 18:3 (#0),
+ },
+ Ident {
+ ident: "foo",
+ span: $DIR/inner-attrs.rs:18:4: 18:7 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/inner-attrs.rs:18:7: 18:9 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:19:5: 19:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:19:6: 19:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:19:8: 19:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "third",
+ span: $DIR/inner-attrs.rs:19:30: 19:35 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:19:29: 19:36 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:19:7: 19:37 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:20:5: 20:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:20:6: 20:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:20:8: 20:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "fourth",
+ span: $DIR/inner-attrs.rs:20:30: 20:36 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:29: 20:37 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:7: 20:38 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:18:10: 21:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): second
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "second",
+ span: $DIR/inner-attrs.rs:17:25: 17:31 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): fn foo()
+{ #! [print_target_and_args(third)] #! [print_target_and_args(fourth)] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fn",
+ span: $DIR/inner-attrs.rs:18:1: 18:3 (#0),
+ },
+ Ident {
+ ident: "foo",
+ span: $DIR/inner-attrs.rs:18:4: 18:7 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/inner-attrs.rs:18:7: 18:9 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:19:5: 19:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:19:6: 19:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:19:8: 19:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "third",
+ span: $DIR/inner-attrs.rs:19:30: 19:35 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:19:29: 19:36 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:19:7: 19:37 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:20:5: 20:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:20:6: 20:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:20:8: 20:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "fourth",
+ span: $DIR/inner-attrs.rs:20:30: 20:36 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:29: 20:37 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:7: 20:38 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:18:10: 21:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): third
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "third",
+ span: $DIR/inner-attrs.rs:19:30: 19:35 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): fn foo() { #! [print_target_and_args(fourth)] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fn",
+ span: $DIR/inner-attrs.rs:18:1: 18:3 (#0),
+ },
+ Ident {
+ ident: "foo",
+ span: $DIR/inner-attrs.rs:18:4: 18:7 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/inner-attrs.rs:18:7: 18:9 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:20:5: 20:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:20:6: 20:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:20:8: 20:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "fourth",
+ span: $DIR/inner-attrs.rs:20:30: 20:36 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:29: 20:37 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:20:7: 20:38 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:18:10: 21:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): fourth
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fourth",
+ span: $DIR/inner-attrs.rs:20:30: 20:36 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): fn foo() {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fn",
+ span: $DIR/inner-attrs.rs:18:1: 18:3 (#0),
+ },
+ Ident {
+ ident: "foo",
+ span: $DIR/inner-attrs.rs:18:4: 18:7 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/inner-attrs.rs:18:7: 18:9 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/inner-attrs.rs:18:10: 21:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): mod_first
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "mod_first",
+ span: $DIR/inner-attrs.rs:23:25: 23:34 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(mod_second)] mod inline_mod
+{
+ #! [print_target_and_args(mod_third)] #!
+ [print_target_and_args(mod_fourth)]
+}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:24:1: 24:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:24:3: 24:24 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "mod_second",
+ span: $DIR/inner-attrs.rs:24:25: 24:35 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:24:24: 24:36 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:24:2: 24:37 (#0),
+ },
+ Ident {
+ ident: "mod",
+ span: $DIR/inner-attrs.rs:25:1: 25:4 (#0),
+ },
+ Ident {
+ ident: "inline_mod",
+ span: $DIR/inner-attrs.rs:25:5: 25:15 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:26:5: 26:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:26:6: 26:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:26:8: 26:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "mod_third",
+ span: $DIR/inner-attrs.rs:26:30: 26:39 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:26:29: 26:40 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:26:7: 26:41 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:27:5: 27:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:27:6: 27:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:27:8: 27:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "mod_fourth",
+ span: $DIR/inner-attrs.rs:27:30: 27:40 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:29: 27:41 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:7: 27:42 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:25:16: 28:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): mod_second
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "mod_second",
+ span: $DIR/inner-attrs.rs:24:25: 24:35 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): mod inline_mod
+{
+ #! [print_target_and_args(mod_third)] #!
+ [print_target_and_args(mod_fourth)]
+}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "mod",
+ span: $DIR/inner-attrs.rs:25:1: 25:4 (#0),
+ },
+ Ident {
+ ident: "inline_mod",
+ span: $DIR/inner-attrs.rs:25:5: 25:15 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:26:5: 26:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:26:6: 26:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:26:8: 26:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "mod_third",
+ span: $DIR/inner-attrs.rs:26:30: 26:39 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:26:29: 26:40 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:26:7: 26:41 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:27:5: 27:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:27:6: 27:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:27:8: 27:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "mod_fourth",
+ span: $DIR/inner-attrs.rs:27:30: 27:40 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:29: 27:41 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:7: 27:42 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:25:16: 28:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): mod_third
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "mod_third",
+ span: $DIR/inner-attrs.rs:26:30: 26:39 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): mod inline_mod { #! [print_target_and_args(mod_fourth)] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "mod",
+ span: $DIR/inner-attrs.rs:25:1: 25:4 (#0),
+ },
+ Ident {
+ ident: "inline_mod",
+ span: $DIR/inner-attrs.rs:25:5: 25:15 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:27:5: 27:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:27:6: 27:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/inner-attrs.rs:27:8: 27:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "mod_fourth",
+ span: $DIR/inner-attrs.rs:27:30: 27:40 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:29: 27:41 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:27:7: 27:42 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:25:16: 28:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): mod_fourth
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "mod_fourth",
+ span: $DIR/inner-attrs.rs:27:30: 27:40 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): mod inline_mod {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "mod",
+ span: $DIR/inner-attrs.rs:25:1: 25:4 (#0),
+ },
+ Ident {
+ ident: "inline_mod",
+ span: $DIR/inner-attrs.rs:25:5: 25:15 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/inner-attrs.rs:25:16: 28:2 (#0),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): struct MyDerivePrint
+{
+ field :
+ [u8 ; { match true { _ => { #! [rustc_dummy(third)] true } } ; 0 }]
+}
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/inner-attrs.rs:35:1: 35:7 (#0),
+ },
+ Ident {
+ ident: "MyDerivePrint",
+ span: $DIR/inner-attrs.rs:35:8: 35:21 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "field",
+ span: $DIR/inner-attrs.rs:36:5: 36:10 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:36:10: 36:11 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "u8",
+ span: $DIR/inner-attrs.rs:36:13: 36:15 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:36:15: 36:16 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "match",
+ span: $DIR/inner-attrs.rs:37:9: 37:14 (#0),
+ },
+ Ident {
+ ident: "true",
+ span: $DIR/inner-attrs.rs:37:15: 37:19 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "_",
+ span: $DIR/inner-attrs.rs:38:13: 38:14 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:38:15: 38:17 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:38:15: 38:17 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:39:17: 39:18 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:39:18: 39:19 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/inner-attrs.rs:39:41: 39:52 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "third",
+ span: $DIR/inner-attrs.rs:39:53: 39:58 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:39:52: 39:59 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:39:17: 39:18 (#0),
+ },
+ Ident {
+ ident: "true",
+ span: $DIR/inner-attrs.rs:40:17: 40:21 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:38:18: 41:14 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:37:20: 42:10 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:42:10: 42:11 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/inner-attrs.rs:43:9: 43:10 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:36:17: 44:6 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:36:12: 44:7 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:35:22: 45:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "tuple_attrs",
+ span: $DIR/inner-attrs.rs:48:29: 48:40 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "3",
+ suffix: None,
+ span: $DIR/inner-attrs.rs:49:9: 49:10 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:49:10: 49:11 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "4",
+ suffix: None,
+ span: $DIR/inner-attrs.rs:49:12: 49:13 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:49:13: 49:14 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:50:13: 50:14 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:50:14: 50:15 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg_attr",
+ span: $DIR/inner-attrs.rs:50:16: 50:24 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/inner-attrs.rs:50:25: 50:28 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/inner-attrs.rs:50:29: 50:34 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:50:28: 50:35 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:50:35: 50:36 (#0),
+ },
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/inner-attrs.rs:50:37: 50:48 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "innermost",
+ span: $DIR/inner-attrs.rs:50:49: 50:58 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:50:48: 50:59 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:50:24: 50:60 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:50:15: 50:61 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "5",
+ suffix: None,
+ span: $DIR/inner-attrs.rs:51:13: 51:14 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:49:15: 52:10 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:48:43: 53:6 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:53:6: 53:7 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "tuple_attrs",
+ span: $DIR/inner-attrs.rs:55:29: 55:40 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "3",
+ suffix: None,
+ span: $DIR/inner-attrs.rs:56:9: 56:10 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:56:10: 56:11 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "4",
+ suffix: None,
+ span: $DIR/inner-attrs.rs:56:12: 56:13 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:56:13: 56:14 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/inner-attrs.rs:57:13: 57:14 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:57:14: 57:15 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg_attr",
+ span: $DIR/inner-attrs.rs:57:16: 57:24 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/inner-attrs.rs:57:25: 57:28 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/inner-attrs.rs:57:29: 57:34 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:57:28: 57:35 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:57:35: 57:36 (#0),
+ },
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/inner-attrs.rs:57:37: 57:48 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "innermost",
+ span: $DIR/inner-attrs.rs:57:49: 57:58 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:57:48: 57:59 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:57:24: 57:60 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:57:15: 57:61 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "5",
+ suffix: None,
+ span: $DIR/inner-attrs.rs:58:13: 58:14 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:56:15: 59:10 (#0),
+ },
+ ],
+ span: $DIR/inner-attrs.rs:55:43: 60:6 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/inner-attrs.rs:60:6: 60:7 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): tenth
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "tenth",
+ span: $DIR/inner-attrs.rs:82:42: 82:47 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): fn weird_extern() {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fn",
+ span: $DIR/inner-attrs.rs:81:5: 81:7 (#0),
+ },
+ Ident {
+ ident: "weird_extern",
+ span: $DIR/inner-attrs.rs:81:8: 81:20 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/inner-attrs.rs:81:20: 81:22 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/inner-attrs.rs:81:23: 83:6 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/input-interpolated.rs b/src/test/ui/proc-macro/input-interpolated.rs
new file mode 100644
index 000000000..5e49e330c
--- /dev/null
+++ b/src/test/ui/proc-macro/input-interpolated.rs
@@ -0,0 +1,29 @@
+// Check what token streams proc macros see when interpolated tokens are passed to them as input.
+
+// check-pass
+// edition:2018
+// aux-build:test-macros.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! pass_ident {
+ ($i:ident) => {
+ fn f() {
+ print_bang!($i);
+ }
+
+ #[print_attr]
+ const $i: u8 = 0;
+
+ #[derive(Print)]
+ struct $i {}
+ };
+}
+
+pass_ident!(A);
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/input-interpolated.stdout b/src/test/ui/proc-macro/input-interpolated.stdout
new file mode 100644
index 000000000..34566c780
--- /dev/null
+++ b/src/test/ui/proc-macro/input-interpolated.stdout
@@ -0,0 +1,59 @@
+PRINT-BANG INPUT (DISPLAY): A
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "A",
+ span: #0 bytes(503..504),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0 ;
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "const",
+ span: #4 bytes(416..421),
+ },
+ Ident {
+ ident: "A",
+ span: #0 bytes(503..504),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: #4 bytes(424..425),
+ },
+ Ident {
+ ident: "u8",
+ span: #4 bytes(426..428),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: #4 bytes(429..430),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: #4 bytes(431..432),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: #4 bytes(432..433),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): struct A {}
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: #4 bytes(468..474),
+ },
+ Ident {
+ ident: "A",
+ span: #0 bytes(503..504),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: #4 bytes(478..480),
+ },
+]
diff --git a/src/test/ui/proc-macro/invalid-attributes.rs b/src/test/ui/proc-macro/invalid-attributes.rs
new file mode 100644
index 000000000..6bbe022c6
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-attributes.rs
@@ -0,0 +1,26 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro = "test"] //~ ERROR malformed `proc_macro` attribute
+pub fn a(a: TokenStream) -> TokenStream { a }
+
+#[proc_macro()] //~ ERROR malformed `proc_macro` attribute
+pub fn c(a: TokenStream) -> TokenStream { a }
+
+#[proc_macro(x)] //~ ERROR malformed `proc_macro` attribute
+pub fn d(a: TokenStream) -> TokenStream { a }
+
+#[proc_macro_attribute = "test"] //~ ERROR malformed `proc_macro_attribute` attribute
+pub fn e(_: TokenStream, a: TokenStream) -> TokenStream { a }
+
+#[proc_macro_attribute()] //~ ERROR malformed `proc_macro_attribute` attribute
+pub fn g(_: TokenStream, a: TokenStream) -> TokenStream { a }
+
+#[proc_macro_attribute(x)] //~ ERROR malformed `proc_macro_attribute` attribute
+pub fn h(_: TokenStream, a: TokenStream) -> TokenStream { a }
diff --git a/src/test/ui/proc-macro/invalid-attributes.stderr b/src/test/ui/proc-macro/invalid-attributes.stderr
new file mode 100644
index 000000000..fe411fa5e
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-attributes.stderr
@@ -0,0 +1,38 @@
+error: malformed `proc_macro` attribute input
+ --> $DIR/invalid-attributes.rs:10:1
+ |
+LL | #[proc_macro = "test"]
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]`
+
+error: malformed `proc_macro` attribute input
+ --> $DIR/invalid-attributes.rs:13:1
+ |
+LL | #[proc_macro()]
+ | ^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]`
+
+error: malformed `proc_macro` attribute input
+ --> $DIR/invalid-attributes.rs:16:1
+ |
+LL | #[proc_macro(x)]
+ | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]`
+
+error: malformed `proc_macro_attribute` attribute input
+ --> $DIR/invalid-attributes.rs:19:1
+ |
+LL | #[proc_macro_attribute = "test"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]`
+
+error: malformed `proc_macro_attribute` attribute input
+ --> $DIR/invalid-attributes.rs:22:1
+ |
+LL | #[proc_macro_attribute()]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]`
+
+error: malformed `proc_macro_attribute` attribute input
+ --> $DIR/invalid-attributes.rs:25:1
+ |
+LL | #[proc_macro_attribute(x)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
new file mode 100644
index 000000000..814cd77cf
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs
@@ -0,0 +1,8 @@
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+invalid_punct!(); //~ ERROR proc macro panicked
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.stderr b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
new file mode 100644
index 000000000..7babe685b
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-1.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+ --> $DIR/invalid-punct-ident-1.rs:6:1
+ |
+LL | invalid_punct!();
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: message: unsupported character `'`'`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
new file mode 100644
index 000000000..a04dec707
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs
@@ -0,0 +1,8 @@
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+invalid_ident!(); //~ ERROR proc macro panicked
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.stderr b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
new file mode 100644
index 000000000..01b80768c
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-2.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+ --> $DIR/invalid-punct-ident-2.rs:6:1
+ |
+LL | invalid_ident!();
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: message: `"*"` is not a valid identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
new file mode 100644
index 000000000..f0e953608
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs
@@ -0,0 +1,8 @@
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+invalid_raw_ident!(); //~ ERROR proc macro panicked
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.stderr b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
new file mode 100644
index 000000000..899c38158
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-3.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+ --> $DIR/invalid-punct-ident-3.rs:6:1
+ |
+LL | invalid_raw_ident!();
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: message: `self` cannot be a raw identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.rs b/src/test/ui/proc-macro/invalid-punct-ident-4.rs
new file mode 100644
index 000000000..59b347dac
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-4.rs
@@ -0,0 +1,12 @@
+// aux-build:invalid-punct-ident.rs
+
+#[macro_use]
+extern crate invalid_punct_ident;
+
+lexer_failure!();
+//~^ ERROR proc macro panicked
+//~| ERROR unexpected closing delimiter: `)`
+
+fn main() {
+ let _recovery_witness: () = 0; //~ ERROR mismatched types
+}
diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr
new file mode 100644
index 000000000..deb93b893
--- /dev/null
+++ b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr
@@ -0,0 +1,25 @@
+error: unexpected closing delimiter: `)`
+ --> $DIR/invalid-punct-ident-4.rs:6:1
+ |
+LL | lexer_failure!();
+ | ^^^^^^^^^^^^^^^^ unexpected closing delimiter
+ |
+ = note: this error originates in the macro `lexer_failure` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: proc macro panicked
+ --> $DIR/invalid-punct-ident-4.rs:6:1
+ |
+LL | lexer_failure!();
+ | ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/invalid-punct-ident-4.rs:11:33
+ |
+LL | let _recovery_witness: () = 0;
+ | -- ^ expected `()`, found integer
+ | |
+ | expected due to this
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/is-available.rs b/src/test/ui/proc-macro/is-available.rs
new file mode 100644
index 000000000..b32bb61b4
--- /dev/null
+++ b/src/test/ui/proc-macro/is-available.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+extern crate proc_macro;
+
+// aux-build:is-available.rs
+extern crate is_available;
+
+fn main() {
+ let a = proc_macro::is_available();
+ let b = is_available::from_inside_proc_macro!();
+ let c = proc_macro::is_available();
+ assert!(!a);
+ assert!(b);
+ assert!(!c);
+}
diff --git a/src/test/ui/proc-macro/issue-36935.rs b/src/test/ui/proc-macro/issue-36935.rs
new file mode 100644
index 000000000..5c43a564c
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-36935.rs
@@ -0,0 +1,13 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Identity, Panic)] //~ ERROR proc-macro derive panicked
+struct Baz {
+ //~^ ERROR the name `Baz` is defined multiple times
+ a: i32,
+ b: i32,
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-36935.stderr b/src/test/ui/proc-macro/issue-36935.stderr
new file mode 100644
index 000000000..079e134c6
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-36935.stderr
@@ -0,0 +1,22 @@
+error[E0428]: the name `Baz` is defined multiple times
+ --> $DIR/issue-36935.rs:7:1
+ |
+LL | struct Baz {
+ | ^^^^^^^^^^
+ | |
+ | `Baz` redefined here
+ | previous definition of the type `Baz` here
+ |
+ = note: `Baz` must be defined only once in the type namespace of this module
+
+error: proc-macro derive panicked
+ --> $DIR/issue-36935.rs:6:20
+ |
+LL | #[derive(Identity, Panic)]
+ | ^^^^^
+ |
+ = help: message: panic-derive
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/proc-macro/issue-37788.rs b/src/test/ui/proc-macro/issue-37788.rs
new file mode 100644
index 000000000..73b1f0d58
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-37788.rs
@@ -0,0 +1,9 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+fn main() {
+ // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE.
+ std::cell::Cell::new(0) //~ ERROR mismatched types
+}
diff --git a/src/test/ui/proc-macro/issue-37788.stderr b/src/test/ui/proc-macro/issue-37788.stderr
new file mode 100644
index 000000000..345520d48
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-37788.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-37788.rs:8:5
+ |
+LL | fn main() {
+ | - expected `()` because of default return type
+LL | // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE.
+LL | std::cell::Cell::new(0)
+ | ^^^^^^^^^^^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
+ | |
+ | expected `()`, found struct `Cell`
+ |
+ = note: expected unit type `()`
+ found struct `Cell<{integer}>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/issue-38586.rs b/src/test/ui/proc-macro/issue-38586.rs
new file mode 100644
index 000000000..24e88ed93
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-38586.rs
@@ -0,0 +1,9 @@
+// aux-build:issue-38586.rs
+
+#[macro_use]
+extern crate issue_38586;
+
+#[derive(A)] //~ ERROR `foo`
+struct A;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-38586.stderr b/src/test/ui/proc-macro/issue-38586.stderr
new file mode 100644
index 000000000..ddd0a0874
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-38586.stderr
@@ -0,0 +1,11 @@
+error[E0425]: cannot find value `foo` in this scope
+ --> $DIR/issue-38586.rs:6:10
+ |
+LL | #[derive(A)]
+ | ^ not found in this scope
+ |
+ = note: this error originates in the derive macro `A` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/issue-39889.rs b/src/test/ui/proc-macro/issue-39889.rs
new file mode 100644
index 000000000..69bfb4f3c
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-39889.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+#![allow(dead_code, unused_macros)]
+// aux-build:issue-39889.rs
+
+extern crate issue_39889;
+use issue_39889::Issue39889;
+
+#[derive(Issue39889)]
+struct S;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-41211.rs b/src/test/ui/proc-macro/issue-41211.rs
new file mode 100644
index 000000000..072a63baf
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-41211.rs
@@ -0,0 +1,16 @@
+// aux-build:test-macros.rs
+
+// FIXME: https://github.com/rust-lang/rust/issues/41430
+// This is a temporary regression test for the ICE reported in #41211
+
+#![feature(custom_inner_attributes)]
+#![feature(register_attr)]
+
+#![register_attr(identity_attr)]
+
+#![identity_attr]
+//~^ ERROR `identity_attr` is ambiguous
+extern crate test_macros;
+use test_macros::identity_attr;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-41211.stderr b/src/test/ui/proc-macro/issue-41211.stderr
new file mode 100644
index 000000000..60cd36a9c
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-41211.stderr
@@ -0,0 +1,22 @@
+error[E0659]: `identity_attr` is ambiguous
+ --> $DIR/issue-41211.rs:11:4
+ |
+LL | #![identity_attr]
+ | ^^^^^^^^^^^^^ ambiguous name
+ |
+ = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution
+note: `identity_attr` could refer to the attribute macro imported here
+ --> $DIR/issue-41211.rs:14:5
+ |
+LL | use test_macros::identity_attr;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: use `crate::identity_attr` to refer to this attribute macro unambiguously
+note: `identity_attr` could also refer to the explicitly registered attribute defined here
+ --> $DIR/issue-41211.rs:9:18
+ |
+LL | #![register_attr(identity_attr)]
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/proc-macro/issue-42708.rs b/src/test/ui/proc-macro/issue-42708.rs
new file mode 100644
index 000000000..e8f445aaa
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-42708.rs
@@ -0,0 +1,26 @@
+// run-pass
+// aux-build:issue-42708.rs
+
+#![feature(decl_macro)]
+#![allow(unused)]
+
+extern crate issue_42708;
+
+macro m() {
+ #[derive(issue_42708::Test)]
+ struct S { x: () }
+
+ #[issue_42708::attr_test]
+ struct S2 { x: () }
+
+ #[derive(Clone)]
+ struct S3 { x: () }
+
+ fn g(s: S, s2: S2, s3: S3) {
+ (s.x, s2.x, s3.x);
+ }
+}
+
+m!();
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-50061.rs b/src/test/ui/proc-macro/issue-50061.rs
new file mode 100644
index 000000000..01c6b80b4
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-50061.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+#![allow(path_statements)]
+// aux-build:issue-50061.rs
+
+#![feature(decl_macro)]
+
+extern crate issue_50061;
+
+macro inner(any_token $v: tt) {
+ $v
+}
+
+macro outer($v: tt) {
+ inner!(any_token $v)
+}
+
+#[issue_50061::check]
+fn main() {
+ //! this doc comment forces roundtrip through a string
+ let checkit = 0;
+ outer!(checkit);
+}
diff --git a/src/test/ui/proc-macro/issue-50493.rs b/src/test/ui/proc-macro/issue-50493.rs
new file mode 100644
index 000000000..ce0e0839f
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-50493.rs
@@ -0,0 +1,13 @@
+// aux-build:issue-50493.rs
+
+#[macro_use]
+extern crate issue_50493;
+
+#[derive(Derive)]
+struct Restricted {
+ pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules
+}
+
+mod restricted {}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-50493.stderr b/src/test/ui/proc-macro/issue-50493.stderr
new file mode 100644
index 000000000..23e103dbf
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-50493.stderr
@@ -0,0 +1,9 @@
+error[E0742]: visibilities can only be restricted to ancestor modules
+ --> $DIR/issue-50493.rs:8:12
+ |
+LL | pub(in restricted) field: usize,
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0742`.
diff --git a/src/test/ui/proc-macro/issue-53481.rs b/src/test/ui/proc-macro/issue-53481.rs
new file mode 100644
index 000000000..ae10a3baa
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-53481.rs
@@ -0,0 +1,22 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+mod m1 {
+ use m2::Empty;
+
+ #[derive(Empty)]
+ struct A {}
+}
+
+mod m2 {
+ pub type Empty = u8;
+
+ #[derive(Empty)]
+ #[empty_helper]
+ struct B {}
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs
new file mode 100644
index 000000000..a4161d4fc
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.rs
@@ -0,0 +1,10 @@
+// Test that using a macro to replace the entire crate tree with a non-'mod' item errors out nicely.
+// `issue_59191::no_main` replaces whatever's passed in with `fn main() {}`.
+
+// edition:2018
+// aux-crate:issue_59191=issue-59191.rs
+// error-pattern: requires `sized` lang_item
+
+#![feature(custom_inner_attributes)]
+#![issue_59191::no_main]
+#![issue_59191::no_main]
diff --git a/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr
new file mode 100644
index 000000000..f7516c7d3
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr
@@ -0,0 +1,4 @@
+error: requires `sized` lang_item
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/issue-66286.rs b/src/test/ui/proc-macro/issue-66286.rs
new file mode 100644
index 000000000..2a67aeab4
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-66286.rs
@@ -0,0 +1,13 @@
+// aux-build:issue-66286.rs
+
+// Regression test for #66286.
+
+extern crate issue_66286;
+
+#[issue_66286::vec_ice]
+pub extern fn foo(_: Vec(u32)) -> u32 {
+ //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait
+ 0
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-66286.stderr b/src/test/ui/proc-macro/issue-66286.stderr
new file mode 100644
index 000000000..fe2464b3b
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-66286.stderr
@@ -0,0 +1,14 @@
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+ --> $DIR/issue-66286.rs:8:22
+ |
+LL | pub extern fn foo(_: Vec(u32)) -> u32 {
+ | ^^^^^^^^ only `Fn` traits may use parentheses
+ |
+help: use angle brackets instead
+ |
+LL | pub extern fn foo(_: Vec<u32>) -> u32 {
+ | ~ ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0214`.
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs
new file mode 100644
index 000000000..0c1c51c01
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs
@@ -0,0 +1,19 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Print)]
+enum ProceduralMasqueradeDummyType {
+//~^ ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+ Input
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
new file mode 100644
index 000000000..be4239089
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
@@ -0,0 +1,91 @@
+error: using `procedural-masquerade` crate
+ --> $DIR/issue-73933-procedural-masquerade.rs:7:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
+error: using `procedural-masquerade` crate
+ --> $DIR/issue-73933-procedural-masquerade.rs:7:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
+error: using `procedural-masquerade` crate
+ --> $DIR/issue-73933-procedural-masquerade.rs:7:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
+error: using `procedural-masquerade` crate
+ --> $DIR/issue-73933-procedural-masquerade.rs:7:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
+error: aborting due to 4 previous errors
+
+Future incompatibility report: Future breakage diagnostic:
+error: using `procedural-masquerade` crate
+ --> $DIR/issue-73933-procedural-masquerade.rs:7:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
+Future breakage diagnostic:
+error: using `procedural-masquerade` crate
+ --> $DIR/issue-73933-procedural-masquerade.rs:7:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
+Future breakage diagnostic:
+error: using `procedural-masquerade` crate
+ --> $DIR/issue-73933-procedural-masquerade.rs:7:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
+Future breakage diagnostic:
+error: using `procedural-masquerade` crate
+ --> $DIR/issue-73933-procedural-masquerade.rs:7:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
+
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout
new file mode 100644
index 000000000..50334589d
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout
@@ -0,0 +1,22 @@
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
+PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: #0 bytes(86..90),
+ },
+ Ident {
+ ident: "ProceduralMasqueradeDummyType",
+ span: #0 bytes(91..120),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Input",
+ span: #0 bytes(315..320),
+ },
+ ],
+ span: #0 bytes(121..322),
+ },
+]
diff --git a/src/test/ui/proc-macro/issue-75734-pp-paren.rs b/src/test/ui/proc-macro/issue-75734-pp-paren.rs
new file mode 100644
index 000000000..faa93787d
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-75734-pp-paren.rs
@@ -0,0 +1,26 @@
+// Regression test for issue #75734
+// Ensures that we don't lose tokens when pretty-printing would
+// normally insert extra parentheses.
+
+// check-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! mul_2 {
+ ($val:expr) => {
+ print_bang!($val * 2);
+ };
+}
+
+
+#[print_attr]
+fn main() {
+ &|_: u8| {};
+ mul_2!(1 + 1);
+}
diff --git a/src/test/ui/proc-macro/issue-75734-pp-paren.stdout b/src/test/ui/proc-macro/issue-75734-pp-paren.stdout
new file mode 100644
index 000000000..0fda6654f
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-75734-pp-paren.stdout
@@ -0,0 +1,134 @@
+PRINT-ATTR INPUT (DISPLAY): fn main() { & | _ : u8 | {} ; mul_2! (1 + 1) ; }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fn",
+ span: $DIR/issue-75734-pp-paren.rs:23:1: 23:3 (#0),
+ },
+ Ident {
+ ident: "main",
+ span: $DIR/issue-75734-pp-paren.rs:23:4: 23:8 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/issue-75734-pp-paren.rs:23:8: 23:10 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '&',
+ spacing: Joint,
+ span: $DIR/issue-75734-pp-paren.rs:24:5: 24:6 (#0),
+ },
+ Punct {
+ ch: '|',
+ spacing: Alone,
+ span: $DIR/issue-75734-pp-paren.rs:24:6: 24:7 (#0),
+ },
+ Ident {
+ ident: "_",
+ span: $DIR/issue-75734-pp-paren.rs:24:7: 24:8 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/issue-75734-pp-paren.rs:24:8: 24:9 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/issue-75734-pp-paren.rs:24:10: 24:12 (#0),
+ },
+ Punct {
+ ch: '|',
+ spacing: Alone,
+ span: $DIR/issue-75734-pp-paren.rs:24:12: 24:13 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/issue-75734-pp-paren.rs:24:14: 24:16 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75734-pp-paren.rs:24:16: 24:17 (#0),
+ },
+ Ident {
+ ident: "mul_2",
+ span: $DIR/issue-75734-pp-paren.rs:25:5: 25:10 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/issue-75734-pp-paren.rs:25:10: 25:11 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/issue-75734-pp-paren.rs:25:12: 25:13 (#0),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/issue-75734-pp-paren.rs:25:14: 25:15 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/issue-75734-pp-paren.rs:25:16: 25:17 (#0),
+ },
+ ],
+ span: $DIR/issue-75734-pp-paren.rs:25:11: 25:18 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75734-pp-paren.rs:25:18: 25:19 (#0),
+ },
+ ],
+ span: $DIR/issue-75734-pp-paren.rs:23:11: 26:2 (#0),
+ },
+]
+PRINT-BANG INPUT (DISPLAY): 1 + 1 * 2
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/issue-75734-pp-paren.rs:25:12: 25:13 (#0),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/issue-75734-pp-paren.rs:25:14: 25:15 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/issue-75734-pp-paren.rs:25:16: 25:17 (#0),
+ },
+ ],
+ span: $DIR/issue-75734-pp-paren.rs:17:21: 17:25 (#7),
+ },
+ Punct {
+ ch: '*',
+ spacing: Alone,
+ span: $DIR/issue-75734-pp-paren.rs:17:26: 17:27 (#7),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "2",
+ suffix: None,
+ span: $DIR/issue-75734-pp-paren.rs:17:28: 17:29 (#7),
+ },
+]
diff --git a/src/test/ui/proc-macro/issue-75801.rs b/src/test/ui/proc-macro/issue-75801.rs
new file mode 100644
index 000000000..b07cde0fa
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-75801.rs
@@ -0,0 +1,19 @@
+// aux-build: issue-75801.rs
+
+// Regression test for #75801.
+
+#[macro_use]
+extern crate issue_75801;
+
+macro_rules! foo {
+ ($arg:expr) => {
+ #[foo]
+ fn bar() {
+ let _bar: u32 = $arg;
+ }
+ };
+}
+
+foo!("baz"); //~ ERROR: mismatched types [E0308]
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-75801.stderr b/src/test/ui/proc-macro/issue-75801.stderr
new file mode 100644
index 000000000..ee0a9bd77
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-75801.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-75801.rs:17:6
+ |
+LL | let _bar: u32 = $arg;
+ | --- expected due to this
+...
+LL | foo!("baz");
+ | ^^^^^ expected `u32`, found `&str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.rs b/src/test/ui/proc-macro/issue-75930-derive-cfg.rs
new file mode 100644
index 000000000..ef56e8e02
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.rs
@@ -0,0 +1,74 @@
+// check-pass
+// compile-flags: -Z span-debug --error-format human
+// aux-build:test-macros.rs
+
+// Regression test for issue #75930
+// Tests that we cfg-strip all targets before invoking
+// a derive macro
+// We need '--error-format human' to stop compiletest from
+// trying to interpret proc-macro output as JSON messages
+// (a pretty-printed struct may cause a line to start with '{' )
+// FIXME: We currently lose spans here (see issue #43081)
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+#[print_helper(a)] //~ WARN derive helper attribute is used before it is introduced
+ //~| WARN this was previously accepted
+#[cfg_attr(not(FALSE), allow(dead_code))]
+#[print_attr]
+#[derive(Print)]
+#[print_helper(b)]
+struct Foo<#[cfg(FALSE)] A, B> {
+ #[cfg(FALSE)] first: String,
+ #[cfg_attr(FALSE, deny(warnings))] second: bool,
+ third: [u8; {
+ #[cfg(FALSE)] struct Bar;
+ #[cfg(not(FALSE))] struct Inner;
+ #[cfg(FALSE)] let a = 25;
+ match true {
+ #[cfg(FALSE)] true => {},
+ #[cfg_attr(not(FALSE), allow(warnings))] false => {},
+ _ => {}
+ };
+
+ #[print_helper(should_be_removed)]
+ fn removed_fn() {
+ #![cfg(FALSE)]
+ }
+
+ #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() {
+ #![cfg(not(FALSE))]
+ let my_val = true;
+ }
+
+ enum TupleEnum {
+ Foo(
+ #[cfg(FALSE)] u8,
+ #[cfg(FALSE)] bool,
+ #[cfg(not(FALSE))] i32,
+ #[cfg(FALSE)] String, u8
+ )
+ }
+
+ struct TupleStruct(
+ #[cfg(FALSE)] String,
+ #[cfg(not(FALSE))] i32,
+ #[cfg(FALSE)] bool,
+ u8
+ );
+
+ fn plain_removed_fn() {
+ #![cfg_attr(not(FALSE), cfg(FALSE))]
+ }
+
+ 0
+ }],
+ #[print_helper(d)]
+ fourth: B
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr b/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr
new file mode 100644
index 000000000..69d72b55c
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr
@@ -0,0 +1,27 @@
+warning: derive helper attribute is used before it is introduced
+ --> $DIR/issue-75930-derive-cfg.rs:19:3
+ |
+LL | #[print_helper(a)]
+ | ^^^^^^^^^^^^
+...
+LL | #[derive(Print)]
+ | ----- the attribute is introduced here
+ |
+ = note: `#[warn(legacy_derive_helpers)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+
+warning: derive helper attribute is used before it is introduced
+ --> $DIR/issue-75930-derive-cfg.rs:19:3
+ |
+LL | #[print_helper(a)]
+ | ^^^^^^^^^^^^
+...
+LL | #[derive(Print)]
+ | ----- the attribute is introduced here
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
new file mode 100644
index 000000000..c81fa201c
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
@@ -0,0 +1,1904 @@
+PRINT-ATTR INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)]
+struct Foo < #[cfg(FALSE)] A, B >
+{
+ #[cfg(FALSE)] first : String, #[cfg_attr(FALSE, deny(warnings))] second :
+ bool, third :
+ [u8 ;
+ {
+ #[cfg(FALSE)] struct Bar ; #[cfg(not(FALSE))] struct Inner ;
+ #[cfg(FALSE)] let a = 25 ; match true
+ {
+ #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))]
+ false => {}, _ => {}
+ } ; #[print_helper(should_be_removed)] fn removed_fn()
+ { #! [cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn()
+ { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum
+ {
+ Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32,
+ #[cfg(FALSE)] String, u8)
+ } struct
+ TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32,
+ #[cfg(FALSE)] bool, u8) ; fn plain_removed_fn()
+ { #! [cfg_attr(not(FALSE), cfg(FALSE))] } 0
+ }], #[print_helper(d)] fourth : B
+}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_helper",
+ span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:15 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "a",
+ span: $DIR/issue-75930-derive-cfg.rs:19:16: 19:17 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:19:15: 19:18 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:19 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/issue-75930-derive-cfg.rs:21:24: 21:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "dead_code",
+ span: $DIR/issue-75930-derive-cfg.rs:21:30: 21:39 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:21:29: 21:40 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:23:1: 23:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "derive",
+ span: $DIR/issue-75930-derive-cfg.rs:23:3: 23:9 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "Print",
+ span: $DIR/issue-75930-derive-cfg.rs:23:10: 23:15 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:23:9: 23:16 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:23:2: 23:17 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:24:1: 24:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_helper",
+ span: $DIR/issue-75930-derive-cfg.rs:24:3: 24:15 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "b",
+ span: $DIR/issue-75930-derive-cfg.rs:24:16: 24:17 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:18 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:24:2: 24:19 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/issue-75930-derive-cfg.rs:25:1: 25:7 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/issue-75930-derive-cfg.rs:25:8: 25:11 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:12 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:25:12: 25:13 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:25:14: 25:17 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:25:18: 25:23 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:25:17: 25:24 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:25:13: 25:25 (#0),
+ },
+ Ident {
+ ident: "A",
+ span: $DIR/issue-75930-derive-cfg.rs:25:26: 25:27 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:25:27: 25:28 (#0),
+ },
+ Ident {
+ ident: "B",
+ span: $DIR/issue-75930-derive-cfg.rs:25:29: 25:30 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:25:30: 25:31 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:26:5: 26:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:26:7: 26:10 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:26:11: 26:16 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:26:10: 26:17 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:26:6: 26:18 (#0),
+ },
+ Ident {
+ ident: "first",
+ span: $DIR/issue-75930-derive-cfg.rs:26:19: 26:24 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:26:24: 26:25 (#0),
+ },
+ Ident {
+ ident: "String",
+ span: $DIR/issue-75930-derive-cfg.rs:26:26: 26:32 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:26:32: 26:33 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:27:5: 27:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg_attr",
+ span: $DIR/issue-75930-derive-cfg.rs:27:7: 27:15 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:27:16: 27:21 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:27:21: 27:22 (#0),
+ },
+ Ident {
+ ident: "deny",
+ span: $DIR/issue-75930-derive-cfg.rs:27:23: 27:27 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "warnings",
+ span: $DIR/issue-75930-derive-cfg.rs:27:28: 27:36 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:27:27: 27:37 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:27:15: 27:38 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:27:6: 27:39 (#0),
+ },
+ Ident {
+ ident: "second",
+ span: $DIR/issue-75930-derive-cfg.rs:27:40: 27:46 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:27:46: 27:47 (#0),
+ },
+ Ident {
+ ident: "bool",
+ span: $DIR/issue-75930-derive-cfg.rs:27:48: 27:52 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:27:52: 27:53 (#0),
+ },
+ Ident {
+ ident: "third",
+ span: $DIR/issue-75930-derive-cfg.rs:28:5: 28:10 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:28:10: 28:11 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "u8",
+ span: $DIR/issue-75930-derive-cfg.rs:28:13: 28:15 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:16 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:29:9: 29:10 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:29:11: 29:14 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:29:15: 29:20 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:29:14: 29:21 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:29:10: 29:22 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/issue-75930-derive-cfg.rs:29:23: 29:29 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/issue-75930-derive-cfg.rs:29:30: 29:33 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:29:33: 29:34 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:30:9: 30:10 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:30:11: 30:14 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:18 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:30:19: 30:24 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:25 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:30:14: 30:26 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:30:10: 30:27 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/issue-75930-derive-cfg.rs:30:28: 30:34 (#0),
+ },
+ Ident {
+ ident: "Inner",
+ span: $DIR/issue-75930-derive-cfg.rs:30:35: 30:40 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:30:40: 30:41 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:31:9: 31:10 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:31:11: 31:14 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:31:15: 31:20 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:31:14: 31:21 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:31:10: 31:22 (#0),
+ },
+ Ident {
+ ident: "let",
+ span: $DIR/issue-75930-derive-cfg.rs:31:23: 31:26 (#0),
+ },
+ Ident {
+ ident: "a",
+ span: $DIR/issue-75930-derive-cfg.rs:31:27: 31:28 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:31:29: 31:30 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "25",
+ suffix: None,
+ span: $DIR/issue-75930-derive-cfg.rs:31:31: 31:33 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:31:33: 31:34 (#0),
+ },
+ Ident {
+ ident: "match",
+ span: $DIR/issue-75930-derive-cfg.rs:32:9: 32:14 (#0),
+ },
+ Ident {
+ ident: "true",
+ span: $DIR/issue-75930-derive-cfg.rs:32:15: 32:19 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:33:13: 33:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:33:15: 33:18 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:33:19: 33:24 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:33:18: 33:25 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:33:14: 33:26 (#0),
+ },
+ Ident {
+ ident: "true",
+ span: $DIR/issue-75930-derive-cfg.rs:33:27: 33:31 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:33:32: 33:34 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:33:32: 33:34 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/issue-75930-derive-cfg.rs:33:35: 33:37 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:33:37: 33:38 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg_attr",
+ span: $DIR/issue-75930-derive-cfg.rs:34:15: 34:23 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:34:24: 34:27 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:34:28: 34:33 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:34:27: 34:34 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:34:34: 34:35 (#0),
+ },
+ Ident {
+ ident: "allow",
+ span: $DIR/issue-75930-derive-cfg.rs:34:36: 34:41 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "warnings",
+ span: $DIR/issue-75930-derive-cfg.rs:34:42: 34:50 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:34:41: 34:51 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:34:23: 34:52 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:34:14: 34:53 (#0),
+ },
+ Ident {
+ ident: "false",
+ span: $DIR/issue-75930-derive-cfg.rs:34:54: 34:59 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/issue-75930-derive-cfg.rs:34:63: 34:65 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:34:65: 34:66 (#0),
+ },
+ Ident {
+ ident: "_",
+ span: $DIR/issue-75930-derive-cfg.rs:35:13: 35:14 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/issue-75930-derive-cfg.rs:35:18: 35:20 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:32:20: 36:10 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:36:10: 36:11 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:38:9: 38:10 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_helper",
+ span: $DIR/issue-75930-derive-cfg.rs:38:11: 38:23 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "should_be_removed",
+ span: $DIR/issue-75930-derive-cfg.rs:38:24: 38:41 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:38:23: 38:42 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:38:10: 38:43 (#0),
+ },
+ Ident {
+ ident: "fn",
+ span: $DIR/issue-75930-derive-cfg.rs:39:9: 39:11 (#0),
+ },
+ Ident {
+ ident: "removed_fn",
+ span: $DIR/issue-75930-derive-cfg.rs:39:12: 39:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/issue-75930-derive-cfg.rs:39:22: 39:24 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:40:13: 40:14 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:40:14: 40:15 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:40:16: 40:19 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:40:20: 40:25 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:40:19: 40:26 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:40:15: 40:27 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:39:25: 41:10 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:43:9: 43:10 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_helper",
+ span: $DIR/issue-75930-derive-cfg.rs:43:11: 43:23 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "c",
+ span: $DIR/issue-75930-derive-cfg.rs:43:24: 43:25 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:23: 43:26 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:10: 43:27 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:43:28: 43:29 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:43:30: 43:33 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:43:34: 43:37 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:43:38: 43:43 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:37: 43:44 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:33: 43:45 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:29: 43:46 (#0),
+ },
+ Ident {
+ ident: "fn",
+ span: $DIR/issue-75930-derive-cfg.rs:43:47: 43:49 (#0),
+ },
+ Ident {
+ ident: "kept_fn",
+ span: $DIR/issue-75930-derive-cfg.rs:43:50: 43:57 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/issue-75930-derive-cfg.rs:43:57: 43:59 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:44:13: 44:14 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:44:14: 44:15 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:44:16: 44:19 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:44:20: 44:23 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:44:24: 44:29 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:44:23: 44:30 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:44:19: 44:31 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:44:15: 44:32 (#0),
+ },
+ Ident {
+ ident: "let",
+ span: $DIR/issue-75930-derive-cfg.rs:45:13: 45:16 (#0),
+ },
+ Ident {
+ ident: "my_val",
+ span: $DIR/issue-75930-derive-cfg.rs:45:17: 45:23 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:45:24: 45:25 (#0),
+ },
+ Ident {
+ ident: "true",
+ span: $DIR/issue-75930-derive-cfg.rs:45:26: 45:30 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:45:30: 45:31 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:60: 46:10 (#0),
+ },
+ Ident {
+ ident: "enum",
+ span: $DIR/issue-75930-derive-cfg.rs:48:9: 48:13 (#0),
+ },
+ Ident {
+ ident: "TupleEnum",
+ span: $DIR/issue-75930-derive-cfg.rs:48:14: 48:23 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Foo",
+ span: $DIR/issue-75930-derive-cfg.rs:49:13: 49:16 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:50:17: 50:18 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:50:19: 50:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:50:23: 50:28 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:50:22: 50:29 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:50:18: 50:30 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/issue-75930-derive-cfg.rs:50:31: 50:33 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:50:33: 50:34 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:51:17: 51:18 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:51:19: 51:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:51:23: 51:28 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:51:22: 51:29 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:51:18: 51:30 (#0),
+ },
+ Ident {
+ ident: "bool",
+ span: $DIR/issue-75930-derive-cfg.rs:51:31: 51:35 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:51:35: 51:36 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:52:17: 52:18 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:52:19: 52:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:52:23: 52:26 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:52:27: 52:32 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:52:26: 52:33 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:52:22: 52:34 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:52:18: 52:35 (#0),
+ },
+ Ident {
+ ident: "i32",
+ span: $DIR/issue-75930-derive-cfg.rs:52:36: 52:39 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:52:39: 52:40 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:53:17: 53:18 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:53:19: 53:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:53:23: 53:28 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:53:22: 53:29 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:53:18: 53:30 (#0),
+ },
+ Ident {
+ ident: "String",
+ span: $DIR/issue-75930-derive-cfg.rs:53:31: 53:37 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:53:37: 53:38 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/issue-75930-derive-cfg.rs:53:39: 53:41 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:49:16: 54:14 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:48:24: 55:10 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/issue-75930-derive-cfg.rs:57:9: 57:15 (#0),
+ },
+ Ident {
+ ident: "TupleStruct",
+ span: $DIR/issue-75930-derive-cfg.rs:57:16: 57:27 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:58:13: 58:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:58:15: 58:18 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:58:19: 58:24 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:58:18: 58:25 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:58:14: 58:26 (#0),
+ },
+ Ident {
+ ident: "String",
+ span: $DIR/issue-75930-derive-cfg.rs:58:27: 58:33 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:58:33: 58:34 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:59:13: 59:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:59:15: 59:18 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:59:19: 59:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:59:23: 59:28 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:59:22: 59:29 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:59:18: 59:30 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:59:14: 59:31 (#0),
+ },
+ Ident {
+ ident: "i32",
+ span: $DIR/issue-75930-derive-cfg.rs:59:32: 59:35 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:59:35: 59:36 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:60:13: 60:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:60:15: 60:18 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:60:19: 60:24 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:60:18: 60:25 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:60:14: 60:26 (#0),
+ },
+ Ident {
+ ident: "bool",
+ span: $DIR/issue-75930-derive-cfg.rs:60:27: 60:31 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:60:31: 60:32 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/issue-75930-derive-cfg.rs:61:13: 61:15 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:57:27: 62:10 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:62:10: 62:11 (#0),
+ },
+ Ident {
+ ident: "fn",
+ span: $DIR/issue-75930-derive-cfg.rs:64:9: 64:11 (#0),
+ },
+ Ident {
+ ident: "plain_removed_fn",
+ span: $DIR/issue-75930-derive-cfg.rs:64:12: 64:28 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/issue-75930-derive-cfg.rs:64:28: 64:30 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:65:13: 65:14 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:65:14: 65:15 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg_attr",
+ span: $DIR/issue-75930-derive-cfg.rs:65:16: 65:24 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:65:25: 65:28 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:65:29: 65:34 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:65:28: 65:35 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:65:35: 65:36 (#0),
+ },
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:65:37: 65:40 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:65:41: 65:46 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:65:40: 65:47 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:65:24: 65:48 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:65:15: 65:49 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:64:31: 66:10 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/issue-75930-derive-cfg.rs:68:9: 68:10 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:28:17: 69:6 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:28:12: 69:7 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:69:7: 69:8 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:70:5: 70:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_helper",
+ span: $DIR/issue-75930-derive-cfg.rs:70:7: 70:19 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "d",
+ span: $DIR/issue-75930-derive-cfg.rs:70:20: 70:21 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:70:19: 70:22 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:70:6: 70:23 (#0),
+ },
+ Ident {
+ ident: "fourth",
+ span: $DIR/issue-75930-derive-cfg.rs:71:5: 71:11 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:71:11: 71:12 (#0),
+ },
+ Ident {
+ ident: "B",
+ span: $DIR/issue-75930-derive-cfg.rs:71:13: 71:14 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:25:32: 72:2 (#0),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_helper(b)] struct Foo < B >
+{
+ second : bool, third :
+ [u8 ;
+ {
+ #[cfg(not(FALSE))] struct Inner ; match true
+ { #[allow(warnings)] false => {}, _ => {} } ; #[print_helper(c)]
+ #[cfg(not(FALSE))] fn kept_fn()
+ { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum
+ { Foo(#[cfg(not(FALSE))] i32, u8) } struct
+ TupleStruct(#[cfg(not(FALSE))] i32, u8) ; 0
+ }], #[print_helper(d)] fourth : B
+}
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:19:1: 19:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_helper",
+ span: $DIR/issue-75930-derive-cfg.rs:19:3: 19:15 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "a",
+ span: $DIR/issue-75930-derive-cfg.rs:19:16: 19:17 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:19:15: 19:18 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:19:2: 19:19 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/issue-75930-derive-cfg.rs:21:24: 21:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "dead_code",
+ span: $DIR/issue-75930-derive-cfg.rs:21:30: 21:39 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:21:29: 21:40 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:21:1: 21:2 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:24:1: 24:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_helper",
+ span: $DIR/issue-75930-derive-cfg.rs:24:3: 24:15 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "b",
+ span: $DIR/issue-75930-derive-cfg.rs:24:16: 24:17 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:24:15: 24:18 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:24:2: 24:19 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/issue-75930-derive-cfg.rs:25:1: 25:7 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/issue-75930-derive-cfg.rs:25:8: 25:11 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:25:11: 25:12 (#0),
+ },
+ Ident {
+ ident: "B",
+ span: $DIR/issue-75930-derive-cfg.rs:25:29: 25:30 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:25:30: 25:31 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "second",
+ span: $DIR/issue-75930-derive-cfg.rs:27:40: 27:46 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:27:46: 27:47 (#0),
+ },
+ Ident {
+ ident: "bool",
+ span: $DIR/issue-75930-derive-cfg.rs:27:48: 27:52 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:27:52: 27:53 (#0),
+ },
+ Ident {
+ ident: "third",
+ span: $DIR/issue-75930-derive-cfg.rs:28:5: 28:10 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:28:10: 28:11 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "u8",
+ span: $DIR/issue-75930-derive-cfg.rs:28:13: 28:15 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:28:15: 28:16 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:30:9: 30:10 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:30:11: 30:14 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:30:15: 30:18 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:30:19: 30:24 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:30:18: 30:25 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:30:14: 30:26 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:30:10: 30:27 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/issue-75930-derive-cfg.rs:30:28: 30:34 (#0),
+ },
+ Ident {
+ ident: "Inner",
+ span: $DIR/issue-75930-derive-cfg.rs:30:35: 30:40 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:30:40: 30:41 (#0),
+ },
+ Ident {
+ ident: "match",
+ span: $DIR/issue-75930-derive-cfg.rs:32:9: 32:14 (#0),
+ },
+ Ident {
+ ident: "true",
+ span: $DIR/issue-75930-derive-cfg.rs:32:15: 32:19 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/issue-75930-derive-cfg.rs:34:36: 34:41 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "warnings",
+ span: $DIR/issue-75930-derive-cfg.rs:34:42: 34:50 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:34:41: 34:51 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:34:13: 34:14 (#0),
+ },
+ Ident {
+ ident: "false",
+ span: $DIR/issue-75930-derive-cfg.rs:34:54: 34:59 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/issue-75930-derive-cfg.rs:34:63: 34:65 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:34:65: 34:66 (#0),
+ },
+ Ident {
+ ident: "_",
+ span: $DIR/issue-75930-derive-cfg.rs:35:13: 35:14 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/issue-75930-derive-cfg.rs:35:18: 35:20 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:32:20: 36:10 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:36:10: 36:11 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:43:9: 43:10 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_helper",
+ span: $DIR/issue-75930-derive-cfg.rs:43:11: 43:23 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "c",
+ span: $DIR/issue-75930-derive-cfg.rs:43:24: 43:25 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:23: 43:26 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:10: 43:27 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:43:28: 43:29 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:43:30: 43:33 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:43:34: 43:37 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:43:38: 43:43 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:37: 43:44 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:33: 43:45 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:29: 43:46 (#0),
+ },
+ Ident {
+ ident: "fn",
+ span: $DIR/issue-75930-derive-cfg.rs:43:47: 43:49 (#0),
+ },
+ Ident {
+ ident: "kept_fn",
+ span: $DIR/issue-75930-derive-cfg.rs:43:50: 43:57 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/issue-75930-derive-cfg.rs:43:57: 43:59 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/issue-75930-derive-cfg.rs:44:13: 44:14 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:44:14: 44:15 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:44:16: 44:19 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:44:20: 44:23 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:44:24: 44:29 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:44:23: 44:30 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:44:19: 44:31 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:44:15: 44:32 (#0),
+ },
+ Ident {
+ ident: "let",
+ span: $DIR/issue-75930-derive-cfg.rs:45:13: 45:16 (#0),
+ },
+ Ident {
+ ident: "my_val",
+ span: $DIR/issue-75930-derive-cfg.rs:45:17: 45:23 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:45:24: 45:25 (#0),
+ },
+ Ident {
+ ident: "true",
+ span: $DIR/issue-75930-derive-cfg.rs:45:26: 45:30 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:45:30: 45:31 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:43:60: 46:10 (#0),
+ },
+ Ident {
+ ident: "enum",
+ span: $DIR/issue-75930-derive-cfg.rs:48:9: 48:13 (#0),
+ },
+ Ident {
+ ident: "TupleEnum",
+ span: $DIR/issue-75930-derive-cfg.rs:48:14: 48:23 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Foo",
+ span: $DIR/issue-75930-derive-cfg.rs:49:13: 49:16 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:52:17: 52:18 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:52:19: 52:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:52:23: 52:26 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:52:27: 52:32 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:52:26: 52:33 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:52:22: 52:34 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:52:18: 52:35 (#0),
+ },
+ Ident {
+ ident: "i32",
+ span: $DIR/issue-75930-derive-cfg.rs:52:36: 52:39 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:52:39: 52:40 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/issue-75930-derive-cfg.rs:53:39: 53:41 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:49:16: 54:14 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:48:24: 55:10 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/issue-75930-derive-cfg.rs:57:9: 57:15 (#0),
+ },
+ Ident {
+ ident: "TupleStruct",
+ span: $DIR/issue-75930-derive-cfg.rs:57:16: 57:27 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:59:13: 59:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/issue-75930-derive-cfg.rs:59:15: 59:18 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "not",
+ span: $DIR/issue-75930-derive-cfg.rs:59:19: 59:22 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/issue-75930-derive-cfg.rs:59:23: 59:28 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:59:22: 59:29 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:59:18: 59:30 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:59:14: 59:31 (#0),
+ },
+ Ident {
+ ident: "i32",
+ span: $DIR/issue-75930-derive-cfg.rs:59:32: 59:35 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:59:35: 59:36 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/issue-75930-derive-cfg.rs:61:13: 61:15 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:57:27: 62:10 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:62:10: 62:11 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/issue-75930-derive-cfg.rs:68:9: 68:10 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:28:17: 69:6 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:28:12: 69:7 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:69:7: 69:8 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:70:5: 70:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_helper",
+ span: $DIR/issue-75930-derive-cfg.rs:70:7: 70:19 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "d",
+ span: $DIR/issue-75930-derive-cfg.rs:70:20: 70:21 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:70:19: 70:22 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:70:6: 70:23 (#0),
+ },
+ Ident {
+ ident: "fourth",
+ span: $DIR/issue-75930-derive-cfg.rs:71:5: 71:11 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/issue-75930-derive-cfg.rs:71:11: 71:12 (#0),
+ },
+ Ident {
+ ident: "B",
+ span: $DIR/issue-75930-derive-cfg.rs:71:13: 71:14 (#0),
+ },
+ ],
+ span: $DIR/issue-75930-derive-cfg.rs:25:32: 72:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs
new file mode 100644
index 000000000..7d31de1d2
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs
@@ -0,0 +1,16 @@
+// check-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+//
+// Regression test for issue #76182
+// Tests that we properly handle patterns with a leading vert
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate test_macros;
+
+#[test_macros::print_attr]
+fn main() {
+ match () { | () => () }
+}
diff --git a/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout
new file mode 100644
index 000000000..5493f9c7b
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout
@@ -0,0 +1,62 @@
+PRINT-ATTR INPUT (DISPLAY): fn main() { match() { | () => () } }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fn",
+ span: $DIR/issue-76182-leading-vert-pat.rs:14:1: 14:3 (#0),
+ },
+ Ident {
+ ident: "main",
+ span: $DIR/issue-76182-leading-vert-pat.rs:14:4: 14:8 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/issue-76182-leading-vert-pat.rs:14:8: 14:10 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "match",
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:5: 15:10 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:11: 15:13 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '|',
+ spacing: Alone,
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:16: 15:17 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:18: 15:20 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Joint,
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:24: 15:26 (#0),
+ },
+ ],
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:14: 15:28 (#0),
+ },
+ ],
+ span: $DIR/issue-76182-leading-vert-pat.rs:14:11: 16:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs
new file mode 100644
index 000000000..98fa06b6e
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.rs
@@ -0,0 +1,12 @@
+// aux-build:proc-macro-panic.rs
+// edition:2018
+
+// Regression test for issue #76270
+// Tests that we don't print an ICE message when a panic
+// occurs in libproc-macro (when `-Z proc-macro-backtrace` is not specified)
+
+extern crate proc_macro_panic;
+
+proc_macro_panic::panic_in_libproc_macro!(); //~ ERROR proc macro panicked
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr
new file mode 100644
index 000000000..1dc0f16bf
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-76270-panic-in-libproc-macro.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+ --> $DIR/issue-76270-panic-in-libproc-macro.rs:10:1
+ |
+LL | proc_macro_panic::panic_in_libproc_macro!();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: message: `""` is not a valid identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.rs b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.rs
new file mode 100644
index 000000000..478809324
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.rs
@@ -0,0 +1,32 @@
+// check-pass
+// edition:2018
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use] extern crate test_macros;
+
+macro_rules! foo {(
+ #[fake_attr]
+ $item:item
+) => (
+ $item
+)}
+
+macro_rules! outer {($item:item) => (
+ print_bang! { // Identity proc-macro
+ foo! {
+ #[fake_attr]
+ $item
+ }
+ }
+)}
+outer! {
+ mod bar {
+ //! Foo
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
new file mode 100644
index 000000000..60a400a5d
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
@@ -0,0 +1,87 @@
+PRINT-BANG INPUT (DISPLAY): foo! { #[fake_attr] mod bar {
+ #![doc = r" Foo"]
+} }
+PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): foo! { #[fake_attr] mod bar { #! [doc = r" Foo"] } }
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "foo",
+ span: $DIR/issue-78675-captured-inner-attrs.rs:20:9: 20:12 (#4),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/issue-78675-captured-inner-attrs.rs:20:12: 20:13 (#4),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-78675-captured-inner-attrs.rs:21:13: 21:14 (#4),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "fake_attr",
+ span: $DIR/issue-78675-captured-inner-attrs.rs:21:15: 21:24 (#4),
+ },
+ ],
+ span: $DIR/issue-78675-captured-inner-attrs.rs:21:14: 21:25 (#4),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "mod",
+ span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 27:8 (#0),
+ },
+ Ident {
+ ident: "bar",
+ span: $DIR/issue-78675-captured-inner-attrs.rs:27:9: 27:12 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "doc",
+ span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0),
+ },
+ Literal {
+ kind: StrRaw(0),
+ symbol: " Foo",
+ suffix: None,
+ span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0),
+ },
+ ],
+ span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0),
+ },
+ ],
+ span: $DIR/issue-78675-captured-inner-attrs.rs:27:13: 29:6 (#0),
+ },
+ ],
+ span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+ },
+ ],
+ span: $DIR/issue-78675-captured-inner-attrs.rs:20:14: 23:10 (#4),
+ },
+]
diff --git a/src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs b/src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs
new file mode 100644
index 000000000..b68f19c5d
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-79242-slow-retokenize-check.rs
@@ -0,0 +1,34 @@
+// check-pass
+// aux-build:issue-79242.rs
+
+// Regression test for issue #79242
+// Tests that compilation time doesn't blow up for a proc-macro
+// invocation with deeply nested nonterminals
+
+#![allow(unused)]
+
+extern crate issue_79242;
+
+macro_rules! declare_nats {
+ ($prev:ty) => {};
+ ($prev:ty, $n:literal$(, $tail:literal)*) => {
+
+ issue_79242::dummy! {
+ $prev
+ }
+
+ declare_nats!(Option<$prev>$(, $tail)*);
+ };
+ (0, $($n:literal),+) => {
+ pub struct N0;
+ declare_nats!(N0, $($n),+);
+ };
+}
+
+declare_nats! {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
+}
+
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-79825.rs b/src/test/ui/proc-macro/issue-79825.rs
new file mode 100644
index 000000000..f628469ce
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-79825.rs
@@ -0,0 +1,10 @@
+// check-pass
+// aux-build:issue-79825.rs
+#![feature(trait_alias)]
+
+extern crate issue_79825;
+
+#[issue_79825::assert_input]
+trait Alias = Sized;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.rs b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs
new file mode 100644
index 000000000..86865af0b
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs
@@ -0,0 +1,26 @@
+// check-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! empty_stmt {
+ ($s:stmt) => {
+ print_bang!($s);
+
+ // Currently, all attributes are ignored
+ // on an empty statement
+ #[print_attr]
+ #[rustc_dummy(first)]
+ #[rustc_dummy(second)]
+ $s
+ }
+}
+
+fn main() {
+ empty_stmt!(;);
+}
diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout
new file mode 100644
index 000000000..4b7ed8743
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout
@@ -0,0 +1,14 @@
+PRINT-BANG INPUT (DISPLAY): ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/issue-80760-empty-stmt.rs:25:17: 25:18 (#0),
+ },
+ ],
+ span: $DIR/issue-80760-empty-stmt.rs:13:21: 13:23 (#4),
+ },
+]
diff --git a/src/test/ui/proc-macro/issue-81007-item-attrs.rs b/src/test/ui/proc-macro/issue-81007-item-attrs.rs
new file mode 100644
index 000000000..ea27d54ee
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-81007-item-attrs.rs
@@ -0,0 +1,31 @@
+// check-pass
+// edition:2018
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+
+#![feature(rustc_attrs)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use] extern crate test_macros;
+
+macro_rules! capture_item {
+ ($item:item) => {
+ #[print_attr]
+ $item
+ }
+}
+
+capture_item! {
+ /// A doc comment
+ struct Foo {}
+}
+
+capture_item! {
+ #[rustc_dummy]
+ /// Another comment comment
+ struct Bar {}
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-81007-item-attrs.stdout b/src/test/ui/proc-macro/issue-81007-item-attrs.stdout
new file mode 100644
index 000000000..3c001e995
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-81007-item-attrs.stdout
@@ -0,0 +1,99 @@
+PRINT-ATTR INPUT (DISPLAY): #[doc = r" A doc comment"] struct Foo {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "doc",
+ span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
+ },
+ Literal {
+ kind: StrRaw(0),
+ symbol: " A doc comment",
+ suffix: None,
+ span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
+ },
+ ],
+ span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/issue-81007-item-attrs.rs:22:5: 22:11 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/issue-81007-item-attrs.rs:22:12: 22:15 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/issue-81007-item-attrs.rs:22:16: 22:18 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[doc = r" Another comment comment"] struct Bar {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-81007-item-attrs.rs:26:5: 26:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/issue-81007-item-attrs.rs:26:7: 26:18 (#0),
+ },
+ ],
+ span: $DIR/issue-81007-item-attrs.rs:26:6: 26:19 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "doc",
+ span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
+ },
+ Literal {
+ kind: StrRaw(0),
+ symbol: " Another comment comment",
+ suffix: None,
+ span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
+ },
+ ],
+ span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/issue-81007-item-attrs.rs:28:5: 28:11 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/issue-81007-item-attrs.rs:28:12: 28:15 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/issue-81007-item-attrs.rs:28:16: 28:18 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/issue-81543-item-parse-err.rs b/src/test/ui/proc-macro/issue-81543-item-parse-err.rs
new file mode 100644
index 000000000..027389556
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-81543-item-parse-err.rs
@@ -0,0 +1,14 @@
+// aux-build:test-macros.rs
+
+// Regression test for issue #81543
+// Tests that we emit a properly spanned error
+// when the output of a proc-macro cannot be parsed
+// as the expected AST node kind
+
+extern crate test_macros;
+
+test_macros::identity! {
+ fn 32() {} //~ ERROR expected identifier
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-81543-item-parse-err.stderr b/src/test/ui/proc-macro/issue-81543-item-parse-err.stderr
new file mode 100644
index 000000000..ca5241760
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-81543-item-parse-err.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `32`
+ --> $DIR/issue-81543-item-parse-err.rs:11:8
+ |
+LL | fn 32() {}
+ | ^^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/issue-81555.rs b/src/test/ui/proc-macro/issue-81555.rs
new file mode 100644
index 000000000..693f1f7dc
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-81555.rs
@@ -0,0 +1,15 @@
+// check-pass
+// aux-build:test-macros.rs
+#![feature(stmt_expr_attributes, proc_macro_hygiene)]
+
+extern crate test_macros;
+
+use test_macros::identity_attr;
+
+#[identity_attr]
+fn main() {
+ let _x;
+ let y = ();
+ #[identity_attr]
+ _x = y;
+}
diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs
new file mode 100644
index 000000000..25adc5d25
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.rs
@@ -0,0 +1,10 @@
+// Regression test for issue #83469
+// Ensures that we recover from `#[global_alloc]` on an invalid
+// stmt without an ICE
+
+fn outer() {
+ #[global_allocator]
+ fn inner() {} //~ ERROR allocators must be statics
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr
new file mode 100644
index 000000000..ec0e3c4c7
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-83469-global-alloc-invalid-stmt.stderr
@@ -0,0 +1,8 @@
+error: allocators must be statics
+ --> $DIR/issue-83469-global-alloc-invalid-stmt.rs:7:5
+ |
+LL | fn inner() {}
+ | ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/issue-83510.rs b/src/test/ui/proc-macro/issue-83510.rs
new file mode 100644
index 000000000..2b1aec4df
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-83510.rs
@@ -0,0 +1,11 @@
+// aux-build: issue-83510.rs
+
+extern crate issue_83510;
+
+issue_83510::dance_like_you_want_to_ice!();
+//~^ ERROR: cannot find type `Foo` in this scope
+//~| ERROR: expected trait, found struct `Box`
+//~| ERROR: cannot find trait `Baz` in this scope
+//~| ERROR: inherent associated types are unstable
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-83510.stderr b/src/test/ui/proc-macro/issue-83510.stderr
new file mode 100644
index 000000000..e0628a317
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-83510.stderr
@@ -0,0 +1,38 @@
+error[E0412]: cannot find type `Foo` in this scope
+ --> $DIR/issue-83510.rs:5:1
+ |
+LL | issue_83510::dance_like_you_want_to_ice!();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+ |
+ = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0404]: expected trait, found struct `Box`
+ --> $DIR/issue-83510.rs:5:1
+ |
+LL | issue_83510::dance_like_you_want_to_ice!();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait
+ |
+ = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0405]: cannot find trait `Baz` in this scope
+ --> $DIR/issue-83510.rs:5:1
+ |
+LL | issue_83510::dance_like_you_want_to_ice!();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+ |
+ = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0658]: inherent associated types are unstable
+ --> $DIR/issue-83510.rs:5:1
+ |
+LL | issue_83510::dance_like_you_want_to_ice!();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
+ = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
+ = note: this error originates in the macro `issue_83510::dance_like_you_want_to_ice` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0404, E0405, E0412, E0658.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed
new file mode 100644
index 000000000..426a5fa72
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed
@@ -0,0 +1,12 @@
+// aux-build:test-macros.rs
+// run-rustfix
+
+#[macro_use]
+extern crate test_macros;
+
+/// Inner doc comment
+//~^ ERROR expected outer doc comment
+#[derive(Empty)]
+pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs
new file mode 100644
index 000000000..31e3f3c85
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs
@@ -0,0 +1,12 @@
+// aux-build:test-macros.rs
+// run-rustfix
+
+#[macro_use]
+extern crate test_macros;
+
+//! Inner doc comment
+//~^ ERROR expected outer doc comment
+#[derive(Empty)]
+pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr
new file mode 100644
index 000000000..a92f07522
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr
@@ -0,0 +1,17 @@
+error[E0753]: expected outer doc comment
+ --> $DIR/issue-86781-bad-inner-doc.rs:7:1
+ |
+LL | //! Inner doc comment
+ | ^^^^^^^^^^^^^^^^^^^^^
+...
+LL | pub struct Foo;
+ | --------------- the inner doc comment doesn't annotate this struct
+ |
+help: to annotate the struct, change the doc comment from inner to outer style
+ |
+LL | /// Inner doc comment
+ | ~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0753`.
diff --git a/src/test/ui/proc-macro/issue-91800.rs b/src/test/ui/proc-macro/issue-91800.rs
new file mode 100644
index 000000000..0c1281de4
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-91800.rs
@@ -0,0 +1,16 @@
+// aux-build: issue-91800-macro.rs
+
+#[macro_use]
+extern crate issue_91800_macro;
+
+#[derive(MyTrait)]
+//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
+//~| ERROR proc-macro derive produced unparseable tokens
+#[attribute_macro]
+//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
+struct MyStruct;
+
+fn_macro! {}
+//~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/issue-91800.stderr b/src/test/ui/proc-macro/issue-91800.stderr
new file mode 100644
index 000000000..9c356263a
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-91800.stderr
@@ -0,0 +1,56 @@
+error: macros that expand to items must be delimited with braces or followed by a semicolon
+ --> $DIR/issue-91800.rs:6:10
+ |
+LL | #[derive(MyTrait)]
+ | ^^^^^^^
+ |
+ = note: this error originates in the derive macro `MyTrait` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: proc-macro derive produced unparseable tokens
+ --> $DIR/issue-91800.rs:6:10
+ |
+LL | #[derive(MyTrait)]
+ | ^^^^^^^
+
+error:
+ --> $DIR/issue-91800.rs:6:10
+ |
+LL | #[derive(MyTrait)]
+ | ^^^^^^^
+ |
+ = note: this error originates in the derive macro `MyTrait` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: macros that expand to items must be delimited with braces or followed by a semicolon
+ --> $DIR/issue-91800.rs:9:1
+ |
+LL | #[attribute_macro]
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error:
+ --> $DIR/issue-91800.rs:9:1
+ |
+LL | #[attribute_macro]
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: macros that expand to items must be delimited with braces or followed by a semicolon
+ --> $DIR/issue-91800.rs:13:1
+ |
+LL | fn_macro! {}
+ | ^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `fn_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error:
+ --> $DIR/issue-91800.rs:13:1
+ |
+LL | fn_macro! {}
+ | ^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `fn_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/proc-macro/item-error.rs b/src/test/ui/proc-macro/item-error.rs
new file mode 100644
index 000000000..64c203e54
--- /dev/null
+++ b/src/test/ui/proc-macro/item-error.rs
@@ -0,0 +1,15 @@
+// aux-build:derive-b.rs
+
+#![allow(warnings)]
+
+#[macro_use]
+extern crate derive_b;
+
+#[derive(B)]
+struct A {
+ a: &u64
+//~^ ERROR: missing lifetime specifier
+}
+
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/item-error.stderr b/src/test/ui/proc-macro/item-error.stderr
new file mode 100644
index 000000000..b544be6e9
--- /dev/null
+++ b/src/test/ui/proc-macro/item-error.stderr
@@ -0,0 +1,15 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/item-error.rs:10:8
+ |
+LL | a: &u64
+ | ^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL ~ struct A<'a> {
+LL ~ a: &'a u64
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/proc-macro/keep-expr-tokens.rs b/src/test/ui/proc-macro/keep-expr-tokens.rs
new file mode 100644
index 000000000..0bf889a85
--- /dev/null
+++ b/src/test/ui/proc-macro/keep-expr-tokens.rs
@@ -0,0 +1,24 @@
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![feature(stmt_expr_attributes)]
+#![feature(proc_macro_hygiene)]
+#![feature(rustc_attrs)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate test_macros;
+
+use test_macros::recollect_attr;
+
+fn main() {
+ #[test_macros::recollect_attr]
+ for item in missing_fn() {} //~ ERROR cannot find
+
+ (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad))); //~ ERROR cannot
+
+ #[test_macros::print_attr]
+ #[rustc_dummy]
+ { 1 +1; } // Don't change the weird spacing of the '+'
+}
diff --git a/src/test/ui/proc-macro/keep-expr-tokens.stderr b/src/test/ui/proc-macro/keep-expr-tokens.stderr
new file mode 100644
index 000000000..11052d11c
--- /dev/null
+++ b/src/test/ui/proc-macro/keep-expr-tokens.stderr
@@ -0,0 +1,15 @@
+error[E0425]: cannot find function `missing_fn` in this scope
+ --> $DIR/keep-expr-tokens.rs:17:17
+ |
+LL | for item in missing_fn() {}
+ | ^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `bad` in this scope
+ --> $DIR/keep-expr-tokens.rs:19:62
+ |
+LL | (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad)));
+ | ^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/keep-expr-tokens.stdout b/src/test/ui/proc-macro/keep-expr-tokens.stdout
new file mode 100644
index 000000000..fcd72a0e0
--- /dev/null
+++ b/src/test/ui/proc-macro/keep-expr-tokens.stdout
@@ -0,0 +1,46 @@
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] { 1 + 1 ; }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/keep-expr-tokens.rs:22:5: 22:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/keep-expr-tokens.rs:22:7: 22:18 (#0),
+ },
+ ],
+ span: $DIR/keep-expr-tokens.rs:22:6: 22:19 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/keep-expr-tokens.rs:23:7: 23:8 (#0),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/keep-expr-tokens.rs:23:9: 23:10 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/keep-expr-tokens.rs:23:10: 23:11 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/keep-expr-tokens.rs:23:11: 23:12 (#0),
+ },
+ ],
+ span: $DIR/keep-expr-tokens.rs:23:5: 23:14 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/lifetimes-rpass.rs b/src/test/ui/proc-macro/lifetimes-rpass.rs
new file mode 100644
index 000000000..a1d33ddca
--- /dev/null
+++ b/src/test/ui/proc-macro/lifetimes-rpass.rs
@@ -0,0 +1,26 @@
+// run-pass
+
+#![allow(unused_variables)]
+// aux-build:lifetimes-rpass.rs
+
+extern crate lifetimes_rpass as lifetimes;
+use lifetimes::*;
+
+lifetimes_bang! {
+ fn bang<'a>() -> &'a u8 { &0 }
+}
+
+#[lifetimes_attr]
+fn attr<'a>() -> &'a u8 { &1 }
+
+#[derive(Lifetimes)]
+pub struct Lifetimes<'a> {
+ pub field: &'a u8,
+}
+
+fn main() {
+ assert_eq!(bang::<'static>(), &0);
+ assert_eq!(attr::<'static>(), &1);
+ let l1 = Lifetimes { field: &0 };
+ let l2 = m::Lifetimes { field: &1 };
+}
diff --git a/src/test/ui/proc-macro/lifetimes.rs b/src/test/ui/proc-macro/lifetimes.rs
new file mode 100644
index 000000000..560569671
--- /dev/null
+++ b/src/test/ui/proc-macro/lifetimes.rs
@@ -0,0 +1,9 @@
+// aux-build:lifetimes.rs
+
+extern crate lifetimes;
+
+use lifetimes::*;
+
+type A = single_quote_alone!(); //~ ERROR expected type, found `'`
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/lifetimes.stderr b/src/test/ui/proc-macro/lifetimes.stderr
new file mode 100644
index 000000000..0c99809ed
--- /dev/null
+++ b/src/test/ui/proc-macro/lifetimes.stderr
@@ -0,0 +1,13 @@
+error: expected type, found `'`
+ --> $DIR/lifetimes.rs:7:10
+ |
+LL | type A = single_quote_alone!();
+ | ^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | expected type
+ | this macro call doesn't expand to a type
+ |
+ = note: this error originates in the macro `single_quote_alone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.rs b/src/test/ui/proc-macro/lints_in_proc_macros.rs
new file mode 100644
index 000000000..377a1f25b
--- /dev/null
+++ b/src/test/ui/proc-macro/lints_in_proc_macros.rs
@@ -0,0 +1,14 @@
+// aux-build:bang_proc_macro2.rs
+
+extern crate bang_proc_macro2;
+
+use bang_proc_macro2::bang_proc_macro2;
+
+fn main() {
+ let foobar = 42;
+ bang_proc_macro2!();
+ //~^ ERROR cannot find value `foobar2` in this scope
+ //~| HELP a local variable with a similar name exists
+ //~| SUGGESTION foobar
+ println!("{}", x);
+}
diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.stderr b/src/test/ui/proc-macro/lints_in_proc_macros.stderr
new file mode 100644
index 000000000..4dd8be7d9
--- /dev/null
+++ b/src/test/ui/proc-macro/lints_in_proc_macros.stderr
@@ -0,0 +1,11 @@
+error[E0425]: cannot find value `foobar2` in this scope
+ --> $DIR/lints_in_proc_macros.rs:9:5
+ |
+LL | bang_proc_macro2!();
+ | ^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar`
+ |
+ = note: this error originates in the macro `bang_proc_macro2` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/load-panic-backtrace.rs b/src/test/ui/proc-macro/load-panic-backtrace.rs
new file mode 100644
index 000000000..cd6f70a55
--- /dev/null
+++ b/src/test/ui/proc-macro/load-panic-backtrace.rs
@@ -0,0 +1,14 @@
+// aux-build:test-macros.rs
+// compile-flags: -Z proc-macro-backtrace
+// rustc-env:RUST_BACKTRACE=0
+// normalize-stderr-test "thread '.*' panicked " -> ""
+// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Panic)]
+//~^ ERROR: proc-macro derive panicked
+struct Foo;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/load-panic-backtrace.stderr b/src/test/ui/proc-macro/load-panic-backtrace.stderr
new file mode 100644
index 000000000..cef5786d1
--- /dev/null
+++ b/src/test/ui/proc-macro/load-panic-backtrace.stderr
@@ -0,0 +1,11 @@
+at 'panic-derive', $DIR/auxiliary/test-macros.rs:43:5
+error: proc-macro derive panicked
+ --> $DIR/load-panic-backtrace.rs:10:10
+ |
+LL | #[derive(Panic)]
+ | ^^^^^
+ |
+ = help: message: panic-derive
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/load-panic.rs b/src/test/ui/proc-macro/load-panic.rs
new file mode 100644
index 000000000..2e9a311d8
--- /dev/null
+++ b/src/test/ui/proc-macro/load-panic.rs
@@ -0,0 +1,10 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Panic)]
+//~^ ERROR: proc-macro derive panicked
+struct Foo;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/load-panic.stderr b/src/test/ui/proc-macro/load-panic.stderr
new file mode 100644
index 000000000..40cc4ee0e
--- /dev/null
+++ b/src/test/ui/proc-macro/load-panic.stderr
@@ -0,0 +1,10 @@
+error: proc-macro derive panicked
+ --> $DIR/load-panic.rs:6:10
+ |
+LL | #[derive(Panic)]
+ | ^^^^^
+ |
+ = help: message: panic-derive
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/load-two.rs b/src/test/ui/proc-macro/load-two.rs
new file mode 100644
index 000000000..5ce0e6545
--- /dev/null
+++ b/src/test/ui/proc-macro/load-two.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+#![allow(path_statements)]
+#![allow(dead_code)]
+// aux-build:derive-atob.rs
+// aux-build:derive-ctod.rs
+
+#[macro_use]
+extern crate derive_atob;
+#[macro_use]
+extern crate derive_ctod;
+
+#[derive(Copy, Clone)]
+#[derive(AToB)]
+struct A;
+
+#[derive(CToD)]
+struct C;
+
+fn main() {
+ B;
+ D;
+}
diff --git a/src/test/ui/proc-macro/macro-brackets.rs b/src/test/ui/proc-macro/macro-brackets.rs
new file mode 100644
index 000000000..aa0046f45
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-brackets.rs
@@ -0,0 +1,14 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! id {
+ ($($t:tt)*) => ($($t)*)
+}
+
+#[identity_attr]
+id![static X: u32 = 'a';]; //~ ERROR: mismatched types
+
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/macro-brackets.stderr b/src/test/ui/proc-macro/macro-brackets.stderr
new file mode 100644
index 000000000..d35163752
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-brackets.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/macro-brackets.rs:11:21
+ |
+LL | id![static X: u32 = 'a';];
+ | ^^^ expected `u32`, found `char`
+ |
+help: you can cast a `char` to a `u32`, since a `char` always occupies 4 bytes
+ |
+LL | id![static X: u32 = 'a' as u32;];
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/macro-crate-multi-decorator.rs b/src/test/ui/proc-macro/macro-crate-multi-decorator.rs
new file mode 100644
index 000000000..ec57dec14
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-crate-multi-decorator.rs
@@ -0,0 +1,41 @@
+// The duplicate macro will create a copy of the item with the given identifier.
+
+// check-pass
+// aux-build:duplicate.rs
+
+#[macro_use]
+extern crate duplicate;
+
+#[duplicate(MyCopy)]
+struct MyStruct {
+ number: i32,
+}
+
+trait TestTrait {
+ #[duplicate(TestType2)]
+ type TestType;
+
+ #[duplicate(required_fn2)]
+ fn required_fn(&self);
+
+ #[duplicate(provided_fn2)]
+ fn provided_fn(&self) {}
+}
+
+impl TestTrait for MyStruct {
+ #[duplicate(TestType2)]
+ type TestType = f64;
+
+ #[duplicate(required_fn2)]
+ fn required_fn(&self) {}
+}
+
+fn main() {
+ let s = MyStruct { number: 42 };
+ s.required_fn();
+ s.required_fn2();
+ s.provided_fn();
+ s.provided_fn2();
+
+ let s = MyCopy { number: 42 };
+}
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.rs b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
new file mode 100644
index 000000000..470b22b48
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.rs
@@ -0,0 +1,57 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn my_macro(input: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_attribute]
+pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_derive(MyTrait)]
+pub fn my_macro_derive(input: TokenStream) -> TokenStream {
+ input
+}
+
+fn check_bang1() {
+ my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+}
+fn check_bang2() {
+ my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr` in this scope
+ crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines
+ //~| ERROR expected macro, found attribute macro `crate::my_macro_attr`
+}
+fn check_bang3() {
+ MyTrait!(); //~ ERROR cannot find macro `MyTrait` in this scope
+ crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
+ //~| ERROR expected macro, found derive macro `crate::MyTrait`
+}
+
+#[my_macro] //~ ERROR cannot find attribute `my_macro` in this scope
+#[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
+ //~| ERROR expected attribute, found macro `crate::my_macro`
+fn check_attr1() {}
+#[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
+fn check_attr2() {}
+#[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
+ //~| ERROR expected attribute, found derive macro `MyTrait`
+fn check_attr3() {}
+
+#[derive(my_macro)] //~ ERROR cannot find derive macro `my_macro` in this scope
+ //~| ERROR cannot find derive macro `my_macro` in this scope
+#[derive(crate::my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines
+ //~| ERROR expected derive macro, found macro `crate::my_macro`
+struct CheckDerive1;
+#[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
+ //~| ERROR expected derive macro, found attribute macro `my_macro_attr`
+struct CheckDerive2;
+#[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
+struct CheckDerive3;
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
new file mode 100644
index 000000000..633a6c6a0
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -0,0 +1,132 @@
+error: can't use a procedural macro from the same crate that defines it
+ --> $DIR/macro-namespace-reserved-2.rs:25:5
+ |
+LL | my_macro!();
+ | ^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+ --> $DIR/macro-namespace-reserved-2.rs:29:5
+ |
+LL | crate::my_macro_attr!();
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: expected macro, found attribute macro `crate::my_macro_attr`
+ --> $DIR/macro-namespace-reserved-2.rs:29:5
+ |
+LL | crate::my_macro_attr!();
+ | ^^^^^^^^^^^^^^^^^^^^ not a macro
+
+error: can't use a procedural macro from the same crate that defines it
+ --> $DIR/macro-namespace-reserved-2.rs:34:5
+ |
+LL | crate::MyTrait!();
+ | ^^^^^^^^^^^^^^
+
+error: expected macro, found derive macro `crate::MyTrait`
+ --> $DIR/macro-namespace-reserved-2.rs:34:5
+ |
+LL | crate::MyTrait!();
+ | ^^^^^^^^^^^^^^ not a macro
+
+error: can't use a procedural macro from the same crate that defines it
+ --> $DIR/macro-namespace-reserved-2.rs:42:3
+ |
+LL | #[my_macro_attr]
+ | ^^^^^^^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+ --> $DIR/macro-namespace-reserved-2.rs:44:3
+ |
+LL | #[MyTrait]
+ | ^^^^^^^
+
+error: expected attribute, found derive macro `MyTrait`
+ --> $DIR/macro-namespace-reserved-2.rs:44:3
+ |
+LL | #[MyTrait]
+ | ^^^^^^^ not an attribute
+
+error: can't use a procedural macro from the same crate that defines it
+ --> $DIR/macro-namespace-reserved-2.rs:53:10
+ |
+LL | #[derive(my_macro_attr)]
+ | ^^^^^^^^^^^^^
+
+error: expected derive macro, found attribute macro `my_macro_attr`
+ --> $DIR/macro-namespace-reserved-2.rs:53:10
+ |
+LL | #[derive(my_macro_attr)]
+ | ^^^^^^^^^^^^^ not a derive macro
+
+error: can't use a procedural macro from the same crate that defines it
+ --> $DIR/macro-namespace-reserved-2.rs:56:10
+ |
+LL | #[derive(MyTrait)]
+ | ^^^^^^^
+
+error: can't use a procedural macro from the same crate that defines it
+ --> $DIR/macro-namespace-reserved-2.rs:39:3
+ |
+LL | #[crate::my_macro]
+ | ^^^^^^^^^^^^^^^
+
+error: expected attribute, found macro `crate::my_macro`
+ --> $DIR/macro-namespace-reserved-2.rs:39:3
+ |
+LL | #[crate::my_macro]
+ | ^^^^^^^^^^^^^^^ not an attribute
+
+error: can't use a procedural macro from the same crate that defines it
+ --> $DIR/macro-namespace-reserved-2.rs:50:10
+ |
+LL | #[derive(crate::my_macro)]
+ | ^^^^^^^^^^^^^^^
+
+error: expected derive macro, found macro `crate::my_macro`
+ --> $DIR/macro-namespace-reserved-2.rs:50:10
+ |
+LL | #[derive(crate::my_macro)]
+ | ^^^^^^^^^^^^^^^ not a derive macro
+
+error: cannot find macro `my_macro_attr` in this scope
+ --> $DIR/macro-namespace-reserved-2.rs:28:5
+ |
+LL | my_macro_attr!();
+ | ^^^^^^^^^^^^^
+ |
+ = note: `my_macro_attr` is in scope, but it is an attribute: `#[my_macro_attr]`
+
+error: cannot find macro `MyTrait` in this scope
+ --> $DIR/macro-namespace-reserved-2.rs:33:5
+ |
+LL | MyTrait!();
+ | ^^^^^^^
+ |
+ = note: `MyTrait` is in scope, but it is a derive macro: `#[derive(MyTrait)]`
+
+error: cannot find attribute `my_macro` in this scope
+ --> $DIR/macro-namespace-reserved-2.rs:38:3
+ |
+LL | #[my_macro]
+ | ^^^^^^^^
+ |
+ = note: `my_macro` is in scope, but it is a function-like macro
+
+error: cannot find derive macro `my_macro` in this scope
+ --> $DIR/macro-namespace-reserved-2.rs:48:10
+ |
+LL | #[derive(my_macro)]
+ | ^^^^^^^^
+ |
+ = note: `my_macro` is in scope, but it is a function-like macro
+
+error: cannot find derive macro `my_macro` in this scope
+ --> $DIR/macro-namespace-reserved-2.rs:48:10
+ |
+LL | #[derive(my_macro)]
+ | ^^^^^^^^
+ |
+ = note: `my_macro` is in scope, but it is a function-like macro
+
+error: aborting due to 20 previous errors
+
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved.rs b/src/test/ui/proc-macro/macro-namespace-reserved.rs
new file mode 100644
index 000000000..60d379e41
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-namespace-reserved.rs
@@ -0,0 +1,38 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(decl_macro)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn my_macro(input: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_attribute]
+pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro_derive(MyTrait)]
+pub fn my_macro_derive(input: TokenStream) -> TokenStream {
+ input
+}
+
+macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times
+macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times
+macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times
+
+#[proc_macro_derive(SameName)]
+pub fn foo(input: TokenStream) -> TokenStream {
+ input
+}
+
+#[proc_macro]
+pub fn SameName(input: TokenStream) -> TokenStream {
+//~^ ERROR the name `SameName` is defined multiple times
+ input
+}
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved.stderr b/src/test/ui/proc-macro/macro-namespace-reserved.stderr
new file mode 100644
index 000000000..f5d589c3a
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-namespace-reserved.stderr
@@ -0,0 +1,47 @@
+error[E0428]: the name `my_macro` is defined multiple times
+ --> $DIR/macro-namespace-reserved.rs:25:1
+ |
+LL | pub fn my_macro(input: TokenStream) -> TokenStream {
+ | -------------------------------------------------- previous definition of the macro `my_macro` here
+...
+LL | macro my_macro() {}
+ | ^^^^^^^^^^^^^^^^ `my_macro` redefined here
+ |
+ = note: `my_macro` must be defined only once in the macro namespace of this module
+
+error[E0428]: the name `my_macro_attr` is defined multiple times
+ --> $DIR/macro-namespace-reserved.rs:26:1
+ |
+LL | pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
+ | ----------------------------------------------------------------------- previous definition of the macro `my_macro_attr` here
+...
+LL | macro my_macro_attr() {}
+ | ^^^^^^^^^^^^^^^^^^^^^ `my_macro_attr` redefined here
+ |
+ = note: `my_macro_attr` must be defined only once in the macro namespace of this module
+
+error[E0428]: the name `MyTrait` is defined multiple times
+ --> $DIR/macro-namespace-reserved.rs:27:1
+ |
+LL | #[proc_macro_derive(MyTrait)]
+ | ------- previous definition of the macro `MyTrait` here
+...
+LL | macro MyTrait() {}
+ | ^^^^^^^^^^^^^^^ `MyTrait` redefined here
+ |
+ = note: `MyTrait` must be defined only once in the macro namespace of this module
+
+error[E0428]: the name `SameName` is defined multiple times
+ --> $DIR/macro-namespace-reserved.rs:35:1
+ |
+LL | #[proc_macro_derive(SameName)]
+ | -------- previous definition of the macro `SameName` here
+...
+LL | pub fn SameName(input: TokenStream) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SameName` redefined here
+ |
+ = note: `SameName` must be defined only once in the macro namespace of this module
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui/proc-macro/macro-quote-cond.rs b/src/test/ui/proc-macro/macro-quote-cond.rs
new file mode 100644
index 000000000..48307f4d9
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-quote-cond.rs
@@ -0,0 +1,46 @@
+// run-pass
+// aux-build:cond_plugin.rs
+
+#![allow(unused_parens)]
+
+extern crate cond_plugin;
+
+use cond_plugin::cond;
+
+fn fact(n : i64) -> i64 {
+ if n == 0 {
+ 1
+ } else {
+ n * fact(n - 1)
+ }
+}
+
+fn fact_cond(n : i64) -> i64 {
+ cond!(
+ ((n == 0) 1)
+ (else (n * fact_cond(n-1)))
+ )
+}
+
+fn fib(n : i64) -> i64 {
+ if n == 0 || n == 1 {
+ 1
+ } else {
+ fib(n-1) + fib(n-2)
+ }
+}
+
+fn fib_cond(n : i64) -> i64 {
+ cond!(
+ ((n == 0) 1)
+ ((n == 1) 1)
+ (else (fib_cond(n-1) + fib_cond(n-2)))
+ )
+}
+
+fn main() {
+ assert_eq!(fact(3), fact_cond(3));
+ assert_eq!(fact(5), fact_cond(5));
+ assert_eq!(fib(5), fib_cond(5));
+ assert_eq!(fib(8), fib_cond(8));
+}
diff --git a/src/test/ui/proc-macro/macro-rules-derive-cfg.rs b/src/test/ui/proc-macro/macro-rules-derive-cfg.rs
new file mode 100644
index 000000000..a221b9578
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-rules-derive-cfg.rs
@@ -0,0 +1,31 @@
+// check-pass
+// compile-flags: -Z span-debug --error-format human
+// aux-build:test-macros.rs
+
+#![feature(rustc_attrs)]
+#![feature(stmt_expr_attributes)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! produce_it {
+ ($expr:expr) => {
+ #[derive(Print)]
+ struct Foo {
+ val: [bool; {
+ let a = #[cfg_attr(not(FALSE), rustc_dummy(first))] $expr;
+ 0
+ }]
+ }
+ }
+}
+
+produce_it!(#[cfg_attr(not(FALSE), rustc_dummy(second))] {
+ #![cfg_attr(not(FALSE), allow(unused))]
+ 30
+});
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout b/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout
new file mode 100644
index 000000000..74641058e
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-rules-derive-cfg.stdout
@@ -0,0 +1,171 @@
+PRINT-DERIVE INPUT (DISPLAY): struct Foo
+{
+ val :
+ [bool ;
+ {
+ let a = #[rustc_dummy(first)] #[rustc_dummy(second)]
+ { #! [allow(unused)] 30 } ; 0
+ }]
+}
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/macro-rules-derive-cfg.rs:17:9: 17:15 (#4),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/macro-rules-derive-cfg.rs:17:16: 17:19 (#4),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "val",
+ span: $DIR/macro-rules-derive-cfg.rs:18:13: 18:16 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:18:16: 18:17 (#4),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "bool",
+ span: $DIR/macro-rules-derive-cfg.rs:18:19: 18:23 (#4),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:18:23: 18:24 (#4),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "let",
+ span: $DIR/macro-rules-derive-cfg.rs:19:17: 19:20 (#4),
+ },
+ Ident {
+ ident: "a",
+ span: $DIR/macro-rules-derive-cfg.rs:19:21: 19:22 (#4),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:19:23: 19:24 (#4),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#4),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/macro-rules-derive-cfg.rs:19:48: 19:59 (#4),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "first",
+ span: $DIR/macro-rules-derive-cfg.rs:19:60: 19:65 (#4),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:19:59: 19:66 (#4),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:19:25: 19:26 (#4),
+ },
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/macro-rules-derive-cfg.rs:26:36: 26:47 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "second",
+ span: $DIR/macro-rules-derive-cfg.rs:26:48: 26:54 (#0),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:26:47: 26:55 (#0),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:26:13: 26:14 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:27:6: 27:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "allow",
+ span: $DIR/macro-rules-derive-cfg.rs:27:29: 27:34 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "unused",
+ span: $DIR/macro-rules-derive-cfg.rs:27:35: 27:41 (#0),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:27:34: 27:42 (#0),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "30",
+ suffix: None,
+ span: $DIR/macro-rules-derive-cfg.rs:28:5: 28:7 (#0),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:26:58: 29:2 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/macro-rules-derive-cfg.rs:19:74: 19:75 (#4),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/macro-rules-derive-cfg.rs:20:17: 20:18 (#4),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:18:25: 21:14 (#4),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:18:18: 21:15 (#4),
+ },
+ ],
+ span: $DIR/macro-rules-derive-cfg.rs:17:20: 22:10 (#4),
+ },
+]
diff --git a/src/test/ui/proc-macro/macro-rules-derive.rs b/src/test/ui/proc-macro/macro-rules-derive.rs
new file mode 100644
index 000000000..e0c40bbc7
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-rules-derive.rs
@@ -0,0 +1,19 @@
+// aux-build:first-second.rs
+
+extern crate first_second;
+use first_second::*;
+
+macro_rules! produce_it {
+ ($name:ident) => {
+ #[first]
+ struct $name {
+ field: MissingType //~ ERROR cannot find type
+ }
+ }
+}
+
+produce_it!(MyName);
+
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/src/test/ui/proc-macro/macro-rules-derive.stderr b/src/test/ui/proc-macro/macro-rules-derive.stderr
new file mode 100644
index 000000000..517cbabd5
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-rules-derive.stderr
@@ -0,0 +1,14 @@
+error[E0412]: cannot find type `MissingType` in this scope
+ --> $DIR/macro-rules-derive.rs:10:20
+ |
+LL | field: MissingType
+ | ^^^^^^^^^^^ not found in this scope
+...
+LL | produce_it!(MyName);
+ | ------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `produce_it` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/proc-macro/macro-use-attr.rs b/src/test/ui/proc-macro/macro-use-attr.rs
new file mode 100644
index 000000000..b101c09ed
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-use-attr.rs
@@ -0,0 +1,12 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[identity_attr]
+struct Foo;
+
+fn main() {
+ let _ = Foo;
+}
diff --git a/src/test/ui/proc-macro/macro-use-bang.rs b/src/test/ui/proc-macro/macro-use-bang.rs
new file mode 100644
index 000000000..4a0bf0b2f
--- /dev/null
+++ b/src/test/ui/proc-macro/macro-use-bang.rs
@@ -0,0 +1,9 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+fn main() {
+ identity!(println!("Hello, world!"));
+}
diff --git a/src/test/ui/proc-macro/macros-in-extern-derive.rs b/src/test/ui/proc-macro/macros-in-extern-derive.rs
new file mode 100644
index 000000000..c8b26b005
--- /dev/null
+++ b/src/test/ui/proc-macro/macros-in-extern-derive.rs
@@ -0,0 +1,6 @@
+extern "C" {
+ #[derive(Copy)] //~ ERROR `derive` may only be applied to `struct`s, `enum`s and `union`s
+ fn f();
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/macros-in-extern-derive.stderr b/src/test/ui/proc-macro/macros-in-extern-derive.stderr
new file mode 100644
index 000000000..efd9ff225
--- /dev/null
+++ b/src/test/ui/proc-macro/macros-in-extern-derive.stderr
@@ -0,0 +1,11 @@
+error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s
+ --> $DIR/macros-in-extern-derive.rs:2:5
+ |
+LL | #[derive(Copy)]
+ | ^^^^^^^^^^^^^^^ not applicable here
+LL | fn f();
+ | ------- not a `struct`, `enum` or `union`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0774`.
diff --git a/src/test/ui/proc-macro/macros-in-extern.rs b/src/test/ui/proc-macro/macros-in-extern.rs
new file mode 100644
index 000000000..57e2066d8
--- /dev/null
+++ b/src/test/ui/proc-macro/macros-in-extern.rs
@@ -0,0 +1,24 @@
+// run-pass
+// aux-build:test-macros.rs
+// ignore-wasm32
+
+#[macro_use]
+extern crate test_macros;
+
+fn main() {
+ assert_eq!(unsafe { rust_get_test_int() }, 1);
+ assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF);
+}
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+ #[empty_attr]
+ fn some_definitely_unknown_symbol_which_should_be_removed();
+
+ #[identity_attr]
+ fn rust_get_test_int() -> isize;
+
+ identity!(
+ fn rust_dbg_extern_identity_u32(arg: u32) -> u32;
+ );
+}
diff --git a/src/test/ui/proc-macro/macros-in-type.rs b/src/test/ui/proc-macro/macros-in-type.rs
new file mode 100644
index 000000000..19ed58ece
--- /dev/null
+++ b/src/test/ui/proc-macro/macros-in-type.rs
@@ -0,0 +1,11 @@
+// check-pass
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+const C: identity!(u8) = 10;
+
+fn main() {
+ let c: u8 = C;
+}
diff --git a/src/test/ui/proc-macro/meta-delim.rs b/src/test/ui/proc-macro/meta-delim.rs
new file mode 100644
index 000000000..964291bc6
--- /dev/null
+++ b/src/test/ui/proc-macro/meta-delim.rs
@@ -0,0 +1,12 @@
+// aux-build:meta-delim.rs
+// edition:2018
+// run-pass
+
+// Tests that we can properly deserialize a macro with strange delimiters
+// See https://github.com/rust-lang/rust/pull/73569#issuecomment-650860457
+
+extern crate meta_delim;
+
+fn main() {
+ assert_eq!("a bunch of idents", meta_delim::meta_delim!(a bunch of idents));
+}
diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.rs b/src/test/ui/proc-macro/meta-macro-hygiene.rs
new file mode 100644
index 000000000..62968ea54
--- /dev/null
+++ b/src/test/ui/proc-macro/meta-macro-hygiene.rs
@@ -0,0 +1,30 @@
+// aux-build:make-macro.rs
+// aux-build:meta-macro.rs
+// edition:2018
+// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no
+// check-pass
+// normalize-stdout-test "\d+#" -> "0#"
+// normalize-stdout-test "expn\d{3,}" -> "expnNNN"
+//
+// We don't care about symbol ids, so we set them all to 0
+// in the stdout
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate meta_macro;
+
+macro_rules! produce_it {
+ () => {
+ // `print_def_site!` will respan the `$crate` identifier
+ // with `Span::def_site()`. This should cause it to resolve
+ // relative to `meta_macro`, *not* `make_macro` (despite
+ // the fact that that `print_def_site` is produced by
+ // a `macro_rules!` macro in `make_macro`).
+ meta_macro::print_def_site!($crate::dummy!());
+ }
+}
+
+fn main() {
+ produce_it!();
+}
diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout
new file mode 100644
index 000000000..5d04fe1e3
--- /dev/null
+++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout
@@ -0,0 +1,69 @@
+Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5)
+Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:24:37: 24:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:24:45: 24:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:50: 24:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:24:51: 24:53 (#4) }]
+Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }]
+#![feature /* 0#0 */(prelude_import)]
+// aux-build:make-macro.rs
+// aux-build:meta-macro.rs
+// edition:2018
+// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene -Z trim-diagnostic-paths=no
+// check-pass
+// normalize-stdout-test "\d+#" -> "0#"
+// normalize-stdout-test "expn\d{3,}" -> "expnNNN"
+//
+// We don't care about symbol ids, so we set them all to 0
+// in the stdout
+
+#![no_std /* 0#0 */]
+#[prelude_import /* 0#1 */]
+use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*;
+#[macro_use /* 0#1 */]
+extern crate core /* 0#1 */;
+#[macro_use /* 0#1 */]
+extern crate compiler_builtins /* 0#1 */;
+// Don't load unnecessary hygiene information from std
+extern crate std /* 0#0 */;
+
+extern crate meta_macro /* 0#0 */;
+
+macro_rules! produce_it
+ /*
+ 0#0
+ */ {
+ () =>
+ {
+ meta_macro :: print_def_site! ($crate :: dummy! ()) ;
+ // `print_def_site!` will respan the `$crate` identifier
+ // with `Span::def_site()`. This should cause it to resolve
+ // relative to `meta_macro`, *not* `make_macro` (despite
+ // the fact that that `print_def_site` is produced by
+ // a `macro_rules!` macro in `make_macro`).
+ }
+}
+
+fn main /* 0#0 */() { ; }
+
+/*
+Expansions:
+crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
+crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
+crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "produce_it")
+crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
+crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #5, def_site_ctxt: #0, kind: Macro(Bang, "$crate::dummy")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include")
+crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
+
+SyntaxContexts:
+#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
+#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
+#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
+#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque)
+#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
+#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
+#6: parent: #4, outer_mark: (crate0::{{expn3}}, Transparent)
+#7: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent)
+#8: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
+#9: parent: #5, outer_mark: (crate0::{{expn4}}, Transparent)
+#10: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
+*/
diff --git a/src/test/ui/proc-macro/meta-macro.rs b/src/test/ui/proc-macro/meta-macro.rs
new file mode 100644
index 000000000..dbac90382
--- /dev/null
+++ b/src/test/ui/proc-macro/meta-macro.rs
@@ -0,0 +1,14 @@
+// aux-build:make-macro.rs
+// aux-build:meta-macro.rs
+// edition:2018
+// compile-flags: -Z span-debug
+// run-pass
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate meta_macro;
+
+fn main() {
+ meta_macro::print_def_site!();
+}
diff --git a/src/test/ui/proc-macro/meta-macro.stdout b/src/test/ui/proc-macro/meta-macro.stdout
new file mode 100644
index 000000000..662682d40
--- /dev/null
+++ b/src/test/ui/proc-macro/meta-macro.stdout
@@ -0,0 +1,3 @@
+Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#4)
+Input: TokenStream []
+Respanned: TokenStream []
diff --git a/src/test/ui/proc-macro/mixed-site-span.rs b/src/test/ui/proc-macro/mixed-site-span.rs
new file mode 100644
index 000000000..008384656
--- /dev/null
+++ b/src/test/ui/proc-macro/mixed-site-span.rs
@@ -0,0 +1,24 @@
+// Proc macros using `mixed_site` spans exhibit usual properties of `macro_rules` hygiene.
+
+// aux-build:mixed-site-span.rs
+
+#[macro_use]
+extern crate mixed_site_span;
+
+struct ItemUse;
+
+fn main() {
+ 'label_use: loop {
+ let local_use = 1;
+ proc_macro_rules!();
+ //~^ ERROR use of undeclared label `'label_use`
+ //~| ERROR cannot find value `local_use` in this scope
+ ItemDef; // OK
+ local_def; //~ ERROR cannot find value `local_def` in this scope
+ }
+}
+
+macro_rules! pass_dollar_crate {
+ () => (proc_macro_rules!($crate);) //~ ERROR cannot find type `ItemUse` in crate `$crate`
+}
+pass_dollar_crate!();
diff --git a/src/test/ui/proc-macro/mixed-site-span.stderr b/src/test/ui/proc-macro/mixed-site-span.stderr
new file mode 100644
index 000000000..eab4317de
--- /dev/null
+++ b/src/test/ui/proc-macro/mixed-site-span.stderr
@@ -0,0 +1,34 @@
+error[E0426]: use of undeclared label `'label_use`
+ --> $DIR/mixed-site-span.rs:13:9
+ |
+LL | proc_macro_rules!();
+ | ^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use`
+ |
+ = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0425]: cannot find value `local_use` in this scope
+ --> $DIR/mixed-site-span.rs:13:9
+ |
+LL | proc_macro_rules!();
+ | ^^^^^^^^^^^^^^^^^^^ not found in this scope
+ |
+ = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0425]: cannot find value `local_def` in this scope
+ --> $DIR/mixed-site-span.rs:17:9
+ |
+LL | local_def;
+ | ^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `ItemUse` in crate `$crate`
+ --> $DIR/mixed-site-span.rs:24:1
+ |
+LL | pass_dollar_crate!();
+ | ^^^^^^^^^^^^^^^^^^^^ not found in `$crate`
+ |
+ = note: this error originates in the macro `proc_macro_rules` which comes from the expansion of the macro `pass_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0412, E0425, E0426.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/proc-macro/modify-ast.rs b/src/test/ui/proc-macro/modify-ast.rs
new file mode 100644
index 000000000..ea9bf837c
--- /dev/null
+++ b/src/test/ui/proc-macro/modify-ast.rs
@@ -0,0 +1,26 @@
+// run-pass
+// aux-build:modify-ast.rs
+
+extern crate modify_ast;
+
+use modify_ast::*;
+
+#[derive(Foo)]
+pub struct MyStructc {
+ #[cfg_attr(my_cfg, foo)]
+ _a: i32,
+}
+
+macro_rules! a {
+ ($i:item) => ($i)
+}
+
+a! {
+ #[assert1]
+ pub fn foo() {}
+}
+
+fn main() {
+ let _a = MyStructc { _a: 0 };
+ foo();
+}
diff --git a/src/test/ui/proc-macro/module.rs b/src/test/ui/proc-macro/module.rs
new file mode 100644
index 000000000..5777ed899
--- /dev/null
+++ b/src/test/ui/proc-macro/module.rs
@@ -0,0 +1 @@
+// ignore-test
diff --git a/src/test/ui/proc-macro/module_with_attrs.rs b/src/test/ui/proc-macro/module_with_attrs.rs
new file mode 100644
index 000000000..63e66a62a
--- /dev/null
+++ b/src/test/ui/proc-macro/module_with_attrs.rs
@@ -0,0 +1,4 @@
+// ignore-test
+
+#![rustfmt::skip]
+#![print_attr]
diff --git a/src/test/ui/proc-macro/multispan.rs b/src/test/ui/proc-macro/multispan.rs
new file mode 100644
index 000000000..e9e0349f2
--- /dev/null
+++ b/src/test/ui/proc-macro/multispan.rs
@@ -0,0 +1,25 @@
+// aux-build:multispan.rs
+
+extern crate multispan;
+
+use multispan::hello;
+
+fn main() {
+ // This one emits no error.
+ hello!();
+
+ // Exactly one 'hi'.
+ hello!(hi); //~ ERROR hello to you, too!
+
+ // Now two, back to back.
+ hello!(hi hi); //~ ERROR hello to you, too!
+
+ // Now three, back to back.
+ hello!(hi hi hi); //~ ERROR hello to you, too!
+
+ // Now several, with spacing.
+ hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too!
+ hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too!
+ hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too!
+ hello!(hi good hi and good bye); //~ ERROR hello to you, too!
+}
diff --git a/src/test/ui/proc-macro/multispan.stderr b/src/test/ui/proc-macro/multispan.stderr
new file mode 100644
index 000000000..0aea02bbd
--- /dev/null
+++ b/src/test/ui/proc-macro/multispan.stderr
@@ -0,0 +1,93 @@
+error: hello to you, too!
+ --> $DIR/multispan.rs:12:5
+ |
+LL | hello!(hi);
+ | ^^^^^^^^^^
+ |
+note: found these 'hi's
+ --> $DIR/multispan.rs:12:12
+ |
+LL | hello!(hi);
+ | ^^
+ = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: hello to you, too!
+ --> $DIR/multispan.rs:15:5
+ |
+LL | hello!(hi hi);
+ | ^^^^^^^^^^^^^
+ |
+note: found these 'hi's
+ --> $DIR/multispan.rs:15:12
+ |
+LL | hello!(hi hi);
+ | ^^ ^^
+ = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: hello to you, too!
+ --> $DIR/multispan.rs:18:5
+ |
+LL | hello!(hi hi hi);
+ | ^^^^^^^^^^^^^^^^
+ |
+note: found these 'hi's
+ --> $DIR/multispan.rs:18:12
+ |
+LL | hello!(hi hi hi);
+ | ^^ ^^ ^^
+ = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: hello to you, too!
+ --> $DIR/multispan.rs:21:5
+ |
+LL | hello!(hi hey hi yo hi beep beep hi hi);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: found these 'hi's
+ --> $DIR/multispan.rs:21:12
+ |
+LL | hello!(hi hey hi yo hi beep beep hi hi);
+ | ^^ ^^ ^^ ^^ ^^
+ = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: hello to you, too!
+ --> $DIR/multispan.rs:22:5
+ |
+LL | hello!(hi there, hi how are you? hi... hi.);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: found these 'hi's
+ --> $DIR/multispan.rs:22:12
+ |
+LL | hello!(hi there, hi how are you? hi... hi.);
+ | ^^ ^^ ^^ ^^
+ = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: hello to you, too!
+ --> $DIR/multispan.rs:23:5
+ |
+LL | hello!(whoah. hi di hi di ho);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: found these 'hi's
+ --> $DIR/multispan.rs:23:19
+ |
+LL | hello!(whoah. hi di hi di ho);
+ | ^^ ^^
+ = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: hello to you, too!
+ --> $DIR/multispan.rs:24:5
+ |
+LL | hello!(hi good hi and good bye);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: found these 'hi's
+ --> $DIR/multispan.rs:24:12
+ |
+LL | hello!(hi good hi and good bye);
+ | ^^ ^^
+ = note: this error originates in the macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/proc-macro/negative-token.rs b/src/test/ui/proc-macro/negative-token.rs
new file mode 100644
index 000000000..2ed3cbc08
--- /dev/null
+++ b/src/test/ui/proc-macro/negative-token.rs
@@ -0,0 +1,11 @@
+// run-pass
+// aux-build:negative-token.rs
+
+extern crate negative_token;
+
+use negative_token::*;
+
+fn main() {
+ assert_eq!(-1, neg_one!());
+ assert_eq!(-1.0, neg_one_float!());
+}
diff --git a/src/test/ui/proc-macro/nested-derive-cfg.rs b/src/test/ui/proc-macro/nested-derive-cfg.rs
new file mode 100644
index 000000000..53cfbb7c9
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-derive-cfg.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Z span-debug --error-format human
+// aux-build:test-macros.rs
+// check-pass
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+#[derive(Print)]
+struct Foo {
+ #[cfg(FALSE)] removed: bool,
+ my_array: [bool; {
+ struct Inner {
+ #[cfg(FALSE)] removed_inner_field: u8,
+ non_removed_inner_field: usize
+ }
+ 0
+ }]
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/nested-derive-cfg.stdout b/src/test/ui/proc-macro/nested-derive-cfg.stdout
new file mode 100644
index 000000000..9a562c971
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-derive-cfg.stdout
@@ -0,0 +1,81 @@
+PRINT-DERIVE INPUT (DISPLAY): struct Foo
+{ my_array : [bool ; { struct Inner { non_removed_inner_field : usize } 0 }] }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/nested-derive-cfg.rs:12:1: 12:7 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/nested-derive-cfg.rs:12:8: 12:11 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "my_array",
+ span: $DIR/nested-derive-cfg.rs:14:5: 14:13 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/nested-derive-cfg.rs:14:13: 14:14 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "bool",
+ span: $DIR/nested-derive-cfg.rs:14:16: 14:20 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/nested-derive-cfg.rs:14:20: 14:21 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/nested-derive-cfg.rs:15:9: 15:15 (#0),
+ },
+ Ident {
+ ident: "Inner",
+ span: $DIR/nested-derive-cfg.rs:15:16: 15:21 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "non_removed_inner_field",
+ span: $DIR/nested-derive-cfg.rs:17:13: 17:36 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/nested-derive-cfg.rs:17:36: 17:37 (#0),
+ },
+ Ident {
+ ident: "usize",
+ span: $DIR/nested-derive-cfg.rs:17:38: 17:43 (#0),
+ },
+ ],
+ span: $DIR/nested-derive-cfg.rs:15:22: 18:10 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/nested-derive-cfg.rs:19:9: 19:10 (#0),
+ },
+ ],
+ span: $DIR/nested-derive-cfg.rs:14:22: 20:6 (#0),
+ },
+ ],
+ span: $DIR/nested-derive-cfg.rs:14:15: 20:7 (#0),
+ },
+ ],
+ span: $DIR/nested-derive-cfg.rs:12:12: 21:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/nested-item-spans.rs b/src/test/ui/proc-macro/nested-item-spans.rs
new file mode 100644
index 000000000..63da170d0
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-item-spans.rs
@@ -0,0 +1,23 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[recollect_attr]
+fn another() {
+ fn bar() {
+ let x: u32 = "x"; //~ ERROR: mismatched types
+ }
+
+ bar();
+}
+
+fn main() {
+ #[recollect_attr]
+ fn bar() {
+ let x: u32 = "x"; //~ ERROR: mismatched types
+ }
+
+ bar();
+ another();
+}
diff --git a/src/test/ui/proc-macro/nested-item-spans.stderr b/src/test/ui/proc-macro/nested-item-spans.stderr
new file mode 100644
index 000000000..44b338fa6
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-item-spans.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+ --> $DIR/nested-item-spans.rs:9:22
+ |
+LL | let x: u32 = "x";
+ | --- ^^^ expected `u32`, found `&str`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/nested-item-spans.rs:18:22
+ |
+LL | let x: u32 = "x";
+ | --- ^^^ expected `u32`, found `&str`
+ | |
+ | expected due to this
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/nested-macro-rules.rs b/src/test/ui/proc-macro/nested-macro-rules.rs
new file mode 100644
index 000000000..25ffcfad7
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-macro-rules.rs
@@ -0,0 +1,23 @@
+// run-pass
+// aux-build:nested-macro-rules.rs
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug -Z macro-backtrace
+// edition:2018
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate nested_macro_rules;
+extern crate test_macros;
+
+use test_macros::{print_bang, print_attr};
+
+use nested_macro_rules::FirstStruct;
+struct SecondStruct;
+
+fn main() {
+ nested_macro_rules::inner_macro!(print_bang, print_attr);
+
+ nested_macro_rules::outer_macro!(SecondStruct, SecondAttrStruct);
+ inner_macro!(print_bang, print_attr);
+}
diff --git a/src/test/ui/proc-macro/nested-macro-rules.stdout b/src/test/ui/proc-macro/nested-macro-rules.stdout
new file mode 100644
index 000000000..311139040
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-macro-rules.stdout
@@ -0,0 +1,46 @@
+PRINT-BANG INPUT (DISPLAY): FirstStruct
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "FirstStruct",
+ span: $DIR/auxiliary/nested-macro-rules.rs:16:14: 16:25 (#7),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): struct FirstAttrStruct {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#6),
+ },
+ Ident {
+ ident: "FirstAttrStruct",
+ span: $DIR/auxiliary/nested-macro-rules.rs:16:27: 16:42 (#7),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#6),
+ },
+]
+PRINT-BANG INPUT (DISPLAY): SecondStruct
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "SecondStruct",
+ span: $DIR/nested-macro-rules.rs:21:38: 21:50 (#16),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): struct SecondAttrStruct {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/auxiliary/nested-macro-rules.rs:10:32: 10:38 (#15),
+ },
+ Ident {
+ ident: "SecondAttrStruct",
+ span: $DIR/nested-macro-rules.rs:21:52: 21:68 (#16),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/auxiliary/nested-macro-rules.rs:10:57: 10:59 (#15),
+ },
+]
diff --git a/src/test/ui/proc-macro/nested-nonterminal-tokens.rs b/src/test/ui/proc-macro/nested-nonterminal-tokens.rs
new file mode 100644
index 000000000..04d34e21c
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-nonterminal-tokens.rs
@@ -0,0 +1,26 @@
+// check-pass
+// edition:2018
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+
+// Tests that we properly pass tokens to proc-macro when nested
+// nonterminals are involved.
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+
+macro_rules! wrap {
+ (first, $e:expr) => { wrap!(second, $e + 1) };
+ (second, $e:expr) => { wrap!(third, $e + 2) };
+ (third, $e:expr) => {
+ print_bang!($e + 3)
+ };
+}
+
+fn main() {
+ let _ = wrap!(first, 0);
+}
diff --git a/src/test/ui/proc-macro/nested-nonterminal-tokens.stdout b/src/test/ui/proc-macro/nested-nonterminal-tokens.stdout
new file mode 100644
index 000000000..a3d24dd26
--- /dev/null
+++ b/src/test/ui/proc-macro/nested-nonterminal-tokens.stdout
@@ -0,0 +1,60 @@
+PRINT-BANG INPUT (DISPLAY): 0 + 1 + 2 + 3
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/nested-nonterminal-tokens.rs:25:26: 25:27 (#0),
+ },
+ ],
+ span: $DIR/nested-nonterminal-tokens.rs:17:41: 17:43 (#4),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/nested-nonterminal-tokens.rs:17:44: 17:45 (#4),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/nested-nonterminal-tokens.rs:17:46: 17:47 (#4),
+ },
+ ],
+ span: $DIR/nested-nonterminal-tokens.rs:18:41: 18:43 (#5),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/nested-nonterminal-tokens.rs:18:44: 18:45 (#5),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "2",
+ suffix: None,
+ span: $DIR/nested-nonterminal-tokens.rs:18:46: 18:47 (#5),
+ },
+ ],
+ span: $DIR/nested-nonterminal-tokens.rs:20:21: 20:23 (#6),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/nested-nonterminal-tokens.rs:20:24: 20:25 (#6),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "3",
+ suffix: None,
+ span: $DIR/nested-nonterminal-tokens.rs:20:26: 20:27 (#6),
+ },
+]
diff --git a/src/test/ui/proc-macro/no-macro-use-attr.rs b/src/test/ui/proc-macro/no-macro-use-attr.rs
new file mode 100644
index 000000000..a8a8fa4e1
--- /dev/null
+++ b/src/test/ui/proc-macro/no-macro-use-attr.rs
@@ -0,0 +1,10 @@
+// aux-build:test-macros.rs
+
+#![feature(rustc_attrs)]
+#![warn(unused_extern_crates)]
+
+extern crate test_macros;
+//~^ WARN unused extern crate
+
+#[rustc_error]
+fn main() {} //~ ERROR fatal error triggered by #[rustc_error]
diff --git a/src/test/ui/proc-macro/no-macro-use-attr.stderr b/src/test/ui/proc-macro/no-macro-use-attr.stderr
new file mode 100644
index 000000000..a9e5256a0
--- /dev/null
+++ b/src/test/ui/proc-macro/no-macro-use-attr.stderr
@@ -0,0 +1,20 @@
+warning: unused extern crate
+ --> $DIR/no-macro-use-attr.rs:6:1
+ |
+LL | extern crate test_macros;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+ |
+note: the lint level is defined here
+ --> $DIR/no-macro-use-attr.rs:4:9
+ |
+LL | #![warn(unused_extern_crates)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: fatal error triggered by #[rustc_error]
+ --> $DIR/no-macro-use-attr.rs:10:1
+ |
+LL | fn main() {}
+ | ^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/proc-macro/no-missing-docs.rs b/src/test/ui/proc-macro/no-missing-docs.rs
new file mode 100644
index 000000000..e1e821858
--- /dev/null
+++ b/src/test/ui/proc-macro/no-missing-docs.rs
@@ -0,0 +1,16 @@
+//! Verify that the `decls` module implicitly added by the compiler does not cause `missing_docs`
+//! warnings.
+
+// build-pass (FIXME(62277): could be check-pass?)
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![deny(missing_docs)]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+/// Foo1.
+#[proc_macro]
+pub fn foo1(input: TokenStream) -> TokenStream { input }
diff --git a/src/test/ui/proc-macro/nodelim-groups.rs b/src/test/ui/proc-macro/nodelim-groups.rs
new file mode 100644
index 000000000..ec3019902
--- /dev/null
+++ b/src/test/ui/proc-macro/nodelim-groups.rs
@@ -0,0 +1,22 @@
+// run-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+// edition:2018
+//
+// Tests the pretty-printing behavior of inserting `Invisible`-delimited groups
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate test_macros;
+use test_macros::print_bang_consume;
+
+macro_rules! expand_it {
+ (($val1:expr) ($val2:expr)) => { expand_it!($val1 + $val2) };
+ ($val:expr) => { print_bang_consume!("hi" $val (1 + 1)) };
+}
+
+fn main() {
+ expand_it!(1 + (25) + 1);
+ expand_it!(("hello".len()) ("world".len()));
+}
diff --git a/src/test/ui/proc-macro/nodelim-groups.stdout b/src/test/ui/proc-macro/nodelim-groups.stdout
new file mode 100644
index 000000000..6b410f0bf
--- /dev/null
+++ b/src/test/ui/proc-macro/nodelim-groups.stdout
@@ -0,0 +1,167 @@
+PRINT-BANG INPUT (DISPLAY): "hi" 1 + (25) + 1 (1 + 1)
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Literal {
+ kind: Str,
+ symbol: "hi",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:16:42: 16:46 (#4),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:20:16: 20:17 (#0),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/nodelim-groups.rs:20:18: 20:19 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "25",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:20:21: 20:23 (#0),
+ },
+ ],
+ span: $DIR/nodelim-groups.rs:20:20: 20:24 (#0),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/nodelim-groups.rs:20:25: 20:26 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:20:27: 20:28 (#0),
+ },
+ ],
+ span: $DIR/nodelim-groups.rs:16:47: 16:51 (#4),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:16:53: 16:54 (#4),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/nodelim-groups.rs:16:55: 16:56 (#4),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:16:57: 16:58 (#4),
+ },
+ ],
+ span: $DIR/nodelim-groups.rs:16:52: 16:59 (#4),
+ },
+]
+PRINT-BANG INPUT (DISPLAY): "hi" "hello".len() + "world".len() (1 + 1)
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Literal {
+ kind: Str,
+ symbol: "hi",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:16:42: 16:46 (#9),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Literal {
+ kind: Str,
+ symbol: "hello",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:21:17: 21:24 (#0),
+ },
+ Punct {
+ ch: '.',
+ spacing: Alone,
+ span: $DIR/nodelim-groups.rs:21:24: 21:25 (#0),
+ },
+ Ident {
+ ident: "len",
+ span: $DIR/nodelim-groups.rs:21:25: 21:28 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/nodelim-groups.rs:21:28: 21:30 (#0),
+ },
+ ],
+ span: $DIR/nodelim-groups.rs:15:49: 15:54 (#8),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/nodelim-groups.rs:15:55: 15:56 (#8),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Literal {
+ kind: Str,
+ symbol: "world",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:21:33: 21:40 (#0),
+ },
+ Punct {
+ ch: '.',
+ spacing: Alone,
+ span: $DIR/nodelim-groups.rs:21:40: 21:41 (#0),
+ },
+ Ident {
+ ident: "len",
+ span: $DIR/nodelim-groups.rs:21:41: 21:44 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/nodelim-groups.rs:21:44: 21:46 (#0),
+ },
+ ],
+ span: $DIR/nodelim-groups.rs:15:57: 15:62 (#8),
+ },
+ ],
+ span: $DIR/nodelim-groups.rs:16:47: 16:51 (#9),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:16:53: 16:54 (#9),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/nodelim-groups.rs:16:55: 16:56 (#9),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/nodelim-groups.rs:16:57: 16:58 (#9),
+ },
+ ],
+ span: $DIR/nodelim-groups.rs:16:52: 16:59 (#9),
+ },
+]
diff --git a/src/test/ui/proc-macro/non-root.rs b/src/test/ui/proc-macro/non-root.rs
new file mode 100644
index 000000000..a7c4ac00a
--- /dev/null
+++ b/src/test/ui/proc-macro/non-root.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+fn foo(arg: TokenStream) -> TokenStream {
+ #[proc_macro]
+ pub fn foo(arg: TokenStream) -> TokenStream { arg }
+ //~^ ERROR functions tagged with `#[proc_macro]` must currently reside in the root of the crate
+
+ arg
+}
diff --git a/src/test/ui/proc-macro/non-root.stderr b/src/test/ui/proc-macro/non-root.stderr
new file mode 100644
index 000000000..90f94b677
--- /dev/null
+++ b/src/test/ui/proc-macro/non-root.stderr
@@ -0,0 +1,8 @@
+error: functions tagged with `#[proc_macro]` must currently reside in the root of the crate
+ --> $DIR/non-root.rs:11:5
+ |
+LL | pub fn foo(arg: TokenStream) -> TokenStream { arg }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/nonterminal-expansion.rs b/src/test/ui/proc-macro/nonterminal-expansion.rs
new file mode 100644
index 000000000..e62155871
--- /dev/null
+++ b/src/test/ui/proc-macro/nonterminal-expansion.rs
@@ -0,0 +1,37 @@
+// check-pass
+// compile-flags: -Z span-debug
+// aux-build:test-macros.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! pass_nonterminal {
+ ($line:expr) => {
+ #[print_attr_args(a, $line, b)]
+ struct S;
+ };
+}
+
+// `line!()` is not expanded before it's passed to the proc macro.
+pass_nonterminal!(line!());
+
+// Test case from #43860.
+
+#[macro_export]
+macro_rules! use_contract {
+ ($name: ident, $path: expr) => {
+ #[derive(Empty)]
+ #[empty_helper(path = $path)] // OK
+ pub struct $name<T, C> {
+ api: T,
+ contract: C,
+ }
+ };
+}
+
+use_contract!(ContractName, file!());
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/nonterminal-expansion.stdout b/src/test/ui/proc-macro/nonterminal-expansion.stdout
new file mode 100644
index 000000000..4d884348f
--- /dev/null
+++ b/src/test/ui/proc-macro/nonterminal-expansion.stdout
@@ -0,0 +1,42 @@
+PRINT-ATTR_ARGS INPUT (DISPLAY): a, line!(), b
+PRINT-ATTR_ARGS RE-COLLECTED (DISPLAY): a, line! (), b
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "a",
+ span: $DIR/nonterminal-expansion.rs:13:27: 13:28 (#4),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/nonterminal-expansion.rs:13:28: 13:29 (#4),
+ },
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "line",
+ span: $DIR/nonterminal-expansion.rs:19:19: 19:23 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/nonterminal-expansion.rs:19:23: 19:24 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/nonterminal-expansion.rs:19:24: 19:26 (#0),
+ },
+ ],
+ span: $DIR/nonterminal-expansion.rs:13:30: 13:35 (#4),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/nonterminal-expansion.rs:13:35: 13:36 (#4),
+ },
+ Ident {
+ ident: "b",
+ span: $DIR/nonterminal-expansion.rs:13:37: 13:38 (#4),
+ },
+]
diff --git a/src/test/ui/proc-macro/nonterminal-recollect-attr.rs b/src/test/ui/proc-macro/nonterminal-recollect-attr.rs
new file mode 100644
index 000000000..79c4ad4cd
--- /dev/null
+++ b/src/test/ui/proc-macro/nonterminal-recollect-attr.rs
@@ -0,0 +1,21 @@
+// check-pass
+// compile-flags: -Z span-debug
+// aux-build:nonterminal-recollect-attr.rs
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate nonterminal_recollect_attr;
+use nonterminal_recollect_attr::*;
+
+macro_rules! my_macro {
+ ($v:ident) => {
+ #[first_attr]
+ $v struct Foo {
+ field: u8
+ }
+ }
+}
+
+my_macro!(pub);
+fn main() {}
diff --git a/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout
new file mode 100644
index 000000000..6824395ae
--- /dev/null
+++ b/src/test/ui/proc-macro/nonterminal-recollect-attr.stdout
@@ -0,0 +1,66 @@
+First recollected: TokenStream [
+ Ident {
+ ident: "pub",
+ span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/nonterminal-recollect-attr.rs:14:12: 14:18 (#4),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/nonterminal-recollect-attr.rs:14:19: 14:22 (#4),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "field",
+ span: $DIR/nonterminal-recollect-attr.rs:15:13: 15:18 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/nonterminal-recollect-attr.rs:15:18: 15:19 (#4),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/nonterminal-recollect-attr.rs:15:20: 15:22 (#4),
+ },
+ ],
+ span: $DIR/nonterminal-recollect-attr.rs:14:23: 16:10 (#4),
+ },
+]
+Second recollected: TokenStream [
+ Ident {
+ ident: "pub",
+ span: $DIR/nonterminal-recollect-attr.rs:20:11: 20:14 (#0),
+ },
+ Ident {
+ ident: "struct",
+ span: $DIR/nonterminal-recollect-attr.rs:14:12: 14:18 (#4),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/nonterminal-recollect-attr.rs:14:19: 14:22 (#4),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "field",
+ span: $DIR/nonterminal-recollect-attr.rs:15:13: 15:18 (#4),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/nonterminal-recollect-attr.rs:15:18: 15:19 (#4),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/nonterminal-recollect-attr.rs:15:20: 15:22 (#4),
+ },
+ ],
+ span: $DIR/nonterminal-recollect-attr.rs:14:23: 16:10 (#4),
+ },
+]
diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.rs b/src/test/ui/proc-macro/nonterminal-token-hygiene.rs
new file mode 100644
index 000000000..fa52a975b
--- /dev/null
+++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.rs
@@ -0,0 +1,34 @@
+// Make sure that marks from declarative macros are applied to tokens in nonterminal.
+
+// check-pass
+// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene
+// compile-flags: -Z trim-diagnostic-paths=no
+// normalize-stdout-test "\d+#" -> "0#"
+// normalize-stdout-test "expn\d{3,}" -> "expnNNN"
+// aux-build:test-macros.rs
+
+#![feature(decl_macro)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! outer {
+ ($item:item) => {
+ macro inner() {
+ print_bang! { $item }
+ }
+
+ inner!();
+ };
+}
+
+struct S;
+
+outer! {
+ struct S; // OK, not a duplicate definition of `S`
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout
new file mode 100644
index 000000000..c08e53081
--- /dev/null
+++ b/src/test/ui/proc-macro/nonterminal-token-hygiene.stdout
@@ -0,0 +1,92 @@
+PRINT-BANG INPUT (DISPLAY): struct S;
+PRINT-BANG RE-COLLECTED (DISPLAY): struct S ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: None,
+ stream: TokenStream [
+ Ident {
+ ident: "struct",
+ span: $DIR/nonterminal-token-hygiene.rs:31:5: 31:11 (#5),
+ },
+ Ident {
+ ident: "S",
+ span: $DIR/nonterminal-token-hygiene.rs:31:12: 31:13 (#5),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/nonterminal-token-hygiene.rs:31:13: 31:14 (#5),
+ },
+ ],
+ span: $DIR/nonterminal-token-hygiene.rs:21:27: 21:32 (#6),
+ },
+]
+#![feature /* 0#0 */(prelude_import)]
+#![no_std /* 0#0 */]
+// Make sure that marks from declarative macros are applied to tokens in nonterminal.
+
+// check-pass
+// compile-flags: -Z span-debug -Z macro-backtrace -Z unpretty=expanded,hygiene
+// compile-flags: -Z trim-diagnostic-paths=no
+// normalize-stdout-test "\d+#" -> "0#"
+// normalize-stdout-test "expn\d{3,}" -> "expnNNN"
+// aux-build:test-macros.rs
+
+#![feature /* 0#0 */(decl_macro)]
+
+#![no_std /* 0#0 */]
+#[prelude_import /* 0#1 */]
+use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*;
+#[macro_use /* 0#1 */]
+extern crate core /* 0#2 */;
+#[macro_use /* 0#1 */]
+extern crate compiler_builtins /* 0#2 */;
+// Don't load unnecessary hygiene information from std
+extern crate std /* 0#0 */;
+
+#[macro_use /* 0#0 */]
+extern crate test_macros /* 0#0 */;
+
+macro_rules! outer
+ /*
+ 0#0
+ */ {
+ ($item : item) =>
+ {
+ macro inner() { print_bang! { $item } } inner! () ;
+
+ } ;
+}
+
+struct S /* 0#0 */;
+macro inner /* 0#4 */ { () => { print_bang! { struct S; } } }
+
+struct S /* 0#5 */;
+// OK, not a duplicate definition of `S`
+
+fn main /* 0#0 */() {}
+
+/*
+Expansions:
+crate0::{{expn0}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
+crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
+crate0::{{expn2}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "outer")
+crate0::{{expn3}}: parent: crate0::{{expn2}}, call_site_ctxt: #4, def_site_ctxt: #4, kind: Macro(Bang, "inner")
+crate0::{{expn4}}: parent: crate0::{{expn3}}, call_site_ctxt: #6, def_site_ctxt: #0, kind: Macro(Bang, "print_bang")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Attr, "derive")
+crate1::{{expnNNN}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "include")
+crate2::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
+
+SyntaxContexts:
+#0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque)
+#1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque)
+#2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent)
+#3: parent: #0, outer_mark: (crate2::{{expn1}}, Opaque)
+#4: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent)
+#5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque)
+#6: parent: #4, outer_mark: (crate0::{{expn3}}, Opaque)
+#7: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque)
+#8: parent: #6, outer_mark: (crate0::{{expn4}}, Transparent)
+#9: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent)
+*/
diff --git a/src/test/ui/proc-macro/not-joint.rs b/src/test/ui/proc-macro/not-joint.rs
new file mode 100644
index 000000000..30da2811e
--- /dev/null
+++ b/src/test/ui/proc-macro/not-joint.rs
@@ -0,0 +1,24 @@
+// run-pass
+// aux-build:not-joint.rs
+
+extern crate not_joint as bar;
+use bar::{tokens, nothing};
+
+tokens![< -];
+
+#[nothing]
+a![< -];
+
+#[nothing]
+b!{< -}
+
+#[nothing]
+c!(< -);
+
+#[nothing]
+fn foo() {
+ //! dox
+ let x = 2 < - 3;
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/out-of-line-mod.rs b/src/test/ui/proc-macro/out-of-line-mod.rs
new file mode 100644
index 000000000..658ed6c18
--- /dev/null
+++ b/src/test/ui/proc-macro/out-of-line-mod.rs
@@ -0,0 +1,13 @@
+// Out-of-line module is found on the filesystem if passed through a proc macro (issue #58818).
+
+// check-pass
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+mod outer {
+ identity! { mod inner; }
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/outer/inner.rs b/src/test/ui/proc-macro/outer/inner.rs
new file mode 100644
index 000000000..5777ed899
--- /dev/null
+++ b/src/test/ui/proc-macro/outer/inner.rs
@@ -0,0 +1 @@
+// ignore-test
diff --git a/src/test/ui/proc-macro/parent-source-spans.rs b/src/test/ui/proc-macro/parent-source-spans.rs
new file mode 100644
index 000000000..354657db4
--- /dev/null
+++ b/src/test/ui/proc-macro/parent-source-spans.rs
@@ -0,0 +1,53 @@
+// aux-build:parent-source-spans.rs
+
+#![feature(decl_macro)]
+
+extern crate parent_source_spans;
+
+use parent_source_spans::parent_source_spans;
+
+macro one($a:expr, $b:expr) {
+ two!($a, $b);
+ //~^ ERROR first parent: "hello"
+ //~| ERROR second parent: "world"
+}
+
+macro two($a:expr, $b:expr) {
+ three!($a, $b);
+ //~^ ERROR first final: "hello"
+ //~| ERROR second final: "world"
+ //~| ERROR first final: "yay"
+ //~| ERROR second final: "rust"
+}
+
+// forwarding tokens directly doesn't create a new source chain
+macro three($($tokens:tt)*) {
+ four!($($tokens)*);
+}
+
+macro four($($tokens:tt)*) {
+ parent_source_spans!($($tokens)*);
+ //~^ ERROR cannot find value `ok` in this scope
+ //~| ERROR cannot find value `ok` in this scope
+ //~| ERROR cannot find value `ok` in this scope
+}
+
+fn main() {
+ one!("hello", "world");
+ //~^ ERROR first grandparent: "hello"
+ //~| ERROR second grandparent: "world"
+ //~| ERROR first source: "hello"
+ //~| ERROR second source: "world"
+
+ two!("yay", "rust");
+ //~^ ERROR first parent: "yay"
+ //~| ERROR second parent: "rust"
+ //~| ERROR first source: "yay"
+ //~| ERROR second source: "rust"
+
+ three!("hip", "hop");
+ //~^ ERROR first final: "hip"
+ //~| ERROR second final: "hop"
+ //~| ERROR first source: "hip"
+ //~| ERROR second source: "hop"
+}
diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr
new file mode 100644
index 000000000..65ce24e55
--- /dev/null
+++ b/src/test/ui/proc-macro/parent-source-spans.stderr
@@ -0,0 +1,189 @@
+error: first final: "hello"
+ --> $DIR/parent-source-spans.rs:16:12
+ |
+LL | three!($a, $b);
+ | ^^
+...
+LL | one!("hello", "world");
+ | ---------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `two` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: second final: "world"
+ --> $DIR/parent-source-spans.rs:16:16
+ |
+LL | three!($a, $b);
+ | ^^
+...
+LL | one!("hello", "world");
+ | ---------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `two` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: first parent: "hello"
+ --> $DIR/parent-source-spans.rs:10:5
+ |
+LL | two!($a, $b);
+ | ^^^^^^^^^^^^
+...
+LL | one!("hello", "world");
+ | ---------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: second parent: "world"
+ --> $DIR/parent-source-spans.rs:10:5
+ |
+LL | two!($a, $b);
+ | ^^^^^^^^^^^^
+...
+LL | one!("hello", "world");
+ | ---------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: first grandparent: "hello"
+ --> $DIR/parent-source-spans.rs:36:5
+ |
+LL | one!("hello", "world");
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: second grandparent: "world"
+ --> $DIR/parent-source-spans.rs:36:5
+ |
+LL | one!("hello", "world");
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: first source: "hello"
+ --> $DIR/parent-source-spans.rs:36:5
+ |
+LL | one!("hello", "world");
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: second source: "world"
+ --> $DIR/parent-source-spans.rs:36:5
+ |
+LL | one!("hello", "world");
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: first final: "yay"
+ --> $DIR/parent-source-spans.rs:16:12
+ |
+LL | three!($a, $b);
+ | ^^
+...
+LL | two!("yay", "rust");
+ | ------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: second final: "rust"
+ --> $DIR/parent-source-spans.rs:16:16
+ |
+LL | three!($a, $b);
+ | ^^
+...
+LL | two!("yay", "rust");
+ | ------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: first parent: "yay"
+ --> $DIR/parent-source-spans.rs:42:5
+ |
+LL | two!("yay", "rust");
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: second parent: "rust"
+ --> $DIR/parent-source-spans.rs:42:5
+ |
+LL | two!("yay", "rust");
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: first source: "yay"
+ --> $DIR/parent-source-spans.rs:42:5
+ |
+LL | two!("yay", "rust");
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: second source: "rust"
+ --> $DIR/parent-source-spans.rs:42:5
+ |
+LL | two!("yay", "rust");
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: first final: "hip"
+ --> $DIR/parent-source-spans.rs:48:12
+ |
+LL | three!("hip", "hop");
+ | ^^^^^
+
+error: second final: "hop"
+ --> $DIR/parent-source-spans.rs:48:19
+ |
+LL | three!("hip", "hop");
+ | ^^^^^
+
+error: first source: "hip"
+ --> $DIR/parent-source-spans.rs:48:12
+ |
+LL | three!("hip", "hop");
+ | ^^^^^
+
+error: second source: "hop"
+ --> $DIR/parent-source-spans.rs:48:19
+ |
+LL | three!("hip", "hop");
+ | ^^^^^
+
+error[E0425]: cannot find value `ok` in this scope
+ --> $DIR/parent-source-spans.rs:29:5
+ |
+LL | parent_source_spans!($($tokens)*);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
+...
+LL | one!("hello", "world");
+ | ---------------------- in this macro invocation
+ |
+ ::: $SRC_DIR/core/src/result.rs:LL:COL
+ |
+LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
+ | -- similarly named tuple variant `Ok` defined here
+ |
+ = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0425]: cannot find value `ok` in this scope
+ --> $DIR/parent-source-spans.rs:29:5
+ |
+LL | parent_source_spans!($($tokens)*);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
+...
+LL | two!("yay", "rust");
+ | ------------------- in this macro invocation
+ |
+ ::: $SRC_DIR/core/src/result.rs:LL:COL
+ |
+LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
+ | -- similarly named tuple variant `Ok` defined here
+ |
+ = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0425]: cannot find value `ok` in this scope
+ --> $DIR/parent-source-spans.rs:29:5
+ |
+LL | parent_source_spans!($($tokens)*);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: a tuple variant with a similar name exists: `Ok`
+...
+LL | three!("hip", "hop");
+ | -------------------- in this macro invocation
+ |
+ ::: $SRC_DIR/core/src/result.rs:LL:COL
+ |
+LL | Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
+ | -- similarly named tuple variant `Ok` defined here
+ |
+ = note: this error originates in the macro `parent_source_spans` which comes from the expansion of the macro `three` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/pretty-print-tts.rs b/src/test/ui/proc-macro/pretty-print-tts.rs
new file mode 100644
index 000000000..ffe2a7415
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-tts.rs
@@ -0,0 +1,20 @@
+// check-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![feature(rustc_attrs)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+// Tests the pretty-printing behavior of various (unparsed) tokens
+print_bang_consume!({
+ #![rustc_dummy]
+ let a = "hello".len();
+ matches!(a, 5);
+});
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/pretty-print-tts.stdout b/src/test/ui/proc-macro/pretty-print-tts.stdout
new file mode 100644
index 000000000..f52e97a86
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-tts.stdout
@@ -0,0 +1,102 @@
+PRINT-BANG INPUT (DISPLAY): { #! [rustc_dummy] let a = "hello".len() ; matches! (a, 5) ; }
+PRINT-BANG INPUT (DEBUG): TokenStream [
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/pretty-print-tts.rs:15:5: 15:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/pretty-print-tts.rs:15:6: 15:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "rustc_dummy",
+ span: $DIR/pretty-print-tts.rs:15:8: 15:19 (#0),
+ },
+ ],
+ span: $DIR/pretty-print-tts.rs:15:7: 15:20 (#0),
+ },
+ Ident {
+ ident: "let",
+ span: $DIR/pretty-print-tts.rs:16:5: 16:8 (#0),
+ },
+ Ident {
+ ident: "a",
+ span: $DIR/pretty-print-tts.rs:16:9: 16:10 (#0),
+ },
+ Punct {
+ ch: '=',
+ spacing: Alone,
+ span: $DIR/pretty-print-tts.rs:16:11: 16:12 (#0),
+ },
+ Literal {
+ kind: Str,
+ symbol: "hello",
+ suffix: None,
+ span: $DIR/pretty-print-tts.rs:16:13: 16:20 (#0),
+ },
+ Punct {
+ ch: '.',
+ spacing: Alone,
+ span: $DIR/pretty-print-tts.rs:16:20: 16:21 (#0),
+ },
+ Ident {
+ ident: "len",
+ span: $DIR/pretty-print-tts.rs:16:21: 16:24 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/pretty-print-tts.rs:16:24: 16:26 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/pretty-print-tts.rs:16:26: 16:27 (#0),
+ },
+ Ident {
+ ident: "matches",
+ span: $DIR/pretty-print-tts.rs:17:5: 17:12 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/pretty-print-tts.rs:17:12: 17:13 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "a",
+ span: $DIR/pretty-print-tts.rs:17:14: 17:15 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/pretty-print-tts.rs:17:15: 17:16 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "5",
+ suffix: None,
+ span: $DIR/pretty-print-tts.rs:17:17: 17:18 (#0),
+ },
+ ],
+ span: $DIR/pretty-print-tts.rs:17:13: 17:19 (#0),
+ },
+ Punct {
+ ch: ';',
+ spacing: Alone,
+ span: $DIR/pretty-print-tts.rs:17:19: 17:20 (#0),
+ },
+ ],
+ span: $DIR/pretty-print-tts.rs:14:21: 18:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs
new file mode 100644
index 000000000..8d96381b9
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-attributes.rs
@@ -0,0 +1,22 @@
+// aux-build:derive-b.rs
+
+#[macro_use]
+extern crate derive_b;
+
+#[B] //~ ERROR `B` is ambiguous
+ //~| WARN derive helper attribute is used before it is introduced
+ //~| WARN this was previously accepted
+#[C] //~ ERROR cannot find attribute `C` in this scope
+#[B(D)] //~ ERROR `B` is ambiguous
+ //~| WARN derive helper attribute is used before it is introduced
+ //~| WARN this was previously accepted
+#[B(E = "foo")] //~ ERROR `B` is ambiguous
+ //~| WARN derive helper attribute is used before it is introduced
+ //~| WARN this was previously accepted
+#[B(arbitrary tokens)] //~ ERROR `B` is ambiguous
+ //~| WARN derive helper attribute is used before it is introduced
+ //~| WARN this was previously accepted
+#[derive(B)]
+struct B;
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr
new file mode 100644
index 000000000..b66e4575e
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr
@@ -0,0 +1,130 @@
+error: cannot find attribute `C` in this scope
+ --> $DIR/proc-macro-attributes.rs:9:3
+ |
+LL | #[C]
+ | ^ help: a derive helper attribute with a similar name exists: `B`
+
+error[E0659]: `B` is ambiguous
+ --> $DIR/proc-macro-attributes.rs:6:3
+ |
+LL | #[B]
+ | ^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a derive helper attribute
+note: `B` could refer to the derive helper attribute defined here
+ --> $DIR/proc-macro-attributes.rs:19:10
+ |
+LL | #[derive(B)]
+ | ^
+note: `B` could also refer to the derive macro imported here
+ --> $DIR/proc-macro-attributes.rs:3:1
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^
+
+error[E0659]: `B` is ambiguous
+ --> $DIR/proc-macro-attributes.rs:10:3
+ |
+LL | #[B(D)]
+ | ^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a derive helper attribute
+note: `B` could refer to the derive helper attribute defined here
+ --> $DIR/proc-macro-attributes.rs:19:10
+ |
+LL | #[derive(B)]
+ | ^
+note: `B` could also refer to the derive macro imported here
+ --> $DIR/proc-macro-attributes.rs:3:1
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^
+
+error[E0659]: `B` is ambiguous
+ --> $DIR/proc-macro-attributes.rs:13:3
+ |
+LL | #[B(E = "foo")]
+ | ^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a derive helper attribute
+note: `B` could refer to the derive helper attribute defined here
+ --> $DIR/proc-macro-attributes.rs:19:10
+ |
+LL | #[derive(B)]
+ | ^
+note: `B` could also refer to the derive macro imported here
+ --> $DIR/proc-macro-attributes.rs:3:1
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^
+
+error[E0659]: `B` is ambiguous
+ --> $DIR/proc-macro-attributes.rs:16:3
+ |
+LL | #[B(arbitrary tokens)]
+ | ^ ambiguous name
+ |
+ = note: ambiguous because of a name conflict with a derive helper attribute
+note: `B` could refer to the derive helper attribute defined here
+ --> $DIR/proc-macro-attributes.rs:19:10
+ |
+LL | #[derive(B)]
+ | ^
+note: `B` could also refer to the derive macro imported here
+ --> $DIR/proc-macro-attributes.rs:3:1
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^
+
+warning: derive helper attribute is used before it is introduced
+ --> $DIR/proc-macro-attributes.rs:6:3
+ |
+LL | #[B]
+ | ^
+...
+LL | #[derive(B)]
+ | - the attribute is introduced here
+ |
+ = note: `#[warn(legacy_derive_helpers)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+
+warning: derive helper attribute is used before it is introduced
+ --> $DIR/proc-macro-attributes.rs:10:3
+ |
+LL | #[B(D)]
+ | ^
+...
+LL | #[derive(B)]
+ | - the attribute is introduced here
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+
+warning: derive helper attribute is used before it is introduced
+ --> $DIR/proc-macro-attributes.rs:13:3
+ |
+LL | #[B(E = "foo")]
+ | ^
+...
+LL | #[derive(B)]
+ | - the attribute is introduced here
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+
+warning: derive helper attribute is used before it is introduced
+ --> $DIR/proc-macro-attributes.rs:16:3
+ |
+LL | #[B(arbitrary tokens)]
+ | ^
+...
+LL | #[derive(B)]
+ | - the attribute is introduced here
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+
+error: aborting due to 5 previous errors; 4 warnings emitted
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs b/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs
new file mode 100644
index 000000000..f1144a4a5
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-deprecated-attr.rs
@@ -0,0 +1,16 @@
+// check-pass
+// force-host
+// no-prefer-dynamic
+
+#![deny(deprecated)]
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+#[deprecated(since = "1.0.0", note = "test")]
+pub fn test_compile_without_warning_with_deprecated(_: TokenStream) -> TokenStream {
+ TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs
new file mode 100644
index 000000000..e2cf4e739
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-gates.rs
@@ -0,0 +1,53 @@
+// aux-build:test-macros.rs
+// gate-test-proc_macro_hygiene
+
+#![feature(stmt_expr_attributes)]
+
+#[macro_use]
+extern crate test_macros;
+
+fn _test_inner() {
+ #![empty_attr] //~ ERROR: inner macro attributes are unstable
+}
+
+mod _test2_inner {
+ #![empty_attr] //~ ERROR: inner macro attributes are unstable
+}
+
+#[empty_attr = "y"] //~ ERROR: key-value macro attributes are not supported
+fn _test3() {}
+
+fn attrs() {
+ // Statement, item
+ #[empty_attr] // OK
+ struct S;
+
+ // Statement, macro
+ #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements
+ println!();
+
+ // Statement, semi
+ #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements
+ S;
+
+ // Statement, local
+ #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements
+ let _x = 2;
+
+ // Expr
+ let _x = #[identity_attr] 2; //~ ERROR: custom attributes cannot be applied to expressions
+
+ // Opt expr
+ let _x = [#[identity_attr] 2]; //~ ERROR: custom attributes cannot be applied to expressions
+
+ // Expr macro
+ let _x = #[identity_attr] println!();
+ //~^ ERROR: custom attributes cannot be applied to expressions
+}
+
+fn test_case() {
+ #![test] //~ ERROR inner macro attributes are unstable
+ //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr
new file mode 100644
index 000000000..118213a17
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-gates.stderr
@@ -0,0 +1,91 @@
+error[E0658]: inner macro attributes are unstable
+ --> $DIR/proc-macro-gates.rs:10:8
+ |
+LL | #![empty_attr]
+ | ^^^^^^^^^^
+ |
+ = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
+ = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
+
+error[E0658]: inner macro attributes are unstable
+ --> $DIR/proc-macro-gates.rs:14:8
+ |
+LL | #![empty_attr]
+ | ^^^^^^^^^^
+ |
+ = note: see issue #54726 <https://github.com/rust-lang/rust/issues/54726> for more information
+ = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
+
+error: key-value macro attributes are not supported
+ --> $DIR/proc-macro-gates.rs:17:1
+ |
+LL | #[empty_attr = "y"]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error[E0658]: custom attributes cannot be applied to statements
+ --> $DIR/proc-macro-gates.rs:26:5
+ |
+LL | #[empty_attr]
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to statements
+ --> $DIR/proc-macro-gates.rs:30:5
+ |
+LL | #[empty_attr]
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to statements
+ --> $DIR/proc-macro-gates.rs:34:5
+ |
+LL | #[empty_attr]
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to expressions
+ --> $DIR/proc-macro-gates.rs:38:14
+ |
+LL | let _x = #[identity_attr] 2;
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to expressions
+ --> $DIR/proc-macro-gates.rs:41:15
+ |
+LL | let _x = [#[identity_attr] 2];
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error[E0658]: custom attributes cannot be applied to expressions
+ --> $DIR/proc-macro-gates.rs:44:14
+ |
+LL | let _x = #[identity_attr] println!();
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information
+ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
+
+error: inner macro attributes are unstable
+ --> $DIR/proc-macro-gates.rs:49:8
+ |
+LL | #![test]
+ | ^^^^
+ |
+ = note: `#[deny(soft_unstable)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/proc-macro/proc-macro-gates2.rs b/src/test/ui/proc-macro/proc-macro-gates2.rs
new file mode 100644
index 000000000..38fbd4733
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-gates2.rs
@@ -0,0 +1,24 @@
+// aux-build:test-macros.rs
+
+#![feature(stmt_expr_attributes)]
+
+#[macro_use]
+extern crate test_macros;
+
+// NB. these errors aren't the best errors right now, but they're definitely
+// intended to be errors. Somehow using a custom attribute in these positions
+// should either require a feature gate or not be allowed on stable.
+
+fn _test6<#[empty_attr] T>() {}
+//~^ ERROR: expected non-macro attribute, found attribute macro
+
+fn _test7() {
+ match 1 {
+ #[empty_attr] //~ ERROR: expected non-macro attribute, found attribute macro
+ 0 => {}
+ _ => {}
+ }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/proc-macro/proc-macro-gates2.stderr b/src/test/ui/proc-macro/proc-macro-gates2.stderr
new file mode 100644
index 000000000..64df34e7c
--- /dev/null
+++ b/src/test/ui/proc-macro/proc-macro-gates2.stderr
@@ -0,0 +1,14 @@
+error: expected non-macro attribute, found attribute macro `empty_attr`
+ --> $DIR/proc-macro-gates2.rs:12:13
+ |
+LL | fn _test6<#[empty_attr] T>() {}
+ | ^^^^^^^^^^ not a non-macro attribute
+
+error: expected non-macro attribute, found attribute macro `empty_attr`
+ --> $DIR/proc-macro-gates2.rs:17:11
+ |
+LL | #[empty_attr]
+ | ^^^^^^^^^^ not a non-macro attribute
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/pub-at-crate-root.rs b/src/test/ui/proc-macro/pub-at-crate-root.rs
new file mode 100644
index 000000000..54cf333a4
--- /dev/null
+++ b/src/test/ui/proc-macro/pub-at-crate-root.rs
@@ -0,0 +1,22 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+pub mod a { //~ `proc-macro` crate types currently cannot export any items
+ use proc_macro::TokenStream;
+
+ #[proc_macro_derive(B)]
+ pub fn bar(a: TokenStream) -> TokenStream {
+ //~^ ERROR: must currently reside in the root of the crate
+ a
+ }
+}
+
+#[proc_macro_derive(B)]
+fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream {
+//~^ ERROR: functions tagged with `#[proc_macro_derive]` must be `pub`
+ a
+}
diff --git a/src/test/ui/proc-macro/pub-at-crate-root.stderr b/src/test/ui/proc-macro/pub-at-crate-root.stderr
new file mode 100644
index 000000000..2e7536a0c
--- /dev/null
+++ b/src/test/ui/proc-macro/pub-at-crate-root.stderr
@@ -0,0 +1,20 @@
+error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
+ --> $DIR/pub-at-crate-root.rs:8:1
+ |
+LL | pub mod a {
+ | ^^^^^^^^^
+
+error: functions tagged with `#[proc_macro_derive]` must currently reside in the root of the crate
+ --> $DIR/pub-at-crate-root.rs:12:5
+ |
+LL | pub fn bar(a: TokenStream) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: functions tagged with `#[proc_macro_derive]` must be `pub`
+ --> $DIR/pub-at-crate-root.rs:19:1
+ |
+LL | fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/proc-macro/quote-debug.rs b/src/test/ui/proc-macro/quote-debug.rs
new file mode 100644
index 000000000..e0304a014
--- /dev/null
+++ b/src/test/ui/proc-macro/quote-debug.rs
@@ -0,0 +1,18 @@
+// check-pass
+// force-host
+// no-prefer-dynamic
+// compile-flags: -Z unpretty=expanded
+//
+// This file is not actually used as a proc-macro - instead,
+// it's just used to show the output of the `quote!` macro
+
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+fn main() {
+ proc_macro::quote! {
+ let hello = "world";
+ }
+}
diff --git a/src/test/ui/proc-macro/quote-debug.stdout b/src/test/ui/proc-macro/quote-debug.stdout
new file mode 100644
index 000000000..d2cc5c6e2
--- /dev/null
+++ b/src/test/ui/proc-macro/quote-debug.stdout
@@ -0,0 +1,47 @@
+#![feature(prelude_import)]
+#![no_std]
+// check-pass
+// force-host
+// no-prefer-dynamic
+// compile-flags: -Z unpretty=expanded
+//
+// This file is not actually used as a proc-macro - instead,
+// it's just used to show the output of the `quote!` macro
+
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+extern crate proc_macro;
+
+fn main() {
+ [crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("let",
+ crate::Span::recover_proc_macro_span(0)))),
+ crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("hello",
+ crate::Span::recover_proc_macro_span(1)))),
+ crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('=',
+ crate::Spacing::Alone))),
+ crate::TokenStream::from(crate::TokenTree::Literal({
+ let mut iter =
+ "\"world\"".parse::<crate::TokenStream>().unwrap().into_iter();
+ if let (Some(crate::TokenTree::Literal(mut lit)), None) =
+ (iter.next(), iter.next()) {
+ lit.set_span(crate::Span::recover_proc_macro_span(2));
+ lit
+ } else {
+ ::core::panicking::panic("internal error: entered unreachable code")
+ }
+ })),
+ crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new(';',
+ crate::Spacing::Alone)))].iter().cloned().collect::<crate::TokenStream>()
+}
+const _: () =
+ {
+ extern crate proc_macro;
+ #[rustc_proc_macro_decls]
+ #[allow(deprecated)]
+ static _DECLS: &[proc_macro::bridge::client::ProcMacro] = &[];
+ };
diff --git a/src/test/ui/proc-macro/raw-ident.rs b/src/test/ui/proc-macro/raw-ident.rs
new file mode 100644
index 000000000..03cb45714
--- /dev/null
+++ b/src/test/ui/proc-macro/raw-ident.rs
@@ -0,0 +1,16 @@
+// aux-build:raw-ident.rs
+
+#[macro_use] extern crate raw_ident;
+
+fn main() {
+ make_struct!(fn);
+ make_struct!(Foo);
+ make_struct!(await);
+
+ r#fn;
+ r#Foo;
+ Foo;
+ r#await;
+
+ make_bad_struct!(S); //~ ERROR expected one of
+}
diff --git a/src/test/ui/proc-macro/raw-ident.stderr b/src/test/ui/proc-macro/raw-ident.stderr
new file mode 100644
index 000000000..905a5f946
--- /dev/null
+++ b/src/test/ui/proc-macro/raw-ident.stderr
@@ -0,0 +1,10 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `S`
+ --> $DIR/raw-ident.rs:15:5
+ |
+LL | make_bad_struct!(S);
+ | ^^^^^^^^^^^^^^^^^^^ expected one of 8 possible tokens
+ |
+ = note: this error originates in the macro `make_bad_struct` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/reserved-macro-names.rs b/src/test/ui/proc-macro/reserved-macro-names.rs
new file mode 100644
index 000000000..c5e71a87d
--- /dev/null
+++ b/src/test/ui/proc-macro/reserved-macro-names.rs
@@ -0,0 +1,19 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
+ //~^ ERROR name `cfg` is reserved in attribute namespace
+ input
+}
+
+#[proc_macro_attribute]
+pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+ //~^ ERROR name `cfg_attr` is reserved in attribute namespace
+ input
+}
diff --git a/src/test/ui/proc-macro/reserved-macro-names.stderr b/src/test/ui/proc-macro/reserved-macro-names.stderr
new file mode 100644
index 000000000..39bdd03be
--- /dev/null
+++ b/src/test/ui/proc-macro/reserved-macro-names.stderr
@@ -0,0 +1,14 @@
+error: name `cfg` is reserved in attribute namespace
+ --> $DIR/reserved-macro-names.rs:10:8
+ |
+LL | pub fn cfg(_: TokenStream, input: TokenStream) -> TokenStream {
+ | ^^^
+
+error: name `cfg_attr` is reserved in attribute namespace
+ --> $DIR/reserved-macro-names.rs:16:8
+ |
+LL | pub fn cfg_attr(_: TokenStream, input: TokenStream) -> TokenStream {
+ | ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs
new file mode 100644
index 000000000..ad8a5bbb0
--- /dev/null
+++ b/src/test/ui/proc-macro/resolve-error.rs
@@ -0,0 +1,62 @@
+// aux-build:derive-foo.rs
+// aux-build:derive-clona.rs
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate derive_foo;
+#[macro_use]
+extern crate derive_clona;
+extern crate test_macros;
+
+use test_macros::empty as bang_proc_macro;
+use test_macros::empty_attr as attr_proc_macro;
+
+macro_rules! FooWithLongNam {
+ () => {}
+}
+
+macro_rules! attr_proc_mac {
+ () => {}
+}
+
+#[derive(FooWithLongNan)]
+//~^ ERROR cannot find
+//~| ERROR cannot find
+struct Foo;
+
+// Interpreted as an unstable custom attribute
+#[attr_proc_macra] //~ ERROR cannot find attribute `attr_proc_macra` in this scope
+struct Bar;
+
+// Interpreted as an unstable custom attribute
+#[FooWithLongNan] //~ ERROR cannot find attribute `FooWithLongNan` in this scope
+struct Asdf;
+
+#[derive(Dlone)]
+//~^ ERROR cannot find
+//~| ERROR cannot find
+struct A;
+
+#[derive(Dlona)]
+//~^ ERROR cannot find
+//~| ERROR cannot find
+struct B;
+
+#[derive(attr_proc_macra)]
+//~^ ERROR cannot find
+//~| ERROR cannot find
+struct C;
+
+fn main() {
+ FooWithLongNama!();
+ //~^ ERROR cannot find
+
+ attr_proc_macra!();
+ //~^ ERROR cannot find
+
+ Dlona!();
+ //~^ ERROR cannot find
+
+ bang_proc_macrp!();
+ //~^ ERROR cannot find
+}
diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr
new file mode 100644
index 000000000..a534b9d53
--- /dev/null
+++ b/src/test/ui/proc-macro/resolve-error.stderr
@@ -0,0 +1,132 @@
+error: cannot find macro `bang_proc_macrp` in this scope
+ --> $DIR/resolve-error.rs:60:5
+ |
+LL | bang_proc_macrp!();
+ | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `bang_proc_macro`
+ |
+ ::: $DIR/auxiliary/test-macros.rs:15:1
+ |
+LL | pub fn empty(_: TokenStream) -> TokenStream {
+ | ------------------------------------------- similarly named macro `bang_proc_macro` defined here
+
+error: cannot find macro `Dlona` in this scope
+ --> $DIR/resolve-error.rs:57:5
+ |
+LL | Dlona!();
+ | ^^^^^
+
+error: cannot find macro `attr_proc_macra` in this scope
+ --> $DIR/resolve-error.rs:54:5
+ |
+LL | macro_rules! attr_proc_mac {
+ | -------------------------- similarly named macro `attr_proc_mac` defined here
+...
+LL | attr_proc_macra!();
+ | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `attr_proc_mac`
+
+error: cannot find macro `FooWithLongNama` in this scope
+ --> $DIR/resolve-error.rs:51:5
+ |
+LL | macro_rules! FooWithLongNam {
+ | --------------------------- similarly named macro `FooWithLongNam` defined here
+...
+LL | FooWithLongNama!();
+ | ^^^^^^^^^^^^^^^ help: a macro with a similar name exists: `FooWithLongNam`
+
+error: cannot find derive macro `attr_proc_macra` in this scope
+ --> $DIR/resolve-error.rs:45:10
+ |
+LL | #[derive(attr_proc_macra)]
+ | ^^^^^^^^^^^^^^^
+
+error: cannot find derive macro `attr_proc_macra` in this scope
+ --> $DIR/resolve-error.rs:45:10
+ |
+LL | #[derive(attr_proc_macra)]
+ | ^^^^^^^^^^^^^^^
+
+error: cannot find derive macro `Dlona` in this scope
+ --> $DIR/resolve-error.rs:40:10
+ |
+LL | #[derive(Dlona)]
+ | ^^^^^ help: a derive macro with a similar name exists: `Clona`
+ |
+ ::: $DIR/auxiliary/derive-clona.rs:11:1
+ |
+LL | pub fn derive_clonea(input: TokenStream) -> TokenStream {
+ | ------------------------------------------------------- similarly named derive macro `Clona` defined here
+
+error: cannot find derive macro `Dlona` in this scope
+ --> $DIR/resolve-error.rs:40:10
+ |
+LL | #[derive(Dlona)]
+ | ^^^^^ help: a derive macro with a similar name exists: `Clona`
+ |
+ ::: $DIR/auxiliary/derive-clona.rs:11:1
+ |
+LL | pub fn derive_clonea(input: TokenStream) -> TokenStream {
+ | ------------------------------------------------------- similarly named derive macro `Clona` defined here
+
+error: cannot find derive macro `Dlone` in this scope
+ --> $DIR/resolve-error.rs:35:10
+ |
+LL | #[derive(Dlone)]
+ | ^^^^^ help: a derive macro with a similar name exists: `Clone`
+ |
+ ::: $SRC_DIR/core/src/clone.rs:LL:COL
+ |
+LL | pub macro Clone($item:item) {
+ | --------------- similarly named derive macro `Clone` defined here
+
+error: cannot find derive macro `Dlone` in this scope
+ --> $DIR/resolve-error.rs:35:10
+ |
+LL | #[derive(Dlone)]
+ | ^^^^^ help: a derive macro with a similar name exists: `Clone`
+ |
+ ::: $SRC_DIR/core/src/clone.rs:LL:COL
+ |
+LL | pub macro Clone($item:item) {
+ | --------------- similarly named derive macro `Clone` defined here
+
+error: cannot find attribute `FooWithLongNan` in this scope
+ --> $DIR/resolve-error.rs:32:3
+ |
+LL | #[FooWithLongNan]
+ | ^^^^^^^^^^^^^^
+
+error: cannot find attribute `attr_proc_macra` in this scope
+ --> $DIR/resolve-error.rs:28:3
+ |
+LL | #[attr_proc_macra]
+ | ^^^^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `attr_proc_macro`
+ |
+ ::: $DIR/auxiliary/test-macros.rs:20:1
+ |
+LL | pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream {
+ | ---------------------------------------------------------------- similarly named attribute macro `attr_proc_macro` defined here
+
+error: cannot find derive macro `FooWithLongNan` in this scope
+ --> $DIR/resolve-error.rs:22:10
+ |
+LL | #[derive(FooWithLongNan)]
+ | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName`
+ |
+ ::: $DIR/auxiliary/derive-foo.rs:11:1
+ |
+LL | pub fn derive_foo(input: TokenStream) -> TokenStream {
+ | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here
+
+error: cannot find derive macro `FooWithLongNan` in this scope
+ --> $DIR/resolve-error.rs:22:10
+ |
+LL | #[derive(FooWithLongNan)]
+ | ^^^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FooWithLongName`
+ |
+ ::: $DIR/auxiliary/derive-foo.rs:11:1
+ |
+LL | pub fn derive_foo(input: TokenStream) -> TokenStream {
+ | ---------------------------------------------------- similarly named derive macro `FooWithLongName` defined here
+
+error: aborting due to 14 previous errors
+
diff --git a/src/test/ui/proc-macro/resolved-located-at.rs b/src/test/ui/proc-macro/resolved-located-at.rs
new file mode 100644
index 000000000..b785573f2
--- /dev/null
+++ b/src/test/ui/proc-macro/resolved-located-at.rs
@@ -0,0 +1,10 @@
+// aux-build:resolved-located-at.rs
+
+#[macro_use]
+extern crate resolved_located_at;
+
+fn main() {
+ resolve_located_at!(a b)
+ //~^ ERROR expected error
+ //~| ERROR mismatched types
+}
diff --git a/src/test/ui/proc-macro/resolved-located-at.stderr b/src/test/ui/proc-macro/resolved-located-at.stderr
new file mode 100644
index 000000000..422820e9d
--- /dev/null
+++ b/src/test/ui/proc-macro/resolved-located-at.stderr
@@ -0,0 +1,21 @@
+error: expected error
+ --> $DIR/resolved-located-at.rs:7:25
+ |
+LL | resolve_located_at!(a b)
+ | ^
+ |
+ = note: this error originates in the macro `resolve_located_at` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+ --> $DIR/resolved-located-at.rs:7:27
+ |
+LL | fn main() {
+ | - expected `()` because of default return type
+LL | resolve_located_at!(a b)
+ | ^ expected `()`, found struct `S`
+ |
+ = note: this error originates in the macro `resolve_located_at` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/shadow.rs b/src/test/ui/proc-macro/shadow.rs
new file mode 100644
index 000000000..61959594c
--- /dev/null
+++ b/src/test/ui/proc-macro/shadow.rs
@@ -0,0 +1,8 @@
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+#[macro_use]
+extern crate test_macros; //~ ERROR the name `test_macros` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/shadow.stderr b/src/test/ui/proc-macro/shadow.stderr
new file mode 100644
index 000000000..e7d95cc83
--- /dev/null
+++ b/src/test/ui/proc-macro/shadow.stderr
@@ -0,0 +1,14 @@
+error[E0259]: the name `test_macros` is defined multiple times
+ --> $DIR/shadow.rs:6:1
+ |
+LL | extern crate test_macros;
+ | ------------------------- previous import of the extern crate `test_macros` here
+LL | #[macro_use]
+LL | extern crate test_macros;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ `test_macros` reimported here
+ |
+ = note: `test_macros` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/proc-macro/signature.rs b/src/test/ui/proc-macro/signature.rs
new file mode 100644
index 000000000..230223825
--- /dev/null
+++ b/src/test/ui/proc-macro/signature.rs
@@ -0,0 +1,13 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![allow(warnings)]
+
+extern crate proc_macro;
+
+#[proc_macro_derive(A)]
+pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
+ //~^ ERROR: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn
+ loop {}
+}
diff --git a/src/test/ui/proc-macro/signature.stderr b/src/test/ui/proc-macro/signature.stderr
new file mode 100644
index 000000000..a6bd98ddb
--- /dev/null
+++ b/src/test/ui/proc-macro/signature.stderr
@@ -0,0 +1,20 @@
+error[E0277]: expected a `Fn<(proc_macro::TokenStream,)>` closure, found `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+ --> $DIR/signature.rs:10:1
+ |
+LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
+LL | |
+LL | | loop {}
+LL | | }
+ | |_^ call the function in a closure: `|| unsafe { /* code */ }`
+ |
+ = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+ = note: unsafe function cannot be called generically without an unsafe block
+note: required by a bound in `ProcMacro::custom_derive`
+ --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
+ |
+LL | expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ProcMacro::custom_derive`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/proc-macro/smoke.rs b/src/test/ui/proc-macro/smoke.rs
new file mode 100644
index 000000000..04625559b
--- /dev/null
+++ b/src/test/ui/proc-macro/smoke.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+#![allow(unused_must_use)]
+#![allow(path_statements)]
+// aux-build:derive-a.rs
+
+#[macro_use]
+extern crate derive_a;
+
+#[derive(Debug, PartialEq, A, Eq, Copy, Clone)]
+struct A;
+
+fn main() {
+ A;
+ assert_eq!(A, A);
+ A.clone();
+ let a = A;
+ let _c = a;
+ let _d = a;
+}
diff --git a/src/test/ui/proc-macro/span-absolute-posititions.rs b/src/test/ui/proc-macro/span-absolute-posititions.rs
new file mode 100644
index 000000000..6d70fe611
--- /dev/null
+++ b/src/test/ui/proc-macro/span-absolute-posititions.rs
@@ -0,0 +1,24 @@
+// aux-build:assert-span-pos.rs
+// ignore-tidy-tab
+extern crate assert_span_pos;
+
+assert_span_pos::assert_span_pos!(5, 35);
+
+// Test space indentation
+ assert_span_pos::assert_span_pos!(8, 39);
+// Test tab indentation
+ assert_span_pos::assert_span_pos!(10, 36);
+
+// Two tests to ensure the promise of the docs that the column is the number
+// of UTF-8 bytes instead of some other number like number of code points.
+
+// Test that multi byte UTF-8 characters indeed count as multiple bytes
+/*🌈*/assert_span_pos::assert_span_pos!(16, 40);
+// Test with a complete grapheme cluster
+/*🏳️‍🌈*/assert_span_pos::assert_span_pos!(18, 43);
+
+// Test that the macro actually emits an error on a mismatch:
+assert_span_pos::assert_span_pos!(0, 35); //~ ERROR line/column mismatch: (0, 35) != (21, 35)
+assert_span_pos::assert_span_pos!(22, 0); //~ ERROR line/column mismatch: (22, 0) != (22, 35)
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/span-absolute-posititions.stderr b/src/test/ui/proc-macro/span-absolute-posititions.stderr
new file mode 100644
index 000000000..6aca44a6b
--- /dev/null
+++ b/src/test/ui/proc-macro/span-absolute-posititions.stderr
@@ -0,0 +1,14 @@
+error: line/column mismatch: (0, 35) != (21, 35)
+ --> $DIR/span-absolute-posititions.rs:21:35
+ |
+LL | assert_span_pos::assert_span_pos!(0, 35);
+ | ^
+
+error: line/column mismatch: (22, 0) != (22, 35)
+ --> $DIR/span-absolute-posititions.rs:22:35
+ |
+LL | assert_span_pos::assert_span_pos!(22, 0);
+ | ^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/span-api-tests.rs b/src/test/ui/proc-macro/span-api-tests.rs
new file mode 100644
index 000000000..914ad54ed
--- /dev/null
+++ b/src/test/ui/proc-macro/span-api-tests.rs
@@ -0,0 +1,61 @@
+// run-pass
+// ignore-pretty
+// aux-build:span-api-tests.rs
+// aux-build:span-test-macros.rs
+
+#[macro_use]
+extern crate span_test_macros;
+
+extern crate span_api_tests;
+
+// FIXME(69775): Investigate `assert_fake_source_file`.
+
+use span_api_tests::{reemit, assert_source_file, macro_stringify};
+
+macro_rules! say_hello {
+ ($macname:ident) => ( $macname! { "Hello, world!" })
+}
+
+assert_source_file! { "Hello, world!" }
+
+say_hello! { assert_source_file }
+
+reemit_legacy! {
+ assert_source_file! { "Hello, world!" }
+}
+
+say_hello_extern! { assert_source_file }
+
+reemit! {
+ assert_source_file! { "Hello, world!" }
+}
+
+fn main() {
+ let s = macro_stringify!(Hello, world!);
+ assert_eq!(s, "Hello, world!");
+ assert_eq!(macro_stringify!(Hello, world!), "Hello, world!");
+ assert_eq!(reemit_legacy!(macro_stringify!(Hello, world!)), "Hello, world!");
+ reemit_legacy!(assert_eq!(macro_stringify!(Hello, world!), "Hello, world!"));
+ // reemit change the span to be that of the call site
+ assert_eq!(
+ reemit!(macro_stringify!(Hello, world!)),
+ "reemit!(macro_stringify!(Hello, world!))"
+ );
+ let r = "reemit!(assert_eq!(macro_stringify!(Hello, world!), r))";
+ reemit!(assert_eq!(macro_stringify!(Hello, world!), r));
+
+ assert_eq!(macro_stringify!(
+ Hello,
+ world!
+ ), "Hello,\n world!");
+
+ assert_eq!(macro_stringify!(Hello, /*world */ !), "Hello, /*world */ !");
+ assert_eq!(macro_stringify!(
+ Hello,
+ // comment
+ world!
+ ), "Hello,\n // comment\n world!");
+
+ assert_eq!(say_hello! { macro_stringify }, "\"Hello, world!\"");
+ assert_eq!(say_hello_extern! { macro_stringify }, "\"Hello, world!\"");
+}
diff --git a/src/test/ui/proc-macro/span-from-proc-macro.rs b/src/test/ui/proc-macro/span-from-proc-macro.rs
new file mode 100644
index 000000000..ecff2d725
--- /dev/null
+++ b/src/test/ui/proc-macro/span-from-proc-macro.rs
@@ -0,0 +1,17 @@
+// aux-build:custom-quote.rs
+// aux-build:span-from-proc-macro.rs
+// compile-flags: -Z macro-backtrace
+
+#[macro_use]
+extern crate span_from_proc_macro;
+
+#[error_from_attribute] //~ ERROR cannot find type `MissingType`
+struct ShouldBeRemoved;
+
+#[derive(ErrorFromDerive)] //~ ERROR cannot find type `OtherMissingType`
+struct Kept;
+
+fn main() {
+ error_from_bang!(); //~ ERROR mismatched types
+ other_error_from_bang!(); //~ ERROR cannot find value `my_ident`
+}
diff --git a/src/test/ui/proc-macro/span-from-proc-macro.stderr b/src/test/ui/proc-macro/span-from-proc-macro.stderr
new file mode 100644
index 000000000..7beed505a
--- /dev/null
+++ b/src/test/ui/proc-macro/span-from-proc-macro.stderr
@@ -0,0 +1,62 @@
+error[E0412]: cannot find type `MissingType` in this scope
+ --> $DIR/auxiliary/span-from-proc-macro.rs:37:20
+ |
+LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream {
+ | ----------------------------------------------------------------------------------- in this expansion of `#[error_from_attribute]`
+...
+LL | field: MissingType
+ | ^^^^^^^^^^^ not found in this scope
+ |
+ ::: $DIR/span-from-proc-macro.rs:8:1
+ |
+LL | #[error_from_attribute]
+ | ----------------------- in this procedural macro expansion
+
+error[E0412]: cannot find type `OtherMissingType` in this scope
+ --> $DIR/auxiliary/span-from-proc-macro.rs:46:21
+ |
+LL | pub fn error_from_derive(_input: TokenStream) -> TokenStream {
+ | ------------------------------------------------------------ in this expansion of `#[derive(ErrorFromDerive)]`
+...
+LL | Variant(OtherMissingType)
+ | ^^^^^^^^^^^^^^^^ not found in this scope
+ |
+ ::: $DIR/span-from-proc-macro.rs:11:10
+ |
+LL | #[derive(ErrorFromDerive)]
+ | --------------- in this derive macro expansion
+
+error[E0425]: cannot find value `my_ident` in this scope
+ --> $DIR/auxiliary/span-from-proc-macro.rs:29:9
+ |
+LL | pub fn other_error_from_bang(_input: TokenStream) -> TokenStream {
+ | ---------------------------------------------------------------- in this expansion of `other_error_from_bang!`
+LL | custom_quote::custom_quote! {
+LL | my_ident
+ | ^^^^^^^^ not found in this scope
+ |
+ ::: $DIR/span-from-proc-macro.rs:16:5
+ |
+LL | other_error_from_bang!();
+ | ------------------------ in this macro invocation
+
+error[E0308]: mismatched types
+ --> $DIR/auxiliary/span-from-proc-macro.rs:16:36
+ |
+LL | let bang_error: bool = 25;
+ | ---- ^^ expected `bool`, found integer
+ | |
+ | expected due to this
+...
+LL | pub fn error_from_bang(_input: TokenStream) -> TokenStream {
+ | ---------------------------------------------------------- in this expansion of `error_from_bang!`
+ |
+ ::: $DIR/span-from-proc-macro.rs:15:5
+ |
+LL | error_from_bang!();
+ | ------------------ in this macro invocation
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0308, E0412, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs
new file mode 100644
index 000000000..0c7358655
--- /dev/null
+++ b/src/test/ui/proc-macro/span-preservation.rs
@@ -0,0 +1,57 @@
+// For each of these, we should get the appropriate type mismatch error message,
+// and the function should be echoed.
+
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+#[recollect_attr]
+fn a() {
+ let x: usize = "hello"; //~ ERROR mismatched types
+}
+
+#[recollect_attr]
+fn b(x: Option<isize>) -> usize {
+ match x {
+ Some(x) => { return x }, //~ ERROR mismatched types
+ None => 10
+ }
+}
+
+#[recollect_attr]
+fn c() {
+ struct Foo {
+ a: usize
+ }
+
+ struct Bar {
+ a: usize,
+ b: usize
+ }
+
+ let x = Foo { a: 10isize }; //~ ERROR mismatched types
+ let y = Foo { a: 10, b: 10isize }; //~ ERROR has no field named `b`
+}
+
+#[recollect_attr]
+extern "C" fn bar() {
+ 0 //~ ERROR mismatched types
+}
+
+#[recollect_attr]
+extern "C" fn baz() {
+ 0 //~ ERROR mismatched types
+}
+
+#[recollect_attr]
+extern "Rust" fn rust_abi() {
+ 0 //~ ERROR mismatched types
+}
+
+#[recollect_attr]
+extern "\x43" fn c_abi_escaped() {
+ 0 //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
new file mode 100644
index 000000000..66c68be2f
--- /dev/null
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -0,0 +1,72 @@
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:11:20
+ |
+LL | let x: usize = "hello";
+ | ----- ^^^^^^^ expected `usize`, found `&str`
+ | |
+ | expected due to this
+
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:17:29
+ |
+LL | fn b(x: Option<isize>) -> usize {
+ | ----- expected `usize` because of return type
+LL | match x {
+LL | Some(x) => { return x },
+ | ^ expected `usize`, found `isize`
+ |
+help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
+ |
+LL | Some(x) => { return x.try_into().unwrap() },
+ | ++++++++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:33:22
+ |
+LL | let x = Foo { a: 10isize };
+ | ^^^^^^^ expected `usize`, found `isize`
+
+error[E0560]: struct `Foo` has no field named `b`
+ --> $DIR/span-preservation.rs:34:26
+ |
+LL | let y = Foo { a: 10, b: 10isize };
+ | ^ `Foo` does not have this field
+ |
+ = note: available fields are: `a`
+
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:39:5
+ |
+LL | extern "C" fn bar() {
+ | - help: try adding a return type: `-> i32`
+LL | 0
+ | ^ expected `()`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:44:5
+ |
+LL | extern "C" fn baz() {
+ | - help: try adding a return type: `-> i32`
+LL | 0
+ | ^ expected `()`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:49:5
+ |
+LL | extern "Rust" fn rust_abi() {
+ | - help: try adding a return type: `-> i32`
+LL | 0
+ | ^ expected `()`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:54:5
+ |
+LL | extern "\x43" fn c_abi_escaped() {
+ | - help: try adding a return type: `-> i32`
+LL | 0
+ | ^ expected `()`, found integer
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0308, E0560.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/proc-macro/struct-field-macro.rs b/src/test/ui/proc-macro/struct-field-macro.rs
new file mode 100644
index 000000000..460f4d9f7
--- /dev/null
+++ b/src/test/ui/proc-macro/struct-field-macro.rs
@@ -0,0 +1,18 @@
+// run-pass
+
+#![allow(dead_code)]
+// aux-build:derive-nothing.rs
+
+#[macro_use]
+extern crate derive_nothing;
+
+macro_rules! int {
+ () => { i32 }
+}
+
+#[derive(Nothing)]
+struct S {
+ x: int!(),
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/subspan.rs b/src/test/ui/proc-macro/subspan.rs
new file mode 100644
index 000000000..a4187f9e7
--- /dev/null
+++ b/src/test/ui/proc-macro/subspan.rs
@@ -0,0 +1,26 @@
+// aux-build:subspan.rs
+
+extern crate subspan;
+
+use subspan::subspan;
+
+// This one emits no error.
+subspan!("");
+
+// Exactly one 'hi'.
+subspan!("hi"); //~ ERROR found 'hi's
+
+// Now two, back to back.
+subspan!("hihi"); //~ ERROR found 'hi's
+
+// Now three, back to back.
+subspan!("hihihi"); //~ ERROR found 'hi's
+
+// Now several, with spacing.
+subspan!("why I hide? hi!"); //~ ERROR found 'hi's
+subspan!("hey, hi, hidy, hidy, hi hi"); //~ ERROR found 'hi's
+subspan!("this is a hi, and this is another hi"); //~ ERROR found 'hi's
+subspan!("how are you this evening"); //~ ERROR found 'hi's
+subspan!("this is highly eradic"); //~ ERROR found 'hi's
+
+fn main() { }
diff --git a/src/test/ui/proc-macro/subspan.stderr b/src/test/ui/proc-macro/subspan.stderr
new file mode 100644
index 000000000..b5dacba0e
--- /dev/null
+++ b/src/test/ui/proc-macro/subspan.stderr
@@ -0,0 +1,106 @@
+error: found 'hi's
+ --> $DIR/subspan.rs:11:1
+ |
+LL | subspan!("hi");
+ | ^^^^^^^^^^^^^^
+ |
+note: here
+ --> $DIR/subspan.rs:11:11
+ |
+LL | subspan!("hi");
+ | ^^
+ = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: found 'hi's
+ --> $DIR/subspan.rs:14:1
+ |
+LL | subspan!("hihi");
+ | ^^^^^^^^^^^^^^^^
+ |
+note: here
+ --> $DIR/subspan.rs:14:11
+ |
+LL | subspan!("hihi");
+ | ^^^^
+ = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: found 'hi's
+ --> $DIR/subspan.rs:17:1
+ |
+LL | subspan!("hihihi");
+ | ^^^^^^^^^^^^^^^^^^
+ |
+note: here
+ --> $DIR/subspan.rs:17:11
+ |
+LL | subspan!("hihihi");
+ | ^^^^^^
+ = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: found 'hi's
+ --> $DIR/subspan.rs:20:1
+ |
+LL | subspan!("why I hide? hi!");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: here
+ --> $DIR/subspan.rs:20:17
+ |
+LL | subspan!("why I hide? hi!");
+ | ^^ ^^
+ = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: found 'hi's
+ --> $DIR/subspan.rs:21:1
+ |
+LL | subspan!("hey, hi, hidy, hidy, hi hi");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: here
+ --> $DIR/subspan.rs:21:16
+ |
+LL | subspan!("hey, hi, hidy, hidy, hi hi");
+ | ^^ ^^ ^^ ^^ ^^
+ = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: found 'hi's
+ --> $DIR/subspan.rs:22:1
+ |
+LL | subspan!("this is a hi, and this is another hi");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: here
+ --> $DIR/subspan.rs:22:12
+ |
+LL | subspan!("this is a hi, and this is another hi");
+ | ^^ ^^ ^^ ^^
+ = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: found 'hi's
+ --> $DIR/subspan.rs:23:1
+ |
+LL | subspan!("how are you this evening");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: here
+ --> $DIR/subspan.rs:23:24
+ |
+LL | subspan!("how are you this evening");
+ | ^^
+ = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: found 'hi's
+ --> $DIR/subspan.rs:24:1
+ |
+LL | subspan!("this is highly eradic");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: here
+ --> $DIR/subspan.rs:24:12
+ |
+LL | subspan!("this is highly eradic");
+ | ^^ ^^
+ = note: this error originates in the macro `subspan` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/proc-macro/test.rs b/src/test/ui/proc-macro/test.rs
new file mode 100644
index 000000000..c96aa7317
--- /dev/null
+++ b/src/test/ui/proc-macro/test.rs
@@ -0,0 +1,12 @@
+// check-pass
+// aux-build:api/mod.rs
+
+//! This is for everything that *would* be a #[test] inside of libproc_macro,
+//! except for the fact that proc_macro objects are not capable of existing
+//! inside of an ordinary Rust test execution, only inside a macro.
+
+extern crate proc_macro_api_tests;
+
+proc_macro_api_tests::run!();
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/three-equals.rs b/src/test/ui/proc-macro/three-equals.rs
new file mode 100644
index 000000000..21b137c99
--- /dev/null
+++ b/src/test/ui/proc-macro/three-equals.rs
@@ -0,0 +1,25 @@
+// aux-build:three-equals.rs
+
+extern crate three_equals;
+
+use three_equals::three_equals;
+
+fn main() {
+ // This one is okay.
+ three_equals!(===);
+
+ // Need exactly three equals.
+ three_equals!(==); //~ ERROR found 2 equal signs, need exactly 3
+
+ // Need exactly three equals.
+ three_equals!(=====); //~ ERROR expected EOF
+
+ // Only equals accepted.
+ three_equals!(abc); //~ ERROR expected `=`
+
+ // Only equals accepted.
+ three_equals!(!!); //~ ERROR expected `=`
+
+ // Only three characters expected.
+ three_equals!(===a); //~ ERROR expected EOF
+}
diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr
new file mode 100644
index 000000000..1ce5e02bd
--- /dev/null
+++ b/src/test/ui/proc-macro/three-equals.stderr
@@ -0,0 +1,49 @@
+error: found 2 equal signs, need exactly 3
+ --> $DIR/three-equals.rs:12:5
+ |
+LL | three_equals!(==);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: input must be: `===`
+ = note: this error originates in the macro `three_equals` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected EOF, found `=`.
+ --> $DIR/three-equals.rs:15:21
+ |
+LL | three_equals!(=====);
+ | ^^
+ |
+note: last good input was here
+ --> $DIR/three-equals.rs:15:21
+ |
+LL | three_equals!(=====);
+ | ^^
+ = help: input must be: `===`
+
+error: expected `=`, found `abc`.
+ --> $DIR/three-equals.rs:18:19
+ |
+LL | three_equals!(abc);
+ | ^^^
+
+error: expected `=`, found `!`.
+ --> $DIR/three-equals.rs:21:19
+ |
+LL | three_equals!(!!);
+ | ^
+
+error: expected EOF, found `a`.
+ --> $DIR/three-equals.rs:24:22
+ |
+LL | three_equals!(===a);
+ | ^
+ |
+note: last good input was here
+ --> $DIR/three-equals.rs:24:21
+ |
+LL | three_equals!(===a);
+ | ^
+ = help: input must be: `===`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/proc-macro/trailing-plus.rs b/src/test/ui/proc-macro/trailing-plus.rs
new file mode 100644
index 000000000..4f61de47d
--- /dev/null
+++ b/src/test/ui/proc-macro/trailing-plus.rs
@@ -0,0 +1,14 @@
+// check-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate test_macros;
+
+#[test_macros::print_attr]
+fn foo<T>() where T: Copy + {
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/trailing-plus.stdout b/src/test/ui/proc-macro/trailing-plus.stdout
new file mode 100644
index 000000000..b90057cd6
--- /dev/null
+++ b/src/test/ui/proc-macro/trailing-plus.stdout
@@ -0,0 +1,57 @@
+PRINT-ATTR INPUT (DISPLAY): fn foo < T > () where T : Copy + {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "fn",
+ span: $DIR/trailing-plus.rs:11:1: 11:3 (#0),
+ },
+ Ident {
+ ident: "foo",
+ span: $DIR/trailing-plus.rs:11:4: 11:7 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/trailing-plus.rs:11:7: 11:8 (#0),
+ },
+ Ident {
+ ident: "T",
+ span: $DIR/trailing-plus.rs:11:8: 11:9 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/trailing-plus.rs:11:9: 11:10 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [],
+ span: $DIR/trailing-plus.rs:11:10: 11:12 (#0),
+ },
+ Ident {
+ ident: "where",
+ span: $DIR/trailing-plus.rs:11:13: 11:18 (#0),
+ },
+ Ident {
+ ident: "T",
+ span: $DIR/trailing-plus.rs:11:19: 11:20 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/trailing-plus.rs:11:20: 11:21 (#0),
+ },
+ Ident {
+ ident: "Copy",
+ span: $DIR/trailing-plus.rs:11:22: 11:26 (#0),
+ },
+ Punct {
+ ch: '+',
+ spacing: Alone,
+ span: $DIR/trailing-plus.rs:11:27: 11:28 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/trailing-plus.rs:11:29: 12:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/trait-fn-args-2015.rs b/src/test/ui/proc-macro/trait-fn-args-2015.rs
new file mode 100644
index 000000000..6b8df78a0
--- /dev/null
+++ b/src/test/ui/proc-macro/trait-fn-args-2015.rs
@@ -0,0 +1,16 @@
+// Unnamed arguments in trait functions can be passed through proc macros on 2015 edition.
+
+// check-pass
+// aux-build:test-macros.rs
+
+#![allow(anonymous_parameters)]
+
+#[macro_use]
+extern crate test_macros;
+
+trait Tr {
+ #[identity_attr]
+ fn method(u8);
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/two-crate-types-1.rs b/src/test/ui/proc-macro/two-crate-types-1.rs
new file mode 100644
index 000000000..80bfd357f
--- /dev/null
+++ b/src/test/ui/proc-macro/two-crate-types-1.rs
@@ -0,0 +1,7 @@
+// error-pattern: cannot mix `proc-macro` crate type with others
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![crate_type = "rlib"]
diff --git a/src/test/ui/proc-macro/two-crate-types-1.stderr b/src/test/ui/proc-macro/two-crate-types-1.stderr
new file mode 100644
index 000000000..deaba1cf2
--- /dev/null
+++ b/src/test/ui/proc-macro/two-crate-types-1.stderr
@@ -0,0 +1,4 @@
+error: cannot mix `proc-macro` crate type with others
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/two-crate-types-2.rs b/src/test/ui/proc-macro/two-crate-types-2.rs
new file mode 100644
index 000000000..39cbf7d3b
--- /dev/null
+++ b/src/test/ui/proc-macro/two-crate-types-2.rs
@@ -0,0 +1,3 @@
+// error-pattern: cannot mix `proc-macro` crate type with others
+// compile-flags: --crate-type rlib --crate-type proc-macro
+// force-host
diff --git a/src/test/ui/proc-macro/two-crate-types-2.stderr b/src/test/ui/proc-macro/two-crate-types-2.stderr
new file mode 100644
index 000000000..deaba1cf2
--- /dev/null
+++ b/src/test/ui/proc-macro/two-crate-types-2.stderr
@@ -0,0 +1,4 @@
+error: cannot mix `proc-macro` crate type with others
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/unsafe-foreign-mod.rs b/src/test/ui/proc-macro/unsafe-foreign-mod.rs
new file mode 100644
index 000000000..7bdfa93c2
--- /dev/null
+++ b/src/test/ui/proc-macro/unsafe-foreign-mod.rs
@@ -0,0 +1,14 @@
+// run-pass
+// aux-build:macro-only-syntax.rs
+
+extern crate macro_only_syntax;
+
+#[macro_only_syntax::expect_unsafe_foreign_mod]
+unsafe extern {
+ type T;
+}
+
+#[macro_only_syntax::expect_unsafe_extern_cpp_mod]
+unsafe extern "C++" {}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/unsafe-mod.rs b/src/test/ui/proc-macro/unsafe-mod.rs
new file mode 100644
index 000000000..8ff6e352c
--- /dev/null
+++ b/src/test/ui/proc-macro/unsafe-mod.rs
@@ -0,0 +1,13 @@
+// run-pass
+// aux-build:macro-only-syntax.rs
+
+#![feature(proc_macro_hygiene)]
+
+extern crate macro_only_syntax;
+
+#[macro_only_syntax::expect_unsafe_mod]
+unsafe mod m {
+ pub unsafe mod inner;
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/visibility-path.rs b/src/test/ui/proc-macro/visibility-path.rs
new file mode 100644
index 000000000..a73430db2
--- /dev/null
+++ b/src/test/ui/proc-macro/visibility-path.rs
@@ -0,0 +1,25 @@
+// Proc macro defined with `pub(path)` doesn't ICEs due to resolving the `path` (issue #68921).
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub(self) fn outer(input: TokenStream) -> TokenStream {
+ //~^ ERROR functions tagged with `#[proc_macro]` must be `pub`
+ input
+}
+
+mod m {
+ use proc_macro::*;
+
+ #[proc_macro]
+ pub(super) fn inner(input: TokenStream) -> TokenStream {
+ //~^ ERROR functions tagged with `#[proc_macro]` must currently reside in the root
+ input
+ }
+}
diff --git a/src/test/ui/proc-macro/visibility-path.stderr b/src/test/ui/proc-macro/visibility-path.stderr
new file mode 100644
index 000000000..1a73cc196
--- /dev/null
+++ b/src/test/ui/proc-macro/visibility-path.stderr
@@ -0,0 +1,14 @@
+error: functions tagged with `#[proc_macro]` must be `pub`
+ --> $DIR/visibility-path.rs:12:1
+ |
+LL | pub(self) fn outer(input: TokenStream) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: functions tagged with `#[proc_macro]` must currently reside in the root of the crate
+ --> $DIR/visibility-path.rs:21:5
+ |
+LL | pub(super) fn inner(input: TokenStream) -> TokenStream {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/weird-braces.rs b/src/test/ui/proc-macro/weird-braces.rs
new file mode 100644
index 000000000..b9a7e08f9
--- /dev/null
+++ b/src/test/ui/proc-macro/weird-braces.rs
@@ -0,0 +1,23 @@
+// aux-build:test-macros.rs
+// check-pass
+// compile-flags: -Z span-debug
+
+#![feature(custom_inner_attributes)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+extern crate test_macros;
+use test_macros::{print_target_and_args};
+
+struct Foo<const V: bool>;
+trait Bar<const V: bool> {}
+
+#[print_target_and_args(first_outer)]
+#[print_target_and_args(second_outer)]
+impl Bar<{1 > 0}> for Foo<{true}> {
+ #![print_target_and_args(first_inner)]
+ #![print_target_and_args(second_inner)]
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/weird-braces.stdout b/src/test/ui/proc-macro/weird-braces.stdout
new file mode 100644
index 000000000..9bf562217
--- /dev/null
+++ b/src/test/ui/proc-macro/weird-braces.stdout
@@ -0,0 +1,524 @@
+PRINT-ATTR_ARGS INPUT (DISPLAY): first_outer
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "first_outer",
+ span: $DIR/weird-braces.rs:16:25: 16:36 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second_outer)] impl Bar < { 1 > 0 } > for Foo <
+{ true } >
+{
+ #! [print_target_and_args(first_inner)] #!
+ [print_target_and_args(second_inner)]
+}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:17:1: 17:2 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/weird-braces.rs:17:3: 17:24 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "second_outer",
+ span: $DIR/weird-braces.rs:17:25: 17:37 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:17:24: 17:38 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:17:2: 17:39 (#0),
+ },
+ Ident {
+ ident: "impl",
+ span: $DIR/weird-braces.rs:18:1: 18:5 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/weird-braces.rs:18:6: 18:9 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:9: 18:10 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/weird-braces.rs:18:11: 18:12 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:13: 18:14 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/weird-braces.rs:18:15: 18:16 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:10: 18:17 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:17: 18:18 (#0),
+ },
+ Ident {
+ ident: "for",
+ span: $DIR/weird-braces.rs:18:19: 18:22 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/weird-braces.rs:18:23: 18:26 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:26: 18:27 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "true",
+ span: $DIR/weird-braces.rs:18:28: 18:32 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:27: 18:33 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:33: 18:34 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/weird-braces.rs:19:5: 19:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:19:6: 19:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/weird-braces.rs:19:8: 19:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "first_inner",
+ span: $DIR/weird-braces.rs:19:30: 19:41 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:19:29: 19:42 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:19:7: 19:43 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/weird-braces.rs:20:5: 20:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:20:6: 20:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/weird-braces.rs:20:8: 20:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "second_inner",
+ span: $DIR/weird-braces.rs:20:30: 20:42 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:20:29: 20:43 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:20:7: 20:44 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:35: 21:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): second_outer
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "second_outer",
+ span: $DIR/weird-braces.rs:17:25: 17:37 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } >
+{
+ #! [print_target_and_args(first_inner)] #!
+ [print_target_and_args(second_inner)]
+}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "impl",
+ span: $DIR/weird-braces.rs:18:1: 18:5 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/weird-braces.rs:18:6: 18:9 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:9: 18:10 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/weird-braces.rs:18:11: 18:12 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:13: 18:14 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/weird-braces.rs:18:15: 18:16 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:10: 18:17 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:17: 18:18 (#0),
+ },
+ Ident {
+ ident: "for",
+ span: $DIR/weird-braces.rs:18:19: 18:22 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/weird-braces.rs:18:23: 18:26 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:26: 18:27 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "true",
+ span: $DIR/weird-braces.rs:18:28: 18:32 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:27: 18:33 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:33: 18:34 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/weird-braces.rs:19:5: 19:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:19:6: 19:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/weird-braces.rs:19:8: 19:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "first_inner",
+ span: $DIR/weird-braces.rs:19:30: 19:41 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:19:29: 19:42 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:19:7: 19:43 (#0),
+ },
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/weird-braces.rs:20:5: 20:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:20:6: 20:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/weird-braces.rs:20:8: 20:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "second_inner",
+ span: $DIR/weird-braces.rs:20:30: 20:42 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:20:29: 20:43 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:20:7: 20:44 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:35: 21:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): first_inner
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "first_inner",
+ span: $DIR/weird-braces.rs:19:30: 19:41 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } >
+{ #! [print_target_and_args(second_inner)] }
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "impl",
+ span: $DIR/weird-braces.rs:18:1: 18:5 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/weird-braces.rs:18:6: 18:9 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:9: 18:10 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/weird-braces.rs:18:11: 18:12 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:13: 18:14 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/weird-braces.rs:18:15: 18:16 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:10: 18:17 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:17: 18:18 (#0),
+ },
+ Ident {
+ ident: "for",
+ span: $DIR/weird-braces.rs:18:19: 18:22 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/weird-braces.rs:18:23: 18:26 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:26: 18:27 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "true",
+ span: $DIR/weird-braces.rs:18:28: 18:32 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:27: 18:33 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:33: 18:34 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Joint,
+ span: $DIR/weird-braces.rs:20:5: 20:6 (#0),
+ },
+ Punct {
+ ch: '!',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:20:6: 20:7 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "print_target_and_args",
+ span: $DIR/weird-braces.rs:20:8: 20:29 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "second_inner",
+ span: $DIR/weird-braces.rs:20:30: 20:42 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:20:29: 20:43 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:20:7: 20:44 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:35: 21:2 (#0),
+ },
+]
+PRINT-ATTR_ARGS INPUT (DISPLAY): second_inner
+PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "second_inner",
+ span: $DIR/weird-braces.rs:20:30: 20:42 (#0),
+ },
+]
+PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > {}
+PRINT-ATTR INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "impl",
+ span: $DIR/weird-braces.rs:18:1: 18:5 (#0),
+ },
+ Ident {
+ ident: "Bar",
+ span: $DIR/weird-braces.rs:18:6: 18:9 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:9: 18:10 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Literal {
+ kind: Integer,
+ symbol: "1",
+ suffix: None,
+ span: $DIR/weird-braces.rs:18:11: 18:12 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:13: 18:14 (#0),
+ },
+ Literal {
+ kind: Integer,
+ symbol: "0",
+ suffix: None,
+ span: $DIR/weird-braces.rs:18:15: 18:16 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:10: 18:17 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:17: 18:18 (#0),
+ },
+ Ident {
+ ident: "for",
+ span: $DIR/weird-braces.rs:18:19: 18:22 (#0),
+ },
+ Ident {
+ ident: "Foo",
+ span: $DIR/weird-braces.rs:18:23: 18:26 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:26: 18:27 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "true",
+ span: $DIR/weird-braces.rs:18:28: 18:32 (#0),
+ },
+ ],
+ span: $DIR/weird-braces.rs:18:27: 18:33 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/weird-braces.rs:18:33: 18:34 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [],
+ span: $DIR/weird-braces.rs:18:35: 21:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/weird-hygiene.rs b/src/test/ui/proc-macro/weird-hygiene.rs
new file mode 100644
index 000000000..7ba3f98a7
--- /dev/null
+++ b/src/test/ui/proc-macro/weird-hygiene.rs
@@ -0,0 +1,46 @@
+// aux-build:weird-hygiene.rs
+
+#![feature(stmt_expr_attributes)]
+#![feature(proc_macro_hygiene)]
+
+extern crate weird_hygiene;
+use weird_hygiene::*;
+
+macro_rules! other {
+ ($tokens:expr) => {
+ macro_rules! call_it {
+ ($outer_ident:ident) => {
+ macro_rules! inner {
+ () => {
+ $outer_ident;
+ }
+ }
+ }
+ }
+
+ #[derive(WeirdDerive)]
+ enum MyEnum {
+ Value = (stringify!($tokens + hidden_ident), 1).1 //~ ERROR cannot find
+ }
+
+ inner!();
+ }
+}
+
+macro_rules! invoke_it {
+ ($token:expr) => {
+ #[recollect_attr] {
+ $token;
+ hidden_ident //~ ERROR cannot find
+ }
+ }
+}
+
+fn main() {
+ // `other` and `invoke_it` are both macro_rules! macros,
+ // so it should be impossible for them to ever see `hidden_ident`,
+ // even if they invoke a proc macro.
+ let hidden_ident = "Hello1";
+ other!(50);
+ invoke_it!(25);
+}
diff --git a/src/test/ui/proc-macro/weird-hygiene.stderr b/src/test/ui/proc-macro/weird-hygiene.stderr
new file mode 100644
index 000000000..256e68e89
--- /dev/null
+++ b/src/test/ui/proc-macro/weird-hygiene.stderr
@@ -0,0 +1,25 @@
+error[E0425]: cannot find value `hidden_ident` in this scope
+ --> $DIR/weird-hygiene.rs:23:43
+ |
+LL | Value = (stringify!($tokens + hidden_ident), 1).1
+ | ^^^^^^^^^^^^ not found in this scope
+...
+LL | other!(50);
+ | ---------- in this macro invocation
+ |
+ = note: this error originates in the macro `inner` which comes from the expansion of the macro `other` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0425]: cannot find value `hidden_ident` in this scope
+ --> $DIR/weird-hygiene.rs:34:13
+ |
+LL | hidden_ident
+ | ^^^^^^^^^^^^ not found in this scope
+...
+LL | invoke_it!(25);
+ | -------------- in this macro invocation
+ |
+ = note: this error originates in the macro `invoke_it` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.