about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-03-12 21:36:47 +0000
committerbors <bors@rust-lang.org>2023-03-12 21:36:47 +0000
commite65ad6f5d0c97d4b20e68c9c81c3f35225563fa6 (patch)
tree6b8e49c5129ac6c769e72e32f3feadb74708f763
parentf19db28361c74195e7baffeca23915549c0805ca (diff)
parent1c7048d7852937099320091900e25061fde5479f (diff)
downloadrust-e65ad6f5d0c97d4b20e68c9c81c3f35225563fa6.tar.gz
rust-e65ad6f5d0c97d4b20e68c9c81c3f35225563fa6.zip
Auto merge of #10453 - Jarcho:test_utils, r=dswij
Add utility macros to help with writing tests.

Adds two utility macros to help with testing:
* `external` expands to it's argument tokens, but makes them appear to come from an external macro. Helps make tests for `in_external_macro` much more readable.
* `inline_macros` is an attribute macro which allows the use of a pseudo `inline!` macro which expands to it's argument tokens, but makes them appear to be from a crate-local macro expansion. This removes the need to write `macro_rules` boilerplate when testing how lints interact with macros.

---

`external`'s usage is simple. `external!(struct Foo { x: u32});` will make the struct appear as though it came from an external macro. Individual tokens can be escaped if needed. `external!($x + 0 / 10)` will make everything except `x` appear as though it came from an external macro. Can also use `$literal` and `$(tokens...)` as well.

---

`inline_macros` is more complicated due to compiler constraints. Given:
```rust
#[inline_macros]
fn foo() {
    inline!(5 + 5 / 10);
}
```
`inline!(5 + 5 / 10)` will be replace with a call to a generated macro which expands to the contained tokens.

Tokens can be escaped by prefixing them with `$`:
```rust
#[inline_macros]
fn foo() {
    let x = 5;
    inline!($x + 5 / $10);
}
```
This will pass `x` as an `ident` argument and `10` as a `literal` argument.

Token sequences can also be passed with `$(...)`:
```rust
#[inline_macros]
fn foo() {
    let mut x = 5;
    inline!(if $(x >= 5) {
        $x = 5;
    });
}
```
This will pass `x >= 5` as `tt` arguments, and `x` as an `ident` argument.

---

Not 100% sure `inline_macros` is actually worth having. It does make the tests a little easier to read once you're used to it and it becomes more useful once there are multiple macro tests. The verbosity of declaring single use macros starts to hurt at that point.

changelog: None
-rw-r--r--tests/ui/almost_complete_range.fixed49
-rw-r--r--tests/ui/almost_complete_range.rs49
-rw-r--r--tests/ui/almost_complete_range.stderr93
-rw-r--r--tests/ui/as_conversions.rs13
-rw-r--r--tests/ui/as_conversions.stderr6
-rw-r--r--tests/ui/auxiliary/doc_unsafe_macros.rs16
-rw-r--r--tests/ui/auxiliary/implicit_hasher_macros.rs6
-rw-r--r--tests/ui/auxiliary/macro_rules.rs141
-rw-r--r--tests/ui/auxiliary/macro_use_helper.rs2
-rw-r--r--tests/ui/auxiliary/proc_macro_with_span.rs32
-rw-r--r--tests/ui/auxiliary/proc_macros.rs474
-rw-r--r--tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs2
-rw-r--r--tests/ui/crashes/ice-10148.rs6
-rw-r--r--tests/ui/default_numeric_fallback_f64.fixed17
-rw-r--r--tests/ui/default_numeric_fallback_f64.rs17
-rw-r--r--tests/ui/default_numeric_fallback_f64.stderr11
-rw-r--r--tests/ui/default_numeric_fallback_i32.fixed17
-rw-r--r--tests/ui/default_numeric_fallback_i32.rs17
-rw-r--r--tests/ui/default_numeric_fallback_i32.stderr11
-rw-r--r--tests/ui/default_trait_access.fixed6
-rw-r--r--tests/ui/default_trait_access.rs6
-rw-r--r--tests/ui/deref_addrof.fixed24
-rw-r--r--tests/ui/deref_addrof.rs24
-rw-r--r--tests/ui/deref_addrof.stderr38
-rw-r--r--tests/ui/deref_addrof_macro.rs15
-rw-r--r--tests/ui/doc_unsafe.rs12
-rw-r--r--tests/ui/empty_loop.rs15
-rw-r--r--tests/ui/equatable_if_let.fixed16
-rw-r--r--tests/ui/equatable_if_let.rs16
-rw-r--r--tests/ui/equatable_if_let.stderr32
-rw-r--r--tests/ui/field_reassign_with_default.rs36
-rw-r--r--tests/ui/field_reassign_with_default.stderr44
-rw-r--r--tests/ui/implicit_hasher.rs25
-rw-r--r--tests/ui/implicit_hasher.stderr55
-rw-r--r--tests/ui/inconsistent_struct_constructor.fixed21
-rw-r--r--tests/ui/inconsistent_struct_constructor.rs21
-rw-r--r--tests/ui/inconsistent_struct_constructor.stderr4
-rw-r--r--tests/ui/large_enum_variant.rs13
-rw-r--r--tests/ui/macro_use_imports.fixed4
-rw-r--r--tests/ui/macro_use_imports.rs2
-rw-r--r--tests/ui/macro_use_imports.stderr2
-rw-r--r--tests/ui/macro_use_imports_expect.rs2
-rw-r--r--tests/ui/manual_rem_euclid.fixed24
-rw-r--r--tests/ui/manual_rem_euclid.rs24
-rw-r--r--tests/ui/manual_rem_euclid.stderr17
-rw-r--r--tests/ui/mem_replace_macro.rs23
-rw-r--r--tests/ui/mem_replace_macro.stderr11
-rw-r--r--tests/ui/missing_const_for_fn/cant_be_const.rs6
-rw-r--r--tests/ui/missing_doc.rs6
-rw-r--r--tests/ui/missing_doc_impl.rs6
-rw-r--r--tests/ui/mistyped_literal_suffix.fixed6
-rw-r--r--tests/ui/mistyped_literal_suffix.rs6
-rw-r--r--tests/ui/multiple_unsafe_ops_per_block.rs11
-rw-r--r--tests/ui/multiple_unsafe_ops_per_block.stderr18
-rw-r--r--tests/ui/must_use_unit.fixed11
-rw-r--r--tests/ui/must_use_unit.rs11
-rw-r--r--tests/ui/mut_mut.rs11
-rw-r--r--tests/ui/mut_mut.stderr25
-rw-r--r--tests/ui/needless_late_init.fixed36
-rw-r--r--tests/ui/needless_late_init.rs36
-rw-r--r--tests/ui/needless_late_init.stderr32
-rw-r--r--tests/ui/needless_lifetimes.fixed37
-rw-r--r--tests/ui/needless_lifetimes.rs37
-rw-r--r--tests/ui/needless_lifetimes.stderr15
-rw-r--r--tests/ui/option_env_unwrap.rs24
-rw-r--r--tests/ui/option_env_unwrap.stderr42
-rw-r--r--tests/ui/ptr_as_ptr.fixed16
-rw-r--r--tests/ui/ptr_as_ptr.rs16
-rw-r--r--tests/ui/ptr_as_ptr.stderr25
-rw-r--r--tests/ui/single_match_else.rs6
-rw-r--r--tests/ui/string_add.rs11
-rw-r--r--tests/ui/toplevel_ref_arg.fixed24
-rw-r--r--tests/ui/toplevel_ref_arg.rs24
-rw-r--r--tests/ui/toplevel_ref_arg.stderr21
-rw-r--r--tests/ui/toplevel_ref_arg_non_rustfix.rs22
-rw-r--r--tests/ui/toplevel_ref_arg_non_rustfix.stderr7
-rw-r--r--tests/ui/try_err.fixed65
-rw-r--r--tests/ui/try_err.rs65
-rw-r--r--tests/ui/try_err.stderr32
-rw-r--r--tests/ui/uninlined_format_args.fixed6
-rw-r--r--tests/ui/uninlined_format_args.rs6
-rw-r--r--tests/ui/unit_arg.rs6
-rw-r--r--tests/ui/unnecessary_lazy_eval.fixed6
-rw-r--r--tests/ui/unnecessary_lazy_eval.rs6
-rw-r--r--tests/ui/unnecessary_unsafety_doc.rs12
-rw-r--r--tests/ui/unnecessary_unsafety_doc.stderr2
86 files changed, 1173 insertions, 1092 deletions
diff --git a/tests/ui/almost_complete_range.fixed b/tests/ui/almost_complete_range.fixed
index 6046addf719..a4bf7fe18d5 100644
--- a/tests/ui/almost_complete_range.fixed
+++ b/tests/ui/almost_complete_range.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 // edition:2018
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![feature(exclusive_range_pattern)]
 #![feature(stmt_expr_attributes)]
@@ -9,33 +9,10 @@
 #![allow(clippy::needless_parens_on_range_literals)]
 #![allow(clippy::double_parens)]
 
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! a {
-    () => {
-        'a'
-    };
-}
-macro_rules! A {
-    () => {
-        'A'
-    };
-}
-macro_rules! zero {
-    () => {
-        '0'
-    };
-}
-
-macro_rules! b {
-    () => {
-        let _ = 'a'..='z';
-        let _ = 'A'..='Z';
-        let _ = '0'..='9';
-    };
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
     #[rustfmt::skip]
     {
@@ -56,9 +33,9 @@ fn main() {
     let _ = b'B'..b'Z';
     let _ = b'1'..b'9';
 
-    let _ = a!()..='z';
-    let _ = A!()..='Z';
-    let _ = zero!()..='9';
+    let _ = inline!('a')..='z';
+    let _ = inline!('A')..='Z';
+    let _ = inline!('0')..='9';
 
     let _ = match 0u8 {
         b'a'..=b'z' if true => 1,
@@ -80,8 +57,16 @@ fn main() {
         _ => 7,
     };
 
-    almost_complete_range!();
-    b!();
+    external!(
+        let _ = 'a'..'z';
+        let _ = 'A'..'Z';
+        let _ = '0'..'9';
+    );
+    inline!(
+        let _ = 'a'..='z';
+        let _ = 'A'..='Z';
+        let _ = '0'..='9';
+    );
 }
 
 #[clippy::msrv = "1.25"]
diff --git a/tests/ui/almost_complete_range.rs b/tests/ui/almost_complete_range.rs
index ae7e07ab872..8237c3a1361 100644
--- a/tests/ui/almost_complete_range.rs
+++ b/tests/ui/almost_complete_range.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 // edition:2018
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![feature(exclusive_range_pattern)]
 #![feature(stmt_expr_attributes)]
@@ -9,33 +9,10 @@
 #![allow(clippy::needless_parens_on_range_literals)]
 #![allow(clippy::double_parens)]
 
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! a {
-    () => {
-        'a'
-    };
-}
-macro_rules! A {
-    () => {
-        'A'
-    };
-}
-macro_rules! zero {
-    () => {
-        '0'
-    };
-}
-
-macro_rules! b {
-    () => {
-        let _ = 'a'..'z';
-        let _ = 'A'..'Z';
-        let _ = '0'..'9';
-    };
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
     #[rustfmt::skip]
     {
@@ -56,9 +33,9 @@ fn main() {
     let _ = b'B'..b'Z';
     let _ = b'1'..b'9';
 
-    let _ = a!()..'z';
-    let _ = A!()..'Z';
-    let _ = zero!()..'9';
+    let _ = inline!('a')..'z';
+    let _ = inline!('A')..'Z';
+    let _ = inline!('0')..'9';
 
     let _ = match 0u8 {
         b'a'..b'z' if true => 1,
@@ -80,8 +57,16 @@ fn main() {
         _ => 7,
     };
 
-    almost_complete_range!();
-    b!();
+    external!(
+        let _ = 'a'..'z';
+        let _ = 'A'..'Z';
+        let _ = '0'..'9';
+    );
+    inline!(
+        let _ = 'a'..'z';
+        let _ = 'A'..'Z';
+        let _ = '0'..'9';
+    );
 }
 
 #[clippy::msrv = "1.25"]
diff --git a/tests/ui/almost_complete_range.stderr b/tests/ui/almost_complete_range.stderr
index a7a53287850..34521c13ab3 100644
--- a/tests/ui/almost_complete_range.stderr
+++ b/tests/ui/almost_complete_range.stderr
@@ -1,5 +1,5 @@
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:42:17
+  --> $DIR/almost_complete_range.rs:19:17
    |
 LL |         let _ = ('a') ..'z';
    |                 ^^^^^^--^^^
@@ -9,7 +9,7 @@ LL |         let _ = ('a') ..'z';
    = note: `-D clippy::almost-complete-range` implied by `-D warnings`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:43:17
+  --> $DIR/almost_complete_range.rs:20:17
    |
 LL |         let _ = 'A' .. ('Z');
    |                 ^^^^--^^^^^^
@@ -17,7 +17,7 @@ LL |         let _ = 'A' .. ('Z');
    |                     help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:44:17
+  --> $DIR/almost_complete_range.rs:21:17
    |
 LL |         let _ = ((('0'))) .. ('9');
    |                 ^^^^^^^^^^--^^^^^^
@@ -25,7 +25,7 @@ LL |         let _ = ((('0'))) .. ('9');
    |                           help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:51:13
+  --> $DIR/almost_complete_range.rs:28:13
    |
 LL |     let _ = (b'a')..(b'z');
    |             ^^^^^^--^^^^^^
@@ -33,7 +33,7 @@ LL |     let _ = (b'a')..(b'z');
    |                   help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:52:13
+  --> $DIR/almost_complete_range.rs:29:13
    |
 LL |     let _ = b'A'..b'Z';
    |             ^^^^--^^^^
@@ -41,7 +41,7 @@ LL |     let _ = b'A'..b'Z';
    |                 help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:53:13
+  --> $DIR/almost_complete_range.rs:30:13
    |
 LL |     let _ = b'0'..b'9';
    |             ^^^^--^^^^
@@ -49,31 +49,31 @@ LL |     let _ = b'0'..b'9';
    |                 help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:59:13
+  --> $DIR/almost_complete_range.rs:36:13
    |
-LL |     let _ = a!()..'z';
-   |             ^^^^--^^^
-   |                 |
-   |                 help: use an inclusive range: `..=`
+LL |     let _ = inline!('a')..'z';
+   |             ^^^^^^^^^^^^--^^^
+   |                         |
+   |                         help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:60:13
+  --> $DIR/almost_complete_range.rs:37:13
    |
-LL |     let _ = A!()..'Z';
-   |             ^^^^--^^^
-   |                 |
-   |                 help: use an inclusive range: `..=`
+LL |     let _ = inline!('A')..'Z';
+   |             ^^^^^^^^^^^^--^^^
+   |                         |
+   |                         help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:61:13
+  --> $DIR/almost_complete_range.rs:38:13
    |
-LL |     let _ = zero!()..'9';
-   |             ^^^^^^^--^^^
-   |                    |
-   |                    help: use an inclusive range: `..=`
+LL |     let _ = inline!('0')..'9';
+   |             ^^^^^^^^^^^^--^^^
+   |                         |
+   |                         help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:64:9
+  --> $DIR/almost_complete_range.rs:41:9
    |
 LL |         b'a'..b'z' if true => 1,
    |         ^^^^--^^^^
@@ -81,7 +81,7 @@ LL |         b'a'..b'z' if true => 1,
    |             help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:65:9
+  --> $DIR/almost_complete_range.rs:42:9
    |
 LL |         b'A'..b'Z' if true => 2,
    |         ^^^^--^^^^
@@ -89,7 +89,7 @@ LL |         b'A'..b'Z' if true => 2,
    |             help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:66:9
+  --> $DIR/almost_complete_range.rs:43:9
    |
 LL |         b'0'..b'9' if true => 3,
    |         ^^^^--^^^^
@@ -97,7 +97,7 @@ LL |         b'0'..b'9' if true => 3,
    |             help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:74:9
+  --> $DIR/almost_complete_range.rs:51:9
    |
 LL |         'a'..'z' if true => 1,
    |         ^^^--^^^
@@ -105,7 +105,7 @@ LL |         'a'..'z' if true => 1,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:75:9
+  --> $DIR/almost_complete_range.rs:52:9
    |
 LL |         'A'..'Z' if true => 2,
    |         ^^^--^^^
@@ -113,7 +113,7 @@ LL |         'A'..'Z' if true => 2,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:76:9
+  --> $DIR/almost_complete_range.rs:53:9
    |
 LL |         '0'..'9' if true => 3,
    |         ^^^--^^^
@@ -121,46 +121,37 @@ LL |         '0'..'9' if true => 3,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:33:17
+  --> $DIR/almost_complete_range.rs:66:17
    |
 LL |         let _ = 'a'..'z';
    |                 ^^^--^^^
    |                    |
    |                    help: use an inclusive range: `..=`
-...
-LL |     b!();
-   |     ---- in this macro invocation
    |
-   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:34:17
+  --> $DIR/almost_complete_range.rs:67:17
    |
 LL |         let _ = 'A'..'Z';
    |                 ^^^--^^^
    |                    |
    |                    help: use an inclusive range: `..=`
-...
-LL |     b!();
-   |     ---- in this macro invocation
    |
-   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:35:17
+  --> $DIR/almost_complete_range.rs:68:17
    |
 LL |         let _ = '0'..'9';
    |                 ^^^--^^^
    |                    |
    |                    help: use an inclusive range: `..=`
-...
-LL |     b!();
-   |     ---- in this macro invocation
    |
-   = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:90:9
+  --> $DIR/almost_complete_range.rs:75:9
    |
 LL |         'a'..'z' => 1,
    |         ^^^--^^^
@@ -168,7 +159,7 @@ LL |         'a'..'z' => 1,
    |            help: use an inclusive range: `...`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:91:9
+  --> $DIR/almost_complete_range.rs:76:9
    |
 LL |         'A'..'Z' => 2,
    |         ^^^--^^^
@@ -176,7 +167,7 @@ LL |         'A'..'Z' => 2,
    |            help: use an inclusive range: `...`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:92:9
+  --> $DIR/almost_complete_range.rs:77:9
    |
 LL |         '0'..'9' => 3,
    |         ^^^--^^^
@@ -184,7 +175,7 @@ LL |         '0'..'9' => 3,
    |            help: use an inclusive range: `...`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:99:13
+  --> $DIR/almost_complete_range.rs:84:13
    |
 LL |     let _ = 'a'..'z';
    |             ^^^--^^^
@@ -192,7 +183,7 @@ LL |     let _ = 'a'..'z';
    |                help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:100:13
+  --> $DIR/almost_complete_range.rs:85:13
    |
 LL |     let _ = 'A'..'Z';
    |             ^^^--^^^
@@ -200,7 +191,7 @@ LL |     let _ = 'A'..'Z';
    |                help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:101:13
+  --> $DIR/almost_complete_range.rs:86:13
    |
 LL |     let _ = '0'..'9';
    |             ^^^--^^^
@@ -208,7 +199,7 @@ LL |     let _ = '0'..'9';
    |                help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:103:9
+  --> $DIR/almost_complete_range.rs:88:9
    |
 LL |         'a'..'z' => 1,
    |         ^^^--^^^
@@ -216,7 +207,7 @@ LL |         'a'..'z' => 1,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:104:9
+  --> $DIR/almost_complete_range.rs:89:9
    |
 LL |         'A'..'Z' => 1,
    |         ^^^--^^^
@@ -224,7 +215,7 @@ LL |         'A'..'Z' => 1,
    |            help: use an inclusive range: `..=`
 
 error: almost complete ascii range
-  --> $DIR/almost_complete_range.rs:105:9
+  --> $DIR/almost_complete_range.rs:90:9
    |
 LL |         '0'..'9' => 3,
    |         ^^^--^^^
diff --git a/tests/ui/as_conversions.rs b/tests/ui/as_conversions.rs
index ba4394defbf..c50d4088b5e 100644
--- a/tests/ui/as_conversions.rs
+++ b/tests/ui/as_conversions.rs
@@ -1,20 +1,15 @@
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::as_conversions)]
 #![allow(clippy::borrow_as_ptr)]
 
-#[macro_use]
-extern crate macro_rules;
-
-fn with_external_macro() {
-    as_conv_with_arg!(0u32 as u64);
-    as_conv!();
-}
+extern crate proc_macros;
+use proc_macros::external;
 
 fn main() {
     let i = 0u32 as u64;
 
     let j = &i as *const u64 as *mut u64;
 
-    with_external_macro();
+    external!(0u32 as u64);
 }
diff --git a/tests/ui/as_conversions.stderr b/tests/ui/as_conversions.stderr
index f5d59e1e5d8..54037a64997 100644
--- a/tests/ui/as_conversions.stderr
+++ b/tests/ui/as_conversions.stderr
@@ -1,5 +1,5 @@
 error: using a potentially dangerous silent `as` conversion
-  --> $DIR/as_conversions.rs:15:13
+  --> $DIR/as_conversions.rs:10:13
    |
 LL |     let i = 0u32 as u64;
    |             ^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let i = 0u32 as u64;
    = note: `-D clippy::as-conversions` implied by `-D warnings`
 
 error: using a potentially dangerous silent `as` conversion
-  --> $DIR/as_conversions.rs:17:13
+  --> $DIR/as_conversions.rs:12:13
    |
 LL |     let j = &i as *const u64 as *mut u64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     let j = &i as *const u64 as *mut u64;
    = help: consider using a safe wrapper for this conversion
 
 error: using a potentially dangerous silent `as` conversion
-  --> $DIR/as_conversions.rs:17:13
+  --> $DIR/as_conversions.rs:12:13
    |
 LL |     let j = &i as *const u64 as *mut u64;
    |             ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/auxiliary/doc_unsafe_macros.rs b/tests/ui/auxiliary/doc_unsafe_macros.rs
deleted file mode 100644
index 3d917e3dc75..00000000000
--- a/tests/ui/auxiliary/doc_unsafe_macros.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-#[macro_export]
-macro_rules! undocd_unsafe {
-    () => {
-        pub unsafe fn oy_vey() {
-            unimplemented!();
-        }
-    };
-}
-#[macro_export]
-macro_rules! undocd_safe {
-    () => {
-        pub fn vey_oy() {
-            unimplemented!();
-        }
-    };
-}
diff --git a/tests/ui/auxiliary/implicit_hasher_macros.rs b/tests/ui/auxiliary/implicit_hasher_macros.rs
deleted file mode 100644
index 1eb77c53183..00000000000
--- a/tests/ui/auxiliary/implicit_hasher_macros.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-#[macro_export]
-macro_rules! implicit_hasher_fn {
-    () => {
-        pub fn f(input: &HashMap<u32, u32>) {}
-    };
-}
diff --git a/tests/ui/auxiliary/macro_rules.rs b/tests/ui/auxiliary/macro_rules.rs
index a13af565203..1dc92c1b92b 100644
--- a/tests/ui/auxiliary/macro_rules.rs
+++ b/tests/ui/auxiliary/macro_rules.rs
@@ -3,21 +3,6 @@
 //! Used to test that certain lints don't trigger in imported external macros
 
 #[macro_export]
-macro_rules! foofoo {
-    () => {
-        loop {}
-    };
-}
-
-#[macro_export]
-macro_rules! must_use_unit {
-    () => {
-        #[must_use]
-        fn foo() {}
-    };
-}
-
-#[macro_export]
 macro_rules! try_err {
     () => {
         pub fn try_err_fn() -> Result<i32, i32> {
@@ -37,134 +22,8 @@ macro_rules! string_add {
 }
 
 #[macro_export]
-macro_rules! take_external {
-    ($s:expr) => {
-        std::mem::replace($s, Default::default())
-    };
-}
-
-#[macro_export]
-macro_rules! option_env_unwrap_external {
-    ($env: expr) => {
-        option_env!($env).unwrap()
-    };
-    ($env: expr, $message: expr) => {
-        option_env!($env).expect($message)
-    };
-}
-
-#[macro_export]
-macro_rules! ref_arg_binding {
-    () => {
-        let ref _y = 42;
-    };
-}
-
-#[macro_export]
-macro_rules! ref_arg_function {
-    () => {
-        fn fun_example(ref _x: usize) {}
-    };
-}
-
-#[macro_export]
-macro_rules! as_conv_with_arg {
-    (0u32 as u64) => {
-        ()
-    };
-}
-
-#[macro_export]
-macro_rules! as_conv {
-    () => {
-        0u32 as u64
-    };
-}
-
-#[macro_export]
-macro_rules! large_enum_variant {
-    () => {
-        enum LargeEnumInMacro {
-            A(i32),
-            B([i32; 8000]),
-        }
-    };
-}
-
-#[macro_export]
-macro_rules! field_reassign_with_default {
-    () => {
-        #[derive(Default)]
-        struct A {
-            pub i: i32,
-            pub j: i64,
-        }
-        fn lint() {
-            let mut a: A = Default::default();
-            a.i = 42;
-            a;
-        }
-    };
-}
-
-#[macro_export]
-macro_rules! default_numeric_fallback {
-    () => {
-        let x = 22;
-    };
-}
-
-#[macro_export]
 macro_rules! mut_mut {
     () => {
         let mut_mut_ty: &mut &mut u32 = &mut &mut 1u32;
     };
 }
-
-#[macro_export]
-macro_rules! ptr_as_ptr_cast {
-    ($ptr: ident) => {
-        $ptr as *const i32
-    };
-}
-
-#[macro_export]
-macro_rules! manual_rem_euclid {
-    () => {
-        let value: i32 = 5;
-        let _: i32 = ((value % 4) + 4) % 4;
-    };
-}
-
-#[macro_export]
-macro_rules! equatable_if_let {
-    ($a:ident) => {{ if let 2 = $a {} }};
-}
-
-#[macro_export]
-macro_rules! almost_complete_range {
-    () => {
-        let _ = 'a'..'z';
-        let _ = 'A'..'Z';
-        let _ = '0'..'9';
-    };
-}
-
-#[macro_export]
-macro_rules! unsafe_macro {
-    () => {
-        unsafe {
-            *core::ptr::null::<()>();
-            *core::ptr::null::<()>();
-        }
-    };
-}
-
-#[macro_export]
-macro_rules! needless_lifetime {
-    () => {
-        fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 {
-            unimplemented!()
-        }
-    };
-}
diff --git a/tests/ui/auxiliary/macro_use_helper.rs b/tests/ui/auxiliary/macro_use_helper.rs
index ecb55d8cb48..7ed8a28dbd9 100644
--- a/tests/ui/auxiliary/macro_use_helper.rs
+++ b/tests/ui/auxiliary/macro_use_helper.rs
@@ -13,7 +13,7 @@ pub mod inner {
 
     // RE-EXPORT
     // this will stick in `inner` module
-    pub use macro_rules::foofoo;
+    pub use macro_rules::mut_mut;
     pub use macro_rules::try_err;
 
     pub mod nested {
diff --git a/tests/ui/auxiliary/proc_macro_with_span.rs b/tests/ui/auxiliary/proc_macro_with_span.rs
deleted file mode 100644
index 8ea631f2bbd..00000000000
--- a/tests/ui/auxiliary/proc_macro_with_span.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// compile-flags: --emit=link
-// no-prefer-dynamic
-
-#![crate_type = "proc-macro"]
-
-extern crate proc_macro;
-
-use proc_macro::{token_stream::IntoIter, Group, Span, TokenStream, TokenTree};
-
-#[proc_macro]
-pub fn with_span(input: TokenStream) -> TokenStream {
-    let mut iter = input.into_iter();
-    let span = iter.next().unwrap().span();
-    let mut res = TokenStream::new();
-    write_with_span(span, iter, &mut res);
-    res
-}
-
-fn write_with_span(s: Span, input: IntoIter, out: &mut TokenStream) {
-    for mut tt in input {
-        if let TokenTree::Group(g) = tt {
-            let mut stream = TokenStream::new();
-            write_with_span(s, g.stream().into_iter(), &mut stream);
-            let mut group = Group::new(g.delimiter(), stream);
-            group.set_span(s);
-            out.extend([TokenTree::Group(group)]);
-        } else {
-            tt.set_span(s);
-            out.extend([tt]);
-        }
-    }
-}
diff --git a/tests/ui/auxiliary/proc_macros.rs b/tests/ui/auxiliary/proc_macros.rs
new file mode 100644
index 00000000000..325be83a0d7
--- /dev/null
+++ b/tests/ui/auxiliary/proc_macros.rs
@@ -0,0 +1,474 @@
+// compile-flags: --emit=link
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(let_chains)]
+#![feature(proc_macro_span)]
+#![allow(dead_code)]
+
+extern crate proc_macro;
+
+use core::mem;
+use proc_macro::{
+    token_stream::IntoIter,
+    Delimiter::{self, Brace, Parenthesis},
+    Group, Ident, Literal, Punct,
+    Spacing::{self, Alone, Joint},
+    Span, TokenStream, TokenTree as TT,
+};
+
+type Result<T> = core::result::Result<T, TokenStream>;
+
+/// Make a `compile_error!` pointing to the given span.
+fn make_error(msg: &str, span: Span) -> TokenStream {
+    TokenStream::from_iter([
+        TT::Ident(Ident::new("compile_error", span)),
+        TT::Punct(punct_with_span('!', Alone, span)),
+        TT::Group({
+            let mut msg = Literal::string(msg);
+            msg.set_span(span);
+            group_with_span(Parenthesis, TokenStream::from_iter([TT::Literal(msg)]), span)
+        }),
+    ])
+}
+
+fn expect_tt<T>(tt: Option<TT>, f: impl FnOnce(TT) -> Option<T>, expected: &str, span: Span) -> Result<T> {
+    match tt {
+        None => Err(make_error(
+            &format!("unexpected end of input, expected {expected}"),
+            span,
+        )),
+        Some(tt) => {
+            let span = tt.span();
+            match f(tt) {
+                Some(x) => Ok(x),
+                None => Err(make_error(&format!("unexpected token, expected {expected}"), span)),
+            }
+        },
+    }
+}
+
+fn punct_with_span(c: char, spacing: Spacing, span: Span) -> Punct {
+    let mut p = Punct::new(c, spacing);
+    p.set_span(span);
+    p
+}
+
+fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Group {
+    let mut g = Group::new(delimiter, stream);
+    g.set_span(span);
+    g
+}
+
+/// Token used to escape the following token from the macro's span rules.
+const ESCAPE_CHAR: char = '$';
+
+/// Takes a single token followed by a sequence tokens. Returns the sequence of tokens with their
+/// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
+#[proc_macro]
+pub fn with_span(input: TokenStream) -> TokenStream {
+    let mut iter = input.into_iter();
+    let span = iter.next().unwrap().span();
+    let mut res = TokenStream::new();
+    if let Err(e) = write_with_span(span, iter, &mut res) {
+        e
+    } else {
+        res
+    }
+}
+
+/// Takes a sequence of tokens and return the tokens with the span set such that they appear to be
+/// from an external macro. Tokens may be escaped with either `#ident` or `#(tokens)`.
+#[proc_macro]
+pub fn external(input: TokenStream) -> TokenStream {
+    let mut res = TokenStream::new();
+    if let Err(e) = write_with_span(Span::mixed_site(), input.into_iter(), &mut res) {
+        e
+    } else {
+        res
+    }
+}
+
+/// Copies all the tokens, replacing all their spans with the given span. Tokens can be escaped
+/// either by `#ident` or `#(tokens)`.
+fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Result<()> {
+    while let Some(tt) = input.next() {
+        match tt {
+            TT::Punct(p) if p.as_char() == ESCAPE_CHAR => {
+                expect_tt(
+                    input.next(),
+                    |tt| match tt {
+                        tt @ (TT::Ident(_) | TT::Literal(_)) => {
+                            out.extend([tt]);
+                            Some(())
+                        },
+                        TT::Punct(mut p) if p.as_char() == ESCAPE_CHAR => {
+                            p.set_span(s);
+                            out.extend([TT::Punct(p)]);
+                            Some(())
+                        },
+                        TT::Group(g) if g.delimiter() == Parenthesis => {
+                            out.extend([TT::Group(group_with_span(Delimiter::None, g.stream(), g.span()))]);
+                            Some(())
+                        },
+                        _ => None,
+                    },
+                    "an ident, a literal, or parenthesized tokens",
+                    p.span(),
+                )?;
+            },
+            TT::Group(g) => {
+                let mut stream = TokenStream::new();
+                write_with_span(s, g.stream().into_iter(), &mut stream)?;
+                out.extend([TT::Group(group_with_span(g.delimiter(), stream, s))]);
+            },
+            mut tt => {
+                tt.set_span(s);
+                out.extend([tt]);
+            },
+        }
+    }
+    Ok(())
+}
+
+/// Within the item this attribute is attached to, an `inline!` macro is available which expands the
+/// contained tokens as though they came from a macro expansion.
+///
+/// Within the `inline!` macro, any token preceded by `$` is passed as though it were an argument
+/// with an automatically chosen fragment specifier. `$ident` will be passed as `ident`, `$1` or
+/// `$"literal"` will be passed as `literal`, `$'lt` will be passed as `lifetime`, and `$(...)` will
+/// pass the contained tokens as a `tt` sequence (the wrapping parenthesis are removed). If another
+/// specifier is required it can be specified within parenthesis like `$(@expr ...)`. This will
+/// expand the remaining tokens as a single argument.
+///
+/// Multiple `inline!` macros may be nested within each other. This will expand as nested macro
+/// calls. However, any arguments will be passed as though they came from the outermost context.
+#[proc_macro_attribute]
+pub fn inline_macros(args: TokenStream, input: TokenStream) -> TokenStream {
+    let mut args = args.into_iter();
+    let mac_name = match args.next() {
+        Some(TT::Ident(name)) => Some(name),
+        Some(tt) => {
+            return make_error(
+                "unexpected argument, expected either an ident or no arguments",
+                tt.span(),
+            );
+        },
+        None => None,
+    };
+    if let Some(tt) = args.next() {
+        return make_error(
+            "unexpected argument, expected either an ident or no arguments",
+            tt.span(),
+        );
+    };
+
+    let mac_name = if let Some(mac_name) = mac_name {
+        Ident::new(&format!("__inline_mac_{mac_name}"), Span::call_site())
+    } else {
+        let mut input = match LookaheadIter::new(input.clone().into_iter()) {
+            Some(x) => x,
+            None => return input,
+        };
+        loop {
+            match input.next() {
+                None => break Ident::new("__inline_mac", Span::call_site()),
+                Some(TT::Ident(kind)) => match &*kind.to_string() {
+                    "impl" => break Ident::new("__inline_mac_impl", Span::call_site()),
+                    kind @ ("struct" | "enum" | "union" | "fn" | "mod" | "trait" | "type" | "const" | "static") => {
+                        if let TT::Ident(name) = &input.tt {
+                            break Ident::new(&format!("__inline_mac_{kind}_{name}"), Span::call_site());
+                        } else {
+                            break Ident::new(&format!("__inline_mac_{kind}"), Span::call_site());
+                        }
+                    },
+                    _ => {},
+                },
+                _ => {},
+            }
+        }
+    };
+
+    let mut expander = Expander::default();
+    let mut mac = MacWriter::new(mac_name);
+    if let Err(e) = expander.expand(input.into_iter(), &mut mac) {
+        return e;
+    }
+    let mut out = TokenStream::new();
+    mac.finish(&mut out);
+    out.extend(expander.expn);
+    out
+}
+
+/// Wraps a `TokenStream` iterator with a single token lookahead.
+struct LookaheadIter {
+    tt: TT,
+    iter: IntoIter,
+}
+impl LookaheadIter {
+    fn new(mut iter: IntoIter) -> Option<Self> {
+        iter.next().map(|tt| Self { tt, iter })
+    }
+
+    /// Get's the lookahead token, replacing it with the next token in the stream.
+    /// Note: If there isn't a next token, this will not return the lookahead token.
+    fn next(&mut self) -> Option<TT> {
+        self.iter.next().map(|tt| mem::replace(&mut self.tt, tt))
+    }
+}
+
+/// Builds the macro used to implement all the `inline!` macro calls.
+struct MacWriter {
+    name: Ident,
+    macros: TokenStream,
+    next_idx: usize,
+}
+impl MacWriter {
+    fn new(name: Ident) -> Self {
+        Self {
+            name,
+            macros: TokenStream::new(),
+            next_idx: 0,
+        }
+    }
+
+    /// Inserts a new `inline!` call.
+    fn insert(&mut self, name_span: Span, bang_span: Span, body: Group, expander: &mut Expander) -> Result<()> {
+        let idx = self.next_idx;
+        self.next_idx += 1;
+
+        let mut inner = Expander::for_arm(idx);
+        inner.expand(body.stream().into_iter(), self)?;
+        let new_arm = inner.arm.unwrap();
+
+        self.macros.extend([
+            TT::Group(Group::new(Parenthesis, new_arm.args_def)),
+            TT::Punct(Punct::new('=', Joint)),
+            TT::Punct(Punct::new('>', Alone)),
+            TT::Group(Group::new(Parenthesis, inner.expn)),
+            TT::Punct(Punct::new(';', Alone)),
+        ]);
+
+        expander.expn.extend([
+            TT::Ident({
+                let mut name = self.name.clone();
+                name.set_span(name_span);
+                name
+            }),
+            TT::Punct(punct_with_span('!', Alone, bang_span)),
+        ]);
+        let mut call_body = TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]);
+        if let Some(arm) = expander.arm.as_mut() {
+            if !new_arm.args.is_empty() {
+                arm.add_sub_args(new_arm.args, &mut call_body);
+            }
+        } else {
+            call_body.extend(new_arm.args);
+        }
+        let mut g = Group::new(body.delimiter(), call_body);
+        g.set_span(body.span());
+        expander.expn.extend([TT::Group(g)]);
+        Ok(())
+    }
+
+    /// Creates the macro definition.
+    fn finish(self, out: &mut TokenStream) {
+        if self.next_idx != 0 {
+            out.extend([
+                TT::Ident(Ident::new("macro_rules", Span::call_site())),
+                TT::Punct(Punct::new('!', Alone)),
+                TT::Ident(self.name),
+                TT::Group(Group::new(Brace, self.macros)),
+            ])
+        }
+    }
+}
+
+struct MacroArm {
+    args_def: TokenStream,
+    args: Vec<TT>,
+}
+impl MacroArm {
+    fn add_single_arg_def(&mut self, kind: &str, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
+        let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
+        self.args_def.extend([
+            TT::Punct(Punct::new('$', Alone)),
+            TT::Ident(name.clone()),
+            TT::Punct(Punct::new(':', Alone)),
+            TT::Ident(Ident::new(kind, Span::call_site())),
+        ]);
+        name.set_span(arg_span);
+        out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]);
+    }
+
+    fn add_parenthesized_arg_def(&mut self, kind: Ident, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
+        let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
+        self.args_def.extend([TT::Group(Group::new(
+            Parenthesis,
+            TokenStream::from_iter([
+                TT::Punct(Punct::new('$', Alone)),
+                TT::Ident(name.clone()),
+                TT::Punct(Punct::new(':', Alone)),
+                TT::Ident(kind),
+            ]),
+        ))]);
+        name.set_span(arg_span);
+        out.extend([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]);
+    }
+
+    fn add_multi_arg_def(&mut self, dollar_span: Span, arg_span: Span, out: &mut TokenStream) {
+        let mut name = Ident::new(&format!("_{}", self.args.len()), Span::call_site());
+        self.args_def.extend([TT::Group(Group::new(
+            Parenthesis,
+            TokenStream::from_iter([
+                TT::Punct(Punct::new('$', Alone)),
+                TT::Group(Group::new(
+                    Parenthesis,
+                    TokenStream::from_iter([
+                        TT::Punct(Punct::new('$', Alone)),
+                        TT::Ident(name.clone()),
+                        TT::Punct(Punct::new(':', Alone)),
+                        TT::Ident(Ident::new("tt", Span::call_site())),
+                    ]),
+                )),
+                TT::Punct(Punct::new('*', Alone)),
+            ]),
+        ))]);
+        name.set_span(arg_span);
+        out.extend([
+            TT::Punct(punct_with_span('$', Alone, dollar_span)),
+            TT::Group(group_with_span(
+                Parenthesis,
+                TokenStream::from_iter([TT::Punct(punct_with_span('$', Alone, dollar_span)), TT::Ident(name)]),
+                dollar_span,
+            )),
+            TT::Punct(punct_with_span('*', Alone, dollar_span)),
+        ]);
+    }
+
+    fn add_arg(&mut self, dollar_span: Span, tt: TT, input: &mut IntoIter, out: &mut TokenStream) -> Result<()> {
+        match tt {
+            TT::Punct(p) if p.as_char() == ESCAPE_CHAR => out.extend([TT::Punct(p)]),
+            TT::Punct(p) if p.as_char() == '\'' && p.spacing() == Joint => {
+                let lt_name = expect_tt(
+                    input.next(),
+                    |tt| match tt {
+                        TT::Ident(x) => Some(x),
+                        _ => None,
+                    },
+                    "lifetime name",
+                    p.span(),
+                )?;
+                let arg_span = p.span().join(lt_name.span()).unwrap_or(p.span());
+                self.add_single_arg_def("lifetime", dollar_span, arg_span, out);
+                self.args.extend([TT::Punct(p), TT::Ident(lt_name)]);
+            },
+            TT::Ident(x) => {
+                self.add_single_arg_def("ident", dollar_span, x.span(), out);
+                self.args.push(TT::Ident(x));
+            },
+            TT::Literal(x) => {
+                self.add_single_arg_def("literal", dollar_span, x.span(), out);
+                self.args.push(TT::Literal(x));
+            },
+            TT::Group(g) if g.delimiter() == Parenthesis => {
+                let mut inner = g.stream().into_iter();
+                if let Some(TT::Punct(p)) = inner.next()
+                    && p.as_char() == '@'
+                {
+                    let kind = expect_tt(
+                        inner.next(),
+                        |tt| match tt {
+                            TT::Ident(kind) => Some(kind),
+                            _ => None,
+                        },
+                        "a macro fragment specifier",
+                        p.span(),
+                    )?;
+                    self.add_parenthesized_arg_def(kind, dollar_span, g.span(), out);
+                    self.args.push(TT::Group(group_with_span(Parenthesis, inner.collect(), g.span())))
+                } else {
+                    self.add_multi_arg_def(dollar_span, g.span(), out);
+                    self.args.push(TT::Group(g));
+                }
+            },
+            tt => return Err(make_error("unsupported escape", tt.span())),
+        };
+        Ok(())
+    }
+
+    fn add_sub_args(&mut self, args: Vec<TT>, out: &mut TokenStream) {
+        self.add_multi_arg_def(Span::call_site(), Span::call_site(), out);
+        self.args
+            .extend([TT::Group(Group::new(Parenthesis, TokenStream::from_iter(args)))]);
+    }
+}
+
+#[derive(Default)]
+struct Expander {
+    arm: Option<MacroArm>,
+    expn: TokenStream,
+}
+impl Expander {
+    fn for_arm(idx: usize) -> Self {
+        Self {
+            arm: Some(MacroArm {
+                args_def: TokenStream::from_iter([TT::Literal(Literal::usize_unsuffixed(idx))]),
+                args: Vec::new(),
+            }),
+            expn: TokenStream::new(),
+        }
+    }
+
+    fn write_tt(&mut self, tt: TT, mac: &mut MacWriter) -> Result<()> {
+        match tt {
+            TT::Group(g) => {
+                let outer = mem::take(&mut self.expn);
+                self.expand(g.stream().into_iter(), mac)?;
+                let inner = mem::replace(&mut self.expn, outer);
+                self.expn
+                    .extend([TT::Group(group_with_span(g.delimiter(), inner, g.span()))]);
+            },
+            tt => self.expn.extend([tt]),
+        }
+        Ok(())
+    }
+
+    fn expand(&mut self, input: IntoIter, mac: &mut MacWriter) -> Result<()> {
+        let Some(mut input) = LookaheadIter::new(input) else {
+            return Ok(());
+        };
+        while let Some(tt) = input.next() {
+            if let TT::Punct(p) = &tt
+                && p.as_char() == ESCAPE_CHAR
+                && let Some(arm) = self.arm.as_mut()
+            {
+                arm.add_arg(p.span(), mem::replace(&mut input.tt, tt), &mut input.iter, &mut self.expn)?;
+                if input.next().is_none() {
+                    return Ok(());
+                }
+            } else if let TT::Punct(p) = &input.tt
+                && p.as_char() == '!'
+                && let TT::Ident(name) = &tt
+                && name.to_string() == "inline"
+            {
+                let g = expect_tt(
+                    input.iter.next(),
+                    |tt| match tt {
+                        TT::Group(g) => Some(g),
+                        _ => None,
+                    },
+                    "macro arguments",
+                    p.span(),
+                )?;
+                mac.insert(name.span(), p.span(), g, self)?;
+                if input.next().is_none() {
+                    return Ok(());
+                }
+            } else {
+                self.write_tt(tt, mac)?;
+            }
+        }
+        self.write_tt(input.tt, mac)
+    }
+}
diff --git a/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs b/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
index f13733af3d0..b03c21262c3 100644
--- a/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
+++ b/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
@@ -1,5 +1,5 @@
 // this file solely exists to test constants defined in foreign crates.
-// As the most common case is the `http` crate, it replicates `http::HeadewrName`'s structure.
+// As the most common case is the `http` crate, it replicates `http::HeaderName`'s structure.
 
 #![allow(clippy::declare_interior_mutable_const)]
 #![allow(unused_tuple_struct_fields)]
diff --git a/tests/ui/crashes/ice-10148.rs b/tests/ui/crashes/ice-10148.rs
index af33b10c693..1ab3570c907 100644
--- a/tests/ui/crashes/ice-10148.rs
+++ b/tests/ui/crashes/ice-10148.rs
@@ -1,8 +1,8 @@
-// aux-build:../../auxiliary/proc_macro_with_span.rs
+// aux-build:../../auxiliary/proc_macros.rs
 
-extern crate proc_macro_with_span;
+extern crate proc_macros;
 
-use proc_macro_with_span::with_span;
+use proc_macros::with_span;
 
 fn main() {
     println!(with_span!(""something ""));
diff --git a/tests/ui/default_numeric_fallback_f64.fixed b/tests/ui/default_numeric_fallback_f64.fixed
index a9e5fd159af..42c15d6a70b 100644
--- a/tests/ui/default_numeric_fallback_f64.fixed
+++ b/tests/ui/default_numeric_fallback_f64.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::default_numeric_fallback)]
 #![allow(
@@ -13,8 +13,8 @@
     clippy::let_with_type_underscore
 )]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 mod basic_expr {
     fn test() {
@@ -167,20 +167,17 @@ mod method_calls {
 }
 
 mod in_macro {
-    macro_rules! internal_macro {
-        () => {
-            let x = 22.0_f64;
-        };
-    }
+    use super::*;
 
     // Should lint in internal macro.
+    #[inline_macros]
     fn internal() {
-        internal_macro!();
+        inline!(let x = 22.0_f64;);
     }
 
     // Should NOT lint in external macro.
     fn external() {
-        default_numeric_fallback!();
+        external!(let x = 22.;);
     }
 }
 
diff --git a/tests/ui/default_numeric_fallback_f64.rs b/tests/ui/default_numeric_fallback_f64.rs
index 085f8f452b2..7da7ea254e9 100644
--- a/tests/ui/default_numeric_fallback_f64.rs
+++ b/tests/ui/default_numeric_fallback_f64.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::default_numeric_fallback)]
 #![allow(
@@ -13,8 +13,8 @@
     clippy::let_with_type_underscore
 )]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 mod basic_expr {
     fn test() {
@@ -167,20 +167,17 @@ mod method_calls {
 }
 
 mod in_macro {
-    macro_rules! internal_macro {
-        () => {
-            let x = 22.;
-        };
-    }
+    use super::*;
 
     // Should lint in internal macro.
+    #[inline_macros]
     fn internal() {
-        internal_macro!();
+        inline!(let x = 22.;);
     }
 
     // Should NOT lint in external macro.
     fn external() {
-        default_numeric_fallback!();
+        external!(let x = 22.;);
     }
 }
 
diff --git a/tests/ui/default_numeric_fallback_f64.stderr b/tests/ui/default_numeric_fallback_f64.stderr
index 44c6f1a9bea..b949cd1d50b 100644
--- a/tests/ui/default_numeric_fallback_f64.stderr
+++ b/tests/ui/default_numeric_fallback_f64.stderr
@@ -139,15 +139,12 @@ LL |         s.generic_arg(1.);
    |                       ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:172:21
+  --> $DIR/default_numeric_fallback_f64.rs:175:25
    |
-LL |             let x = 22.;
-   |                     ^^^ help: consider adding suffix: `22.0_f64`
-...
-LL |         internal_macro!();
-   |         ----------------- in this macro invocation
+LL |         inline!(let x = 22.;);
+   |                         ^^^ help: consider adding suffix: `22.0_f64`
    |
-   = note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 24 previous errors
 
diff --git a/tests/ui/default_numeric_fallback_i32.fixed b/tests/ui/default_numeric_fallback_i32.fixed
index 63ac4d5aeb6..b7485b73dcd 100644
--- a/tests/ui/default_numeric_fallback_i32.fixed
+++ b/tests/ui/default_numeric_fallback_i32.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![feature(lint_reasons)]
 #![warn(clippy::default_numeric_fallback)]
@@ -13,8 +13,8 @@
     clippy::let_with_type_underscore
 )]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 mod basic_expr {
     fn test() {
@@ -168,20 +168,17 @@ mod method_calls {
 }
 
 mod in_macro {
-    macro_rules! internal_macro {
-        () => {
-            let x = 22_i32;
-        };
-    }
+    use super::*;
 
     // Should lint in internal macro.
+    #[inline_macros]
     fn internal() {
-        internal_macro!();
+        inline!(let x = 22_i32;);
     }
 
     // Should NOT lint in external macro.
     fn external() {
-        default_numeric_fallback!();
+        external!(let x = 22;);
     }
 }
 
diff --git a/tests/ui/default_numeric_fallback_i32.rs b/tests/ui/default_numeric_fallback_i32.rs
index 28e6eceb80e..7307d31354e 100644
--- a/tests/ui/default_numeric_fallback_i32.rs
+++ b/tests/ui/default_numeric_fallback_i32.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![feature(lint_reasons)]
 #![warn(clippy::default_numeric_fallback)]
@@ -13,8 +13,8 @@
     clippy::let_with_type_underscore
 )]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 mod basic_expr {
     fn test() {
@@ -168,20 +168,17 @@ mod method_calls {
 }
 
 mod in_macro {
-    macro_rules! internal_macro {
-        () => {
-            let x = 22;
-        };
-    }
+    use super::*;
 
     // Should lint in internal macro.
+    #[inline_macros]
     fn internal() {
-        internal_macro!();
+        inline!(let x = 22;);
     }
 
     // Should NOT lint in external macro.
     fn external() {
-        default_numeric_fallback!();
+        external!(let x = 22;);
     }
 }
 
diff --git a/tests/ui/default_numeric_fallback_i32.stderr b/tests/ui/default_numeric_fallback_i32.stderr
index dd91574d5b3..48cd28102ce 100644
--- a/tests/ui/default_numeric_fallback_i32.stderr
+++ b/tests/ui/default_numeric_fallback_i32.stderr
@@ -151,15 +151,12 @@ LL |         s.generic_arg(1);
    |                       ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:173:21
+  --> $DIR/default_numeric_fallback_i32.rs:176:25
    |
-LL |             let x = 22;
-   |                     ^^ help: consider adding suffix: `22_i32`
-...
-LL |         internal_macro!();
-   |         ----------------- in this macro invocation
+LL |         inline!(let x = 22;);
+   |                         ^^ help: consider adding suffix: `22_i32`
    |
-   = note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 26 previous errors
 
diff --git a/tests/ui/default_trait_access.fixed b/tests/ui/default_trait_access.fixed
index 5640599d48a..7842ef3ec40 100644
--- a/tests/ui/default_trait_access.fixed
+++ b/tests/ui/default_trait_access.fixed
@@ -1,12 +1,12 @@
 // run-rustfix
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 #![deny(clippy::default_trait_access)]
 #![allow(dead_code, unused_imports)]
 #![allow(clippy::uninlined_format_args)]
 
-extern crate proc_macro_with_span;
+extern crate proc_macros;
 
-use proc_macro_with_span::with_span;
+use proc_macros::with_span;
 use std::default;
 use std::default::Default as D2;
 use std::string;
diff --git a/tests/ui/default_trait_access.rs b/tests/ui/default_trait_access.rs
index 11d4bc5c5f0..cbb3e59c970 100644
--- a/tests/ui/default_trait_access.rs
+++ b/tests/ui/default_trait_access.rs
@@ -1,12 +1,12 @@
 // run-rustfix
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 #![deny(clippy::default_trait_access)]
 #![allow(dead_code, unused_imports)]
 #![allow(clippy::uninlined_format_args)]
 
-extern crate proc_macro_with_span;
+extern crate proc_macros;
 
-use proc_macro_with_span::with_span;
+use proc_macros::with_span;
 use std::default;
 use std::default::Default as D2;
 use std::string;
diff --git a/tests/ui/deref_addrof.fixed b/tests/ui/deref_addrof.fixed
index 2f489deb1ee..ca5c03304c7 100644
--- a/tests/ui/deref_addrof.fixed
+++ b/tests/ui/deref_addrof.fixed
@@ -1,7 +1,12 @@
 // run-rustfix
+// aux-build:proc_macros.rs
+
 #![allow(clippy::return_self_not_must_use)]
 #![warn(clippy::deref_addrof)]
 
+extern crate proc_macros;
+use proc_macros::inline_macros;
+
 fn get_number() -> usize {
     10
 }
@@ -41,28 +46,15 @@ fn main() {
     let _ = unsafe { *core::ptr::addr_of!(a) };
 }
 
-#[rustfmt::skip]
-macro_rules! m {
-    ($visitor: expr) => {
-        $visitor
-    };
-}
-
-#[rustfmt::skip]
-macro_rules! m_mut {
-    ($visitor: expr) => {
-        $visitor
-    };
-}
-
 #[derive(Copy, Clone)]
 pub struct S;
+#[inline_macros]
 impl S {
     pub fn f(&self) -> &Self {
-        m!(self)
+        inline!($(@expr self))
     }
     #[allow(unused_mut)] // mut will be unused, once the macro is fixed
     pub fn f_mut(mut self) -> Self {
-        m_mut!(self)
+        inline!($(@expr self))
     }
 }
diff --git a/tests/ui/deref_addrof.rs b/tests/ui/deref_addrof.rs
index 49f360b9a7f..3db5fafe944 100644
--- a/tests/ui/deref_addrof.rs
+++ b/tests/ui/deref_addrof.rs
@@ -1,7 +1,12 @@
 // run-rustfix
+// aux-build:proc_macros.rs
+
 #![allow(clippy::return_self_not_must_use)]
 #![warn(clippy::deref_addrof)]
 
+extern crate proc_macros;
+use proc_macros::inline_macros;
+
 fn get_number() -> usize {
     10
 }
@@ -41,28 +46,15 @@ fn main() {
     let _ = unsafe { *core::ptr::addr_of!(a) };
 }
 
-#[rustfmt::skip]
-macro_rules! m {
-    ($visitor: expr) => {
-        *& $visitor
-    };
-}
-
-#[rustfmt::skip]
-macro_rules! m_mut {
-    ($visitor: expr) => {
-        *& mut $visitor
-    };
-}
-
 #[derive(Copy, Clone)]
 pub struct S;
+#[inline_macros]
 impl S {
     pub fn f(&self) -> &Self {
-        m!(self)
+        inline!(*& $(@expr self))
     }
     #[allow(unused_mut)] // mut will be unused, once the macro is fixed
     pub fn f_mut(mut self) -> Self {
-        m_mut!(self)
+        inline!(*&mut $(@expr self))
     }
 }
diff --git a/tests/ui/deref_addrof.stderr b/tests/ui/deref_addrof.stderr
index 75371fcdb96..e0287522fc5 100644
--- a/tests/ui/deref_addrof.stderr
+++ b/tests/ui/deref_addrof.stderr
@@ -1,5 +1,5 @@
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:19:13
+  --> $DIR/deref_addrof.rs:24:13
    |
 LL |     let b = *&a;
    |             ^^^ help: try this: `a`
@@ -7,68 +7,62 @@ LL |     let b = *&a;
    = note: `-D clippy::deref-addrof` implied by `-D warnings`
 
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:21:13
+  --> $DIR/deref_addrof.rs:26:13
    |
 LL |     let b = *&get_number();
    |             ^^^^^^^^^^^^^^ help: try this: `get_number()`
 
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:26:13
+  --> $DIR/deref_addrof.rs:31:13
    |
 LL |     let b = *&bytes[1..2][0];
    |             ^^^^^^^^^^^^^^^^ help: try this: `bytes[1..2][0]`
 
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:30:13
+  --> $DIR/deref_addrof.rs:35:13
    |
 LL |     let b = *&(a);
    |             ^^^^^ help: try this: `(a)`
 
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:32:13
+  --> $DIR/deref_addrof.rs:37:13
    |
 LL |     let b = *(&a);
    |             ^^^^^ help: try this: `a`
 
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:35:13
+  --> $DIR/deref_addrof.rs:40:13
    |
 LL |     let b = *((&a));
    |             ^^^^^^^ help: try this: `a`
 
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:37:13
+  --> $DIR/deref_addrof.rs:42:13
    |
 LL |     let b = *&&a;
    |             ^^^^ help: try this: `&a`
 
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:39:14
+  --> $DIR/deref_addrof.rs:44:14
    |
 LL |     let b = **&aref;
    |              ^^^^^^ help: try this: `aref`
 
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:47:9
+  --> $DIR/deref_addrof.rs:54:17
    |
-LL |         *& $visitor
-   |         ^^^^^^^^^^^ help: try this: `$visitor`
-...
-LL |         m!(self)
-   |         -------- in this macro invocation
+LL |         inline!(*& $(@expr self))
+   |                 ^^^^^^^^^^^^^^^^ help: try this: `$(@expr self)`
    |
-   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: immediately dereferencing a reference
-  --> $DIR/deref_addrof.rs:54:9
+  --> $DIR/deref_addrof.rs:58:17
    |
-LL |         *& mut $visitor
-   |         ^^^^^^^^^^^^^^^ help: try this: `$visitor`
-...
-LL |         m_mut!(self)
-   |         ------------ in this macro invocation
+LL |         inline!(*&mut $(@expr self))
+   |                 ^^^^^^^^^^^^^^^^^^^ help: try this: `$(@expr self)`
    |
-   = note: this error originates in the macro `m_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 10 previous errors
 
diff --git a/tests/ui/deref_addrof_macro.rs b/tests/ui/deref_addrof_macro.rs
index dcebd6c6e29..57c0be3f51e 100644
--- a/tests/ui/deref_addrof_macro.rs
+++ b/tests/ui/deref_addrof_macro.rs
@@ -1,10 +1,13 @@
-macro_rules! m {
-    ($($x:tt),*) => { &[$(($x, stringify!(x)),)*] };
-}
+// aux-build:proc_macros.rs
+
+#![warn(clippy::deref_addrof)]
+
+extern crate proc_macros;
 
-#[warn(clippy::deref_addrof)]
-fn f() -> [(i32, &'static str); 3] {
-    *m![1, 2, 3] // should be fine
+#[proc_macros::inline_macros]
+fn f() -> i32 {
+    // should be fine
+    *inline!(&$1)
 }
 
 fn main() {}
diff --git a/tests/ui/doc_unsafe.rs b/tests/ui/doc_unsafe.rs
index b91f7aa0dd8..30674ce3708 100644
--- a/tests/ui/doc_unsafe.rs
+++ b/tests/ui/doc_unsafe.rs
@@ -1,9 +1,9 @@
-// aux-build:doc_unsafe_macros.rs
+// aux-build:proc_macros.rs
 
 #![allow(clippy::let_unit_value)]
 
-#[macro_use]
-extern crate doc_unsafe_macros;
+extern crate proc_macros;
+use proc_macros::external;
 
 /// This is not sufficiently documented
 pub unsafe fn destroy_the_planet() {
@@ -105,7 +105,11 @@ macro_rules! very_unsafe {
 very_unsafe!();
 
 // we don't lint code from external macros
-undocd_unsafe!();
+external! {
+    pub unsafe fn oy_vey() {
+        unimplemented!();
+    }
+}
 
 fn main() {
     unsafe {
diff --git a/tests/ui/empty_loop.rs b/tests/ui/empty_loop.rs
index 8fd7697eb3b..6a8e6b550c1 100644
--- a/tests/ui/empty_loop.rs
+++ b/tests/ui/empty_loop.rs
@@ -1,9 +1,9 @@
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::empty_loop)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 fn should_trigger() {
     loop {}
@@ -16,6 +16,7 @@ fn should_trigger() {
     }
 }
 
+#[inline_macros]
 fn should_not_trigger() {
     loop {
         panic!("This is fine")
@@ -38,14 +39,10 @@ fn should_not_trigger() {
     loop {}
 
     // We don't lint loops inside macros
-    macro_rules! foo {
-        () => {
-            loop {}
-        };
-    }
+    inline!(loop {});
 
     // We don't lint external macros
-    foofoo!()
+    external!(loop {});
 }
 
 fn main() {}
diff --git a/tests/ui/equatable_if_let.fixed b/tests/ui/equatable_if_let.fixed
index 9af2ba96272..007702ab550 100644
--- a/tests/ui/equatable_if_let.fixed
+++ b/tests/ui/equatable_if_let.fixed
@@ -1,11 +1,11 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
 #![warn(clippy::equatable_if_let)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 use std::cmp::Ordering;
 
@@ -44,6 +44,7 @@ impl PartialEq for NotStructuralEq {
     }
 }
 
+#[inline_macros]
 fn main() {
     let a = 2;
     let b = 3;
@@ -78,14 +79,9 @@ fn main() {
     if Some(g) == Some(NotStructuralEq::A) {}
     if matches!(h, NoPartialEqStruct { a: 2, b: false }) {}
 
-    macro_rules! m1 {
-        (x) => {
-            "abc"
-        };
-    }
-    if "abc" == m1!(x) {
+    if "abc" == inline!("abc") {
         println!("OK");
     }
 
-    equatable_if_let!(a);
+    external!({ if let 2 = $a {} });
 }
diff --git a/tests/ui/equatable_if_let.rs b/tests/ui/equatable_if_let.rs
index c3626c081dd..3bda7977645 100644
--- a/tests/ui/equatable_if_let.rs
+++ b/tests/ui/equatable_if_let.rs
@@ -1,11 +1,11 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![allow(unused_variables, dead_code, clippy::derive_partial_eq_without_eq)]
 #![warn(clippy::equatable_if_let)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 use std::cmp::Ordering;
 
@@ -44,6 +44,7 @@ impl PartialEq for NotStructuralEq {
     }
 }
 
+#[inline_macros]
 fn main() {
     let a = 2;
     let b = 3;
@@ -78,14 +79,9 @@ fn main() {
     if let Some(NotStructuralEq::A) = Some(g) {}
     if let NoPartialEqStruct { a: 2, b: false } = h {}
 
-    macro_rules! m1 {
-        (x) => {
-            "abc"
-        };
-    }
-    if let m1!(x) = "abc" {
+    if let inline!("abc") = "abc" {
         println!("OK");
     }
 
-    equatable_if_let!(a);
+    external!({ if let 2 = $a {} });
 }
diff --git a/tests/ui/equatable_if_let.stderr b/tests/ui/equatable_if_let.stderr
index 40ca75b8da2..a72d87bb7ba 100644
--- a/tests/ui/equatable_if_let.stderr
+++ b/tests/ui/equatable_if_let.stderr
@@ -1,5 +1,5 @@
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:59:8
+  --> $DIR/equatable_if_let.rs:60:8
    |
 LL |     if let 2 = a {}
    |        ^^^^^^^^^ help: try: `a == 2`
@@ -7,82 +7,82 @@ LL |     if let 2 = a {}
    = note: `-D clippy::equatable-if-let` implied by `-D warnings`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:60:8
+  --> $DIR/equatable_if_let.rs:61:8
    |
 LL |     if let Ordering::Greater = a.cmp(&b) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.cmp(&b) == Ordering::Greater`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:61:8
+  --> $DIR/equatable_if_let.rs:62:8
    |
 LL |     if let Some(2) = c {}
    |        ^^^^^^^^^^^^^^^ help: try: `c == Some(2)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:62:8
+  --> $DIR/equatable_if_let.rs:63:8
    |
 LL |     if let Struct { a: 2, b: false } = d {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `d == (Struct { a: 2, b: false })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:63:8
+  --> $DIR/equatable_if_let.rs:64:8
    |
 LL |     if let Enum::TupleVariant(32, 64) = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::TupleVariant(32, 64)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:64:8
+  --> $DIR/equatable_if_let.rs:65:8
    |
 LL |     if let Enum::RecordVariant { a: 64, b: 32 } = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == (Enum::RecordVariant { a: 64, b: 32 })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:65:8
+  --> $DIR/equatable_if_let.rs:66:8
    |
 LL |     if let Enum::UnitVariant = e {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `e == Enum::UnitVariant`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:66:8
+  --> $DIR/equatable_if_let.rs:67:8
    |
 LL |     if let (Enum::UnitVariant, &Struct { a: 2, b: false }) = (e, &d) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(e, &d) == (Enum::UnitVariant, &Struct { a: 2, b: false })`
 
 error: this pattern matching can be expressed using `matches!`
-  --> $DIR/equatable_if_let.rs:75:8
+  --> $DIR/equatable_if_let.rs:76:8
    |
 LL |     if let NotPartialEq::A = f {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(f, NotPartialEq::A)`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:76:8
+  --> $DIR/equatable_if_let.rs:77:8
    |
 LL |     if let NotStructuralEq::A = g {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `g == NotStructuralEq::A`
 
 error: this pattern matching can be expressed using `matches!`
-  --> $DIR/equatable_if_let.rs:77:8
+  --> $DIR/equatable_if_let.rs:78:8
    |
 LL |     if let Some(NotPartialEq::A) = Some(f) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(Some(f), Some(NotPartialEq::A))`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:78:8
+  --> $DIR/equatable_if_let.rs:79:8
    |
 LL |     if let Some(NotStructuralEq::A) = Some(g) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(g) == Some(NotStructuralEq::A)`
 
 error: this pattern matching can be expressed using `matches!`
-  --> $DIR/equatable_if_let.rs:79:8
+  --> $DIR/equatable_if_let.rs:80:8
    |
 LL |     if let NoPartialEqStruct { a: 2, b: false } = h {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(h, NoPartialEqStruct { a: 2, b: false })`
 
 error: this pattern matching can be expressed using equality
-  --> $DIR/equatable_if_let.rs:86:8
+  --> $DIR/equatable_if_let.rs:82:8
    |
-LL |     if let m1!(x) = "abc" {
-   |        ^^^^^^^^^^^^^^^^^^ help: try: `"abc" == m1!(x)`
+LL |     if let inline!("abc") = "abc" {
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"abc" == inline!("abc")`
 
 error: aborting due to 14 previous errors
 
diff --git a/tests/ui/field_reassign_with_default.rs b/tests/ui/field_reassign_with_default.rs
index 1f989bb1220..0e208b3ed0e 100644
--- a/tests/ui/field_reassign_with_default.rs
+++ b/tests/ui/field_reassign_with_default.rs
@@ -1,12 +1,12 @@
 // aux-build:proc_macro_derive.rs
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::field_reassign_with_default)]
 
 #[macro_use]
 extern crate proc_macro_derive;
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 // Don't lint on derives that derive `Default`
 // See https://github.com/rust-lang/rust-clippy/issues/6545
@@ -36,14 +36,6 @@ struct D {
     b: Option<i32>,
 }
 
-macro_rules! m {
-    ($key:ident: $value:tt) => {{
-        let mut data = $crate::D::default();
-        data.$key = Some($value);
-        data
-    }};
-}
-
 /// Implements .next() that returns a different number each time.
 struct SideEffect(i32);
 
@@ -57,6 +49,7 @@ impl SideEffect {
     }
 }
 
+#[inline_macros]
 fn main() {
     // wrong, produces first error in stderr
     let mut a: A = Default::default();
@@ -150,7 +143,18 @@ fn main() {
     a.i = vec![1];
 
     // Don't lint in external macros
-    field_reassign_with_default!();
+    external! {
+        #[derive(Default)]
+        struct A {
+            pub i: i32,
+            pub j: i64,
+        }
+        fn lint() {
+            let mut a: A = Default::default();
+            a.i = 42;
+            a;
+        }
+    }
 
     // be sure suggestion is correct with generics
     let mut a: Wrapper<bool> = Default::default();
@@ -160,9 +164,11 @@ fn main() {
     a.i = 42;
 
     // Don't lint in macros
-    m! {
-        a: 42
-    };
+    inline!(
+        let mut data = $crate::D::default();
+        data.$a = Some($42);
+        data
+    );
 }
 
 mod m {
diff --git a/tests/ui/field_reassign_with_default.stderr b/tests/ui/field_reassign_with_default.stderr
index 710bb66a48a..da74f9ef9f7 100644
--- a/tests/ui/field_reassign_with_default.stderr
+++ b/tests/ui/field_reassign_with_default.stderr
@@ -1,132 +1,132 @@
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:63:5
+  --> $DIR/field_reassign_with_default.rs:56:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:62:5
+  --> $DIR/field_reassign_with_default.rs:55:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:103:5
+  --> $DIR/field_reassign_with_default.rs:96:5
    |
 LL |     a.j = 43;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { j: 43, i: 42 }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:102:5
+  --> $DIR/field_reassign_with_default.rs:95:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:108:5
+  --> $DIR/field_reassign_with_default.rs:101:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: 42, j: 44 }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:107:5
+  --> $DIR/field_reassign_with_default.rs:100:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:114:5
+  --> $DIR/field_reassign_with_default.rs:107:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:113:5
+  --> $DIR/field_reassign_with_default.rs:106:5
    |
 LL |     let mut a = A::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:124:5
+  --> $DIR/field_reassign_with_default.rs:117:5
    |
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:123:5
+  --> $DIR/field_reassign_with_default.rs:116:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:128:5
+  --> $DIR/field_reassign_with_default.rs:121:5
    |
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `main::A { i: Default::default(), j: 45 }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:127:5
+  --> $DIR/field_reassign_with_default.rs:120:5
    |
 LL |     let mut a: A = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:150:5
+  --> $DIR/field_reassign_with_default.rs:143:5
    |
 LL |     a.i = vec![1];
    |     ^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `C { i: vec![1], ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:149:5
+  --> $DIR/field_reassign_with_default.rs:142:5
    |
 LL |     let mut a: C = C::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:157:5
+  --> $DIR/field_reassign_with_default.rs:161:5
    |
 LL |     a.i = true;
    |     ^^^^^^^^^^^
    |
 note: consider initializing the variable with `Wrapper::<bool> { i: true }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:156:5
+  --> $DIR/field_reassign_with_default.rs:160:5
    |
 LL |     let mut a: Wrapper<bool> = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:160:5
+  --> $DIR/field_reassign_with_default.rs:164:5
    |
 LL |     a.i = 42;
    |     ^^^^^^^^^
    |
 note: consider initializing the variable with `WrapperMulti::<i32, i64> { i: 42, ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:159:5
+  --> $DIR/field_reassign_with_default.rs:163:5
    |
 LL |     let mut a: WrapperMulti<i32, i64> = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:229:13
+  --> $DIR/field_reassign_with_default.rs:235:13
    |
 LL |             f.name = name.len();
    |             ^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `issue6312::ImplDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:228:13
+  --> $DIR/field_reassign_with_default.rs:234:13
    |
 LL |             let mut f = ImplDropAllCopy::default();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: field assignment outside of initializer for an instance created with Default::default()
-  --> $DIR/field_reassign_with_default.rs:245:13
+  --> $DIR/field_reassign_with_default.rs:251:13
    |
 LL |             f.name = name.len();
    |             ^^^^^^^^^^^^^^^^^^^^
    |
 note: consider initializing the variable with `issue6312::NoDropAllCopy { name: name.len(), ..Default::default() }` and removing relevant reassignments
-  --> $DIR/field_reassign_with_default.rs:244:13
+  --> $DIR/field_reassign_with_default.rs:250:13
    |
 LL |             let mut f = NoDropAllCopy::default();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs
index fd96ca3f466..35d08a07bc3 100644
--- a/tests/ui/implicit_hasher.rs
+++ b/tests/ui/implicit_hasher.rs
@@ -1,9 +1,11 @@
-// aux-build:implicit_hasher_macros.rs
+// aux-build:proc_macros.rs
+
 #![deny(clippy::implicit_hasher)]
 #![allow(unused)]
 
 #[macro_use]
-extern crate implicit_hasher_macros;
+extern crate proc_macros;
+use proc_macros::external;
 
 use std::cmp::Eq;
 use std::collections::{HashMap, HashSet};
@@ -68,22 +70,19 @@ impl<S: BuildHasher + Default> Foo<i64> for HashSet<String, S> {
 
 pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
 
-macro_rules! gen {
-    (impl) => {
+#[proc_macros::inline_macros]
+pub mod gen {
+    use super::*;
+    inline! {
         impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> {
             fn make() -> (Self, Self) {
                 (HashMap::new(), HashMap::with_capacity(10))
             }
         }
-    };
 
-    (fn $name:ident) => {
-        pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
-    };
+        pub fn bar(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
+    }
 }
-#[rustfmt::skip]
-gen!(impl);
-gen!(fn bar);
 
 // When the macro is in a different file, the suggestion spans can't be combined properly
 // and should not cause an ICE
@@ -94,7 +93,9 @@ pub mod test_macro;
 __implicit_hasher_test_macro!(impl<K, V> for HashMap<K, V> where V: test_macro::A);
 
 // #4260
-implicit_hasher_fn!();
+external! {
+    pub fn f(input: &HashMap<u32, u32>) {}
+}
 
 // #7712
 pub async fn election_vote(_data: HashMap<i32, i32>) {}
diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr
index 59b0fba2a4c..83b46de2eb5 100644
--- a/tests/ui/implicit_hasher.stderr
+++ b/tests/ui/implicit_hasher.stderr
@@ -1,11 +1,11 @@
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:16:35
+  --> $DIR/implicit_hasher.rs:18:35
    |
 LL | impl<K: Hash + Eq, V> Foo<i8> for HashMap<K, V> {
    |                                   ^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/implicit_hasher.rs:2:9
+  --> $DIR/implicit_hasher.rs:3:9
    |
 LL | #![deny(clippy::implicit_hasher)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |         (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:25:36
+  --> $DIR/implicit_hasher.rs:27:36
    |
 LL | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) {
    |                                    ^^^^^^^^^^^^^
@@ -34,7 +34,7 @@ LL |         ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Defa
    |           ~~~~~~~~~~~~~~~~~~     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:30:19
+  --> $DIR/implicit_hasher.rs:32:19
    |
 LL | impl Foo<i16> for HashMap<String, String> {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@ LL |         (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:47:32
+  --> $DIR/implicit_hasher.rs:49:32
    |
 LL | impl<T: Hash + Eq> Foo<i8> for HashSet<T> {
    |                                ^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |         (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: impl for `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:52:19
+  --> $DIR/implicit_hasher.rs:54:19
    |
 LL | impl Foo<i16> for HashSet<String> {
    |                   ^^^^^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL |         (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default:
    |          ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:69:23
+  --> $DIR/implicit_hasher.rs:71:23
    |
 LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                       ^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _s
    |           +++++++++++++++++++++++++++++            ~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:69:53
+  --> $DIR/implicit_hasher.rs:71:53
    |
 LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
    |                                                     ^^^^^^^^^^^^
@@ -101,15 +101,12 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set:
    |           +++++++++++++++++++++++++++++                                          ~~~~~~~~~~~~~~~
 
 error: impl for `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:73:43
+  --> $DIR/implicit_hasher.rs:77:43
    |
 LL |         impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> {
    |                                           ^^^^^^^^^^^^^
-...
-LL | gen!(impl);
-   | ---------- in this macro invocation
    |
-   = note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_mod_gen` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider adding a type parameter
    |
 LL |         impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<u8> for HashMap<K, V, S> {
@@ -120,37 +117,31 @@ LL |                 (HashMap::default(), HashMap::with_capacity_and_hasher(10,
    |                  ~~~~~~~~~~~~~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:81:33
+  --> $DIR/implicit_hasher.rs:83:31
    |
-LL |         pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
-   |                                 ^^^^^^^^^^^^^^^^^
-...
-LL | gen!(fn bar);
-   | ------------ in this macro invocation
+LL |         pub fn bar(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
+   |                               ^^^^^^^^^^^^^^^^^
    |
-   = note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_mod_gen` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider adding a type parameter
    |
-LL |         pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _set: &mut HashSet<i32>) {}
-   |                     +++++++++++++++++++++++++++++            ~~~~~~~~~~~~~~~~~~~~
+LL |         pub fn bar<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _set: &mut HashSet<i32>) {}
+   |                   +++++++++++++++++++++++++++++            ~~~~~~~~~~~~~~~~~~~~
 
 error: parameter of type `HashSet` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:81:63
+  --> $DIR/implicit_hasher.rs:83:61
    |
-LL |         pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
-   |                                                               ^^^^^^^^^^^^
-...
-LL | gen!(fn bar);
-   | ------------ in this macro invocation
+LL |         pub fn bar(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
+   |                                                             ^^^^^^^^^^^^
    |
-   = note: this error originates in the macro `gen` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_mod_gen` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider adding a type parameter
    |
-LL |         pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32, S>) {}
-   |                     +++++++++++++++++++++++++++++                                          ~~~~~~~~~~~~~~~
+LL |         pub fn bar<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32, S>) {}
+   |                   +++++++++++++++++++++++++++++                                          ~~~~~~~~~~~~~~~
 
 error: parameter of type `HashMap` should be generalized over different hashers
-  --> $DIR/implicit_hasher.rs:100:35
+  --> $DIR/implicit_hasher.rs:101:35
    |
 LL | pub async fn election_vote(_data: HashMap<i32, i32>) {}
    |                                   ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/inconsistent_struct_constructor.fixed b/tests/ui/inconsistent_struct_constructor.fixed
index 74ba2f1c5e7..5aaa00f8517 100644
--- a/tests/ui/inconsistent_struct_constructor.fixed
+++ b/tests/ui/inconsistent_struct_constructor.fixed
@@ -1,10 +1,14 @@
 // run-rustfix
+// aux-build:proc_macros.rs
+
 #![warn(clippy::inconsistent_struct_constructor)]
 #![allow(clippy::redundant_field_names)]
 #![allow(clippy::unnecessary_operation)]
 #![allow(clippy::no_effect)]
 #![allow(dead_code)]
 
+extern crate proc_macros;
+
 #[derive(Default)]
 struct Foo {
     x: i32,
@@ -12,18 +16,10 @@ struct Foo {
     z: i32,
 }
 
-macro_rules! new_foo {
-    () => {
-        let x = 1;
-        let y = 1;
-        let z = 1;
-        Foo { y, x, z }
-    };
-}
-
 mod without_base {
     use super::Foo;
 
+    #[proc_macros::inline_macros]
     fn test() {
         let x = 1;
         let y = 1;
@@ -34,7 +30,12 @@ mod without_base {
 
         // Should NOT lint.
         // issue #7069.
-        new_foo!();
+        inline!({
+            let x = 1;
+            let y = 1;
+            let z = 1;
+            Foo { y, x, z }
+        });
 
         // Should NOT lint because the order is the same as in the definition.
         Foo { x, y, z };
diff --git a/tests/ui/inconsistent_struct_constructor.rs b/tests/ui/inconsistent_struct_constructor.rs
index ba96e1e330f..2b2dd7f59a4 100644
--- a/tests/ui/inconsistent_struct_constructor.rs
+++ b/tests/ui/inconsistent_struct_constructor.rs
@@ -1,10 +1,14 @@
 // run-rustfix
+// aux-build:proc_macros.rs
+
 #![warn(clippy::inconsistent_struct_constructor)]
 #![allow(clippy::redundant_field_names)]
 #![allow(clippy::unnecessary_operation)]
 #![allow(clippy::no_effect)]
 #![allow(dead_code)]
 
+extern crate proc_macros;
+
 #[derive(Default)]
 struct Foo {
     x: i32,
@@ -12,18 +16,10 @@ struct Foo {
     z: i32,
 }
 
-macro_rules! new_foo {
-    () => {
-        let x = 1;
-        let y = 1;
-        let z = 1;
-        Foo { y, x, z }
-    };
-}
-
 mod without_base {
     use super::Foo;
 
+    #[proc_macros::inline_macros]
     fn test() {
         let x = 1;
         let y = 1;
@@ -34,7 +30,12 @@ mod without_base {
 
         // Should NOT lint.
         // issue #7069.
-        new_foo!();
+        inline!({
+            let x = 1;
+            let y = 1;
+            let z = 1;
+            Foo { y, x, z }
+        });
 
         // Should NOT lint because the order is the same as in the definition.
         Foo { x, y, z };
diff --git a/tests/ui/inconsistent_struct_constructor.stderr b/tests/ui/inconsistent_struct_constructor.stderr
index c90189e964f..785a6dc9d53 100644
--- a/tests/ui/inconsistent_struct_constructor.stderr
+++ b/tests/ui/inconsistent_struct_constructor.stderr
@@ -1,5 +1,5 @@
 error: struct constructor field order is inconsistent with struct definition field order
-  --> $DIR/inconsistent_struct_constructor.rs:33:9
+  --> $DIR/inconsistent_struct_constructor.rs:29:9
    |
 LL |         Foo { y, x, z };
    |         ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }`
@@ -7,7 +7,7 @@ LL |         Foo { y, x, z };
    = note: `-D clippy::inconsistent-struct-constructor` implied by `-D warnings`
 
 error: struct constructor field order is inconsistent with struct definition field order
-  --> $DIR/inconsistent_struct_constructor.rs:55:9
+  --> $DIR/inconsistent_struct_constructor.rs:56:9
    |
 LL | /         Foo {
 LL | |             z,
diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs
index 3b96f09d7b1..f09f8ae0ccc 100644
--- a/tests/ui/large_enum_variant.rs
+++ b/tests/ui/large_enum_variant.rs
@@ -1,11 +1,11 @@
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![allow(dead_code)]
 #![allow(unused_variables)]
 #![warn(clippy::large_enum_variant)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::external;
 
 enum LargeEnum {
     A(i32),
@@ -155,5 +155,10 @@ enum LargeEnumOfConst {
 }
 
 fn main() {
-    large_enum_variant!();
+    external!(
+        enum LargeEnumInMacro {
+            A(i32),
+            B([i32; 8000]),
+        }
+    );
 }
diff --git a/tests/ui/macro_use_imports.fixed b/tests/ui/macro_use_imports.fixed
index e612480d264..15f7a099a7d 100644
--- a/tests/ui/macro_use_imports.fixed
+++ b/tests/ui/macro_use_imports.fixed
@@ -20,7 +20,7 @@ mod a {
     use mac;
     use mini_mac::ClippyMiniMacroTest;
     use mini_mac;
-    use mac::{inner::foofoo, inner::try_err};
+    use mac::{inner::mut_mut, inner::try_err};
     use mac::inner;
     use mac::inner::nested::string_add;
     use mac::inner::nested;
@@ -36,7 +36,7 @@ mod a {
         let v: ty_macro!() = Vec::default();
 
         inner::try_err!();
-        inner::foofoo!();
+        inner::mut_mut!();
         nested::string_add!();
     }
 }
diff --git a/tests/ui/macro_use_imports.rs b/tests/ui/macro_use_imports.rs
index b34817cc3b2..b1a28733294 100644
--- a/tests/ui/macro_use_imports.rs
+++ b/tests/ui/macro_use_imports.rs
@@ -36,7 +36,7 @@ mod a {
         let v: ty_macro!() = Vec::default();
 
         inner::try_err!();
-        inner::foofoo!();
+        inner::mut_mut!();
         nested::string_add!();
     }
 }
diff --git a/tests/ui/macro_use_imports.stderr b/tests/ui/macro_use_imports.stderr
index 61843124ccd..68d558dede0 100644
--- a/tests/ui/macro_use_imports.stderr
+++ b/tests/ui/macro_use_imports.stderr
@@ -16,7 +16,7 @@ error: `macro_use` attributes are no longer needed in the Rust 2018 edition
   --> $DIR/macro_use_imports.rs:23:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::mut_mut, inner::try_err};`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
   --> $DIR/macro_use_imports.rs:19:5
diff --git a/tests/ui/macro_use_imports_expect.rs b/tests/ui/macro_use_imports_expect.rs
index 8a1b05da9ef..5aac5af26db 100644
--- a/tests/ui/macro_use_imports_expect.rs
+++ b/tests/ui/macro_use_imports_expect.rs
@@ -39,7 +39,7 @@ mod a {
         let v: ty_macro!() = Vec::default();
 
         inner::try_err!();
-        inner::foofoo!();
+        inner::mut_mut!();
         nested::string_add!();
     }
 }
diff --git a/tests/ui/manual_rem_euclid.fixed b/tests/ui/manual_rem_euclid.fixed
index 6916a284a20..1f6df1b0a86 100644
--- a/tests/ui/manual_rem_euclid.fixed
+++ b/tests/ui/manual_rem_euclid.fixed
@@ -1,19 +1,13 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::manual_rem_euclid)]
 #![allow(clippy::let_with_type_underscore)]
 
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! internal_rem_euclid {
-    () => {
-        let value: i32 = 5;
-        let _: i32 = value.rem_euclid(4);
-    };
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
     let value: i32 = 5;
 
@@ -39,10 +33,16 @@ fn main() {
     let _: i32 = ((4 % value) + 4) % 4;
 
     // Lint in internal macros
-    internal_rem_euclid!();
+    inline!(
+        let value: i32 = 5;
+        let _: i32 = value.rem_euclid(4);
+    );
 
     // Do not lint in external macros
-    manual_rem_euclid!();
+    external!(
+        let value: i32 = 5;
+        let _: i32 = ((value % 4) + 4) % 4;
+    );
 }
 
 // Should lint for params too
diff --git a/tests/ui/manual_rem_euclid.rs b/tests/ui/manual_rem_euclid.rs
index 412dbddb426..b275e8a38d2 100644
--- a/tests/ui/manual_rem_euclid.rs
+++ b/tests/ui/manual_rem_euclid.rs
@@ -1,19 +1,13 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::manual_rem_euclid)]
 #![allow(clippy::let_with_type_underscore)]
 
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! internal_rem_euclid {
-    () => {
-        let value: i32 = 5;
-        let _: i32 = ((value % 4) + 4) % 4;
-    };
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
     let value: i32 = 5;
 
@@ -39,10 +33,16 @@ fn main() {
     let _: i32 = ((4 % value) + 4) % 4;
 
     // Lint in internal macros
-    internal_rem_euclid!();
+    inline!(
+        let value: i32 = 5;
+        let _: i32 = ((value % 4) + 4) % 4;
+    );
 
     // Do not lint in external macros
-    manual_rem_euclid!();
+    external!(
+        let value: i32 = 5;
+        let _: i32 = ((value % 4) + 4) % 4;
+    );
 }
 
 // Should lint for params too
diff --git a/tests/ui/manual_rem_euclid.stderr b/tests/ui/manual_rem_euclid.stderr
index 6d06654638b..a43707f89c4 100644
--- a/tests/ui/manual_rem_euclid.stderr
+++ b/tests/ui/manual_rem_euclid.stderr
@@ -1,5 +1,5 @@
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:20:18
+  --> $DIR/manual_rem_euclid.rs:14:18
    |
 LL |     let _: i32 = ((value % 4) + 4) % 4;
    |                  ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
@@ -7,39 +7,36 @@ LL |     let _: i32 = ((value % 4) + 4) % 4;
    = note: `-D clippy::manual-rem-euclid` implied by `-D warnings`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:21:18
+  --> $DIR/manual_rem_euclid.rs:15:18
    |
 LL |     let _: i32 = (4 + (value % 4)) % 4;
    |                  ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:22:18
+  --> $DIR/manual_rem_euclid.rs:16:18
    |
 LL |     let _: i32 = (value % 4 + 4) % 4;
    |                  ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:23:18
+  --> $DIR/manual_rem_euclid.rs:17:18
    |
 LL |     let _: i32 = (4 + value % 4) % 4;
    |                  ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:24:22
+  --> $DIR/manual_rem_euclid.rs:18:22
    |
 LL |     let _: i32 = 1 + (4 + value % 4) % 4;
    |                      ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
 
 error: manual `rem_euclid` implementation
-  --> $DIR/manual_rem_euclid.rs:13:22
+  --> $DIR/manual_rem_euclid.rs:38:22
    |
 LL |         let _: i32 = ((value % 4) + 4) % 4;
    |                      ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
-...
-LL |     internal_rem_euclid!();
-   |     ---------------------- in this macro invocation
    |
-   = note: this error originates in the macro `internal_rem_euclid` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: manual `rem_euclid` implementation
   --> $DIR/manual_rem_euclid.rs:50:5
diff --git a/tests/ui/mem_replace_macro.rs b/tests/ui/mem_replace_macro.rs
index 0c09344b80d..3932e7d00c1 100644
--- a/tests/ui/mem_replace_macro.rs
+++ b/tests/ui/mem_replace_macro.rs
@@ -1,21 +1,12 @@
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 #![warn(clippy::mem_replace_with_default)]
 
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! take {
-    ($s:expr) => {
-        std::mem::replace($s, Default::default())
-    };
-}
-
-fn replace_with_default() {
-    let s = &mut String::from("foo");
-    take!(s);
-    take_external!(s);
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
-    replace_with_default();
+    let s = &mut String::from("foo");
+    inline!(std::mem::replace($s, Default::default()));
+    external!(std::mem::replace($s, Default::default()));
 }
diff --git a/tests/ui/mem_replace_macro.stderr b/tests/ui/mem_replace_macro.stderr
index dd69ab8b5ef..35dda93da3d 100644
--- a/tests/ui/mem_replace_macro.stderr
+++ b/tests/ui/mem_replace_macro.stderr
@@ -1,14 +1,11 @@
 error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
-  --> $DIR/mem_replace_macro.rs:9:9
+  --> $DIR/mem_replace_macro.rs:10:13
    |
-LL |         std::mem::replace($s, Default::default())
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     take!(s);
-   |     -------- in this macro invocation
+LL |     inline!(std::mem::replace($s, Default::default()));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::mem-replace-with-default` implied by `-D warnings`
-   = note: this error originates in the macro `take` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs
index 75cace18167..e6f88c6e622 100644
--- a/tests/ui/missing_const_for_fn/cant_be_const.rs
+++ b/tests/ui/missing_const_for_fn/cant_be_const.rs
@@ -3,15 +3,15 @@
 //! The .stderr output of this test should be empty. Otherwise it's a bug somewhere.
 
 // aux-build:helper.rs
-// aux-build:../../auxiliary/proc_macro_with_span.rs
+// aux-build:../../auxiliary/proc_macros.rs
 
 #![warn(clippy::missing_const_for_fn)]
 #![feature(start)]
 
 extern crate helper;
-extern crate proc_macro_with_span;
+extern crate proc_macros;
 
-use proc_macro_with_span::with_span;
+use proc_macros::with_span;
 
 struct Game;
 
diff --git a/tests/ui/missing_doc.rs b/tests/ui/missing_doc.rs
index 590ad63c90b..5752048949c 100644
--- a/tests/ui/missing_doc.rs
+++ b/tests/ui/missing_doc.rs
@@ -1,5 +1,5 @@
 // needs-asm-support
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 
 #![warn(clippy::missing_docs_in_private_items)]
 // When denying at the crate level, be sure to not get random warnings from the
@@ -8,9 +8,9 @@
 //! Some garbage docs for the crate here
 #![doc = "More garbage"]
 
-extern crate proc_macro_with_span;
+extern crate proc_macros;
 
-use proc_macro_with_span::with_span;
+use proc_macros::with_span;
 use std::arch::global_asm;
 
 type Typedef = String;
diff --git a/tests/ui/missing_doc_impl.rs b/tests/ui/missing_doc_impl.rs
index 0396d1193ff..e2d49b0907d 100644
--- a/tests/ui/missing_doc_impl.rs
+++ b/tests/ui/missing_doc_impl.rs
@@ -1,4 +1,4 @@
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 
 #![warn(clippy::missing_docs_in_private_items)]
 #![allow(dead_code)]
@@ -7,8 +7,8 @@
 //! Some garbage docs for the crate here
 #![doc = "More garbage"]
 
-extern crate proc_macro_with_span;
-use proc_macro_with_span::with_span;
+extern crate proc_macros;
+use proc_macros::with_span;
 
 struct Foo {
     a: isize,
diff --git a/tests/ui/mistyped_literal_suffix.fixed b/tests/ui/mistyped_literal_suffix.fixed
index becb9562a84..9a47d7c56ed 100644
--- a/tests/ui/mistyped_literal_suffix.fixed
+++ b/tests/ui/mistyped_literal_suffix.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 
 #![allow(
     dead_code,
@@ -10,8 +10,8 @@
     clippy::unusual_byte_groupings
 )]
 
-extern crate proc_macro_with_span;
-use proc_macro_with_span::with_span;
+extern crate proc_macros;
+use proc_macros::with_span;
 
 fn main() {
     let fail14 = 2_i32;
diff --git a/tests/ui/mistyped_literal_suffix.rs b/tests/ui/mistyped_literal_suffix.rs
index ee841bcd7e4..04261cba55a 100644
--- a/tests/ui/mistyped_literal_suffix.rs
+++ b/tests/ui/mistyped_literal_suffix.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 
 #![allow(
     dead_code,
@@ -10,8 +10,8 @@
     clippy::unusual_byte_groupings
 )]
 
-extern crate proc_macro_with_span;
-use proc_macro_with_span::with_span;
+extern crate proc_macros;
+use proc_macros::with_span;
 
 fn main() {
     let fail14 = 2_32;
diff --git a/tests/ui/multiple_unsafe_ops_per_block.rs b/tests/ui/multiple_unsafe_ops_per_block.rs
index 5073685c9f0..9082f1675a8 100644
--- a/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -1,12 +1,12 @@
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 #![allow(unused)]
 #![allow(deref_nullptr)]
 #![allow(clippy::unnecessary_operation)]
 #![allow(clippy::drop_copy)]
 #![warn(clippy::multiple_unsafe_ops_per_block)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::external;
 
 use core::arch::asm;
 
@@ -113,7 +113,10 @@ unsafe fn read_char_good(ptr: *const u8) -> char {
 
 // no lint
 fn issue10259() {
-    unsafe_macro!();
+    external!(unsafe {
+        *core::ptr::null::<()>();
+        *core::ptr::null::<()>();
+    });
 }
 
 fn _fn_ptr(x: unsafe fn()) {
diff --git a/tests/ui/multiple_unsafe_ops_per_block.stderr b/tests/ui/multiple_unsafe_ops_per_block.stderr
index e0c1d3801f7..badc284ec42 100644
--- a/tests/ui/multiple_unsafe_ops_per_block.stderr
+++ b/tests/ui/multiple_unsafe_ops_per_block.stderr
@@ -126,7 +126,7 @@ LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |                                       ^^^^^^^^^^^^^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> $DIR/multiple_unsafe_ops_per_block.rs:120:5
+  --> $DIR/multiple_unsafe_ops_per_block.rs:123:5
    |
 LL | /     unsafe {
 LL | |         x();
@@ -135,18 +135,18 @@ LL | |     }
    | |_____^
    |
 note: unsafe function call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:121:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:124:9
    |
 LL |         x();
    |         ^^^
 note: unsafe function call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:122:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:125:9
    |
 LL |         x();
    |         ^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> $DIR/multiple_unsafe_ops_per_block.rs:131:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:134:9
    |
 LL | /         unsafe {
 LL | |             T::X();
@@ -155,18 +155,18 @@ LL | |         }
    | |_________^
    |
 note: unsafe function call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:132:13
+  --> $DIR/multiple_unsafe_ops_per_block.rs:135:13
    |
 LL |             T::X();
    |             ^^^^^^
 note: unsafe function call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:133:13
+  --> $DIR/multiple_unsafe_ops_per_block.rs:136:13
    |
 LL |             T::X();
    |             ^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> $DIR/multiple_unsafe_ops_per_block.rs:141:5
+  --> $DIR/multiple_unsafe_ops_per_block.rs:144:5
    |
 LL | /     unsafe {
 LL | |         x.0();
@@ -175,12 +175,12 @@ LL | |     }
    | |_____^
    |
 note: unsafe function call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:142:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:145:9
    |
 LL |         x.0();
    |         ^^^^^
 note: unsafe function call occurs here
-  --> $DIR/multiple_unsafe_ops_per_block.rs:143:9
+  --> $DIR/multiple_unsafe_ops_per_block.rs:146:9
    |
 LL |         x.0();
    |         ^^^^^
diff --git a/tests/ui/must_use_unit.fixed b/tests/ui/must_use_unit.fixed
index 6c9aa434ac0..b7d375ff80e 100644
--- a/tests/ui/must_use_unit.fixed
+++ b/tests/ui/must_use_unit.fixed
@@ -1,11 +1,11 @@
 //run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::must_use_unit)]
 #![allow(clippy::unused_unit)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::external;
 
 
 pub fn must_use_default() {}
@@ -22,5 +22,8 @@ fn main() {
     must_use_with_note();
 
     // We should not lint in external macros
-    must_use_unit!();
+    external!(
+        #[must_use]
+        fn foo() {}
+    );
 }
diff --git a/tests/ui/must_use_unit.rs b/tests/ui/must_use_unit.rs
index 8a395dc284d..74d6b4ca865 100644
--- a/tests/ui/must_use_unit.rs
+++ b/tests/ui/must_use_unit.rs
@@ -1,11 +1,11 @@
 //run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::must_use_unit)]
 #![allow(clippy::unused_unit)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::external;
 
 #[must_use]
 pub fn must_use_default() {}
@@ -22,5 +22,8 @@ fn main() {
     must_use_with_note();
 
     // We should not lint in external macros
-    must_use_unit!();
+    external!(
+        #[must_use]
+        fn foo() {}
+    );
 }
diff --git a/tests/ui/mut_mut.rs b/tests/ui/mut_mut.rs
index ee3a856566c..06bb085442a 100644
--- a/tests/ui/mut_mut.rs
+++ b/tests/ui/mut_mut.rs
@@ -1,10 +1,10 @@
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 #![warn(clippy::mut_mut)]
 #![allow(unused)]
 #![allow(clippy::no_effect, clippy::uninlined_format_args, clippy::unnecessary_operation)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 fn fun(x: &mut &mut u32) -> bool {
     **x > 0
@@ -21,6 +21,7 @@ macro_rules! mut_ptr {
 }
 
 #[allow(unused_mut, unused_variables)]
+#[inline_macros]
 fn main() {
     let mut x = &mut &mut 1u32;
     {
@@ -37,7 +38,7 @@ fn main() {
         ***y + **x;
     }
 
-    let mut z = mut_ptr!(&mut 3u32);
+    let mut z = inline!(&mut $(&mut 3u32));
 }
 
 fn issue939() {
@@ -55,7 +56,7 @@ fn issue939() {
 
 fn issue6922() {
     // do not lint from an external macro
-    mut_mut!();
+    external!(let mut_mut_ty: &mut &mut u32 = &mut &mut 1u32;);
 }
 
 mod issue9035 {
diff --git a/tests/ui/mut_mut.stderr b/tests/ui/mut_mut.stderr
index 6820a85aa54..93b857eb207 100644
--- a/tests/ui/mut_mut.stderr
+++ b/tests/ui/mut_mut.stderr
@@ -7,54 +7,51 @@ LL | fn fun(x: &mut &mut u32) -> bool {
    = note: `-D clippy::mut-mut` implied by `-D warnings`
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> $DIR/mut_mut.rs:25:17
+  --> $DIR/mut_mut.rs:26:17
    |
 LL |     let mut x = &mut &mut 1u32;
    |                 ^^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> $DIR/mut_mut.rs:19:9
+  --> $DIR/mut_mut.rs:41:25
    |
-LL |         &mut $p
-   |         ^^^^^^^
-...
-LL |     let mut z = mut_ptr!(&mut 3u32);
-   |                 ------------------- in this macro invocation
+LL |     let mut z = inline!(&mut $(&mut 3u32));
+   |                         ^
    |
-   = note: this error originates in the macro `mut_ptr` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this expression mutably borrows a mutable reference. Consider reborrowing
-  --> $DIR/mut_mut.rs:27:21
+  --> $DIR/mut_mut.rs:28:21
    |
 LL |         let mut y = &mut x;
    |                     ^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> $DIR/mut_mut.rs:31:32
+  --> $DIR/mut_mut.rs:32:32
    |
 LL |         let y: &mut &mut u32 = &mut &mut 2;
    |                                ^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> $DIR/mut_mut.rs:31:16
+  --> $DIR/mut_mut.rs:32:16
    |
 LL |         let y: &mut &mut u32 = &mut &mut 2;
    |                ^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> $DIR/mut_mut.rs:36:37
+  --> $DIR/mut_mut.rs:37:37
    |
 LL |         let y: &mut &mut &mut u32 = &mut &mut &mut 2;
    |                                     ^^^^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> $DIR/mut_mut.rs:36:16
+  --> $DIR/mut_mut.rs:37:16
    |
 LL |         let y: &mut &mut &mut u32 = &mut &mut &mut 2;
    |                ^^^^^^^^^^^^^^^^^^
 
 error: generally you want to avoid `&mut &mut _` if possible
-  --> $DIR/mut_mut.rs:36:21
+  --> $DIR/mut_mut.rs:37:21
    |
 LL |         let y: &mut &mut &mut u32 = &mut &mut &mut 2;
    |                     ^^^^^^^^^^^^^
diff --git a/tests/ui/needless_late_init.fixed b/tests/ui/needless_late_init.fixed
index 17f2227ba91..86d899bb46c 100644
--- a/tests/ui/needless_late_init.fixed
+++ b/tests/ui/needless_late_init.fixed
@@ -1,4 +1,5 @@
 // run-rustfix
+// aux-build:proc_macros.rs
 #![feature(let_chains)]
 #![allow(unused)]
 #![allow(
@@ -10,6 +11,8 @@
     clippy::uninlined_format_args
 )]
 
+extern crate proc_macros;
+
 use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
 use std::rc::Rc;
 
@@ -138,6 +141,7 @@ const fn in_const() -> &'static str {
     a
 }
 
+#[proc_macros::inline_macros]
 fn does_not_lint() {
     let z;
     if false {
@@ -195,35 +199,27 @@ fn does_not_lint() {
     }
     y = 3;
 
-    macro_rules! assign {
-        ($i:ident) => {
-            $i = 1;
-        };
-    }
     let x;
-    assign!(x);
+    inline!($x = 1;);
 
     let x;
     if true {
-        assign!(x);
+        inline!($x = 1;);
     } else {
         x = 2;
     }
 
-    macro_rules! in_macro {
-        () => {
-            let x;
-            x = 1;
+    inline!({
+        let x;
+        x = 1;
 
-            let x;
-            if true {
-                x = 1;
-            } else {
-                x = 2;
-            }
-        };
-    }
-    in_macro!();
+        let x;
+        if true {
+            x = 1;
+        } else {
+            x = 2;
+        }
+    });
 
     // ignore if-lets - https://github.com/rust-lang/rust-clippy/issues/8613
     let x;
diff --git a/tests/ui/needless_late_init.rs b/tests/ui/needless_late_init.rs
index d84457a2987..969afb38edf 100644
--- a/tests/ui/needless_late_init.rs
+++ b/tests/ui/needless_late_init.rs
@@ -1,4 +1,5 @@
 // run-rustfix
+// aux-build:proc_macros.rs
 #![feature(let_chains)]
 #![allow(unused)]
 #![allow(
@@ -10,6 +11,8 @@
     clippy::uninlined_format_args
 )]
 
+extern crate proc_macros;
+
 use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
 use std::rc::Rc;
 
@@ -138,6 +141,7 @@ const fn in_const() -> &'static str {
     a
 }
 
+#[proc_macros::inline_macros]
 fn does_not_lint() {
     let z;
     if false {
@@ -195,35 +199,27 @@ fn does_not_lint() {
     }
     y = 3;
 
-    macro_rules! assign {
-        ($i:ident) => {
-            $i = 1;
-        };
-    }
     let x;
-    assign!(x);
+    inline!($x = 1;);
 
     let x;
     if true {
-        assign!(x);
+        inline!($x = 1;);
     } else {
         x = 2;
     }
 
-    macro_rules! in_macro {
-        () => {
-            let x;
-            x = 1;
+    inline!({
+        let x;
+        x = 1;
 
-            let x;
-            if true {
-                x = 1;
-            } else {
-                x = 2;
-            }
-        };
-    }
-    in_macro!();
+        let x;
+        if true {
+            x = 1;
+        } else {
+            x = 2;
+        }
+    });
 
     // ignore if-lets - https://github.com/rust-lang/rust-clippy/issues/8613
     let x;
diff --git a/tests/ui/needless_late_init.stderr b/tests/ui/needless_late_init.stderr
index 0a256fb4a13..eff782f8bf1 100644
--- a/tests/ui/needless_late_init.stderr
+++ b/tests/ui/needless_late_init.stderr
@@ -1,5 +1,5 @@
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:24:5
+  --> $DIR/needless_late_init.rs:27:5
    |
 LL |     let a;
    |     ^^^^^^ created here
@@ -13,7 +13,7 @@ LL |     let a = "zero";
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:27:5
+  --> $DIR/needless_late_init.rs:30:5
    |
 LL |     let b;
    |     ^^^^^^ created here
@@ -27,7 +27,7 @@ LL |     let b = 1;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:28:5
+  --> $DIR/needless_late_init.rs:31:5
    |
 LL |     let c;
    |     ^^^^^^ created here
@@ -41,7 +41,7 @@ LL |     let c = 2;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:32:5
+  --> $DIR/needless_late_init.rs:35:5
    |
 LL |     let d: usize;
    |     ^^^^^^^^^^^^^ created here
@@ -54,7 +54,7 @@ LL |     let d: usize = 1;
    |     ~~~~~~~~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:35:5
+  --> $DIR/needless_late_init.rs:38:5
    |
 LL |     let e;
    |     ^^^^^^ created here
@@ -67,7 +67,7 @@ LL |     let e = format!("{}", d);
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:40:5
+  --> $DIR/needless_late_init.rs:43:5
    |
 LL |     let a;
    |     ^^^^^^
@@ -88,7 +88,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:49:5
+  --> $DIR/needless_late_init.rs:52:5
    |
 LL |     let b;
    |     ^^^^^^
@@ -109,7 +109,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:56:5
+  --> $DIR/needless_late_init.rs:59:5
    |
 LL |     let d;
    |     ^^^^^^
@@ -130,7 +130,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:64:5
+  --> $DIR/needless_late_init.rs:67:5
    |
 LL |     let e;
    |     ^^^^^^
@@ -151,7 +151,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:71:5
+  --> $DIR/needless_late_init.rs:74:5
    |
 LL |     let f;
    |     ^^^^^^
@@ -167,7 +167,7 @@ LL +         1 => "three",
    |
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:77:5
+  --> $DIR/needless_late_init.rs:80:5
    |
 LL |     let g: usize;
    |     ^^^^^^^^^^^^^
@@ -187,7 +187,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:85:5
+  --> $DIR/needless_late_init.rs:88:5
    |
 LL |     let x;
    |     ^^^^^^ created here
@@ -201,7 +201,7 @@ LL |     let x = 1;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:89:5
+  --> $DIR/needless_late_init.rs:92:5
    |
 LL |     let x;
    |     ^^^^^^ created here
@@ -215,7 +215,7 @@ LL |     let x = SignificantDrop;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:93:5
+  --> $DIR/needless_late_init.rs:96:5
    |
 LL |     let x;
    |     ^^^^^^ created here
@@ -229,7 +229,7 @@ LL |     let x = SignificantDrop;
    |     ~~~~~
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:112:5
+  --> $DIR/needless_late_init.rs:115:5
    |
 LL |     let a;
    |     ^^^^^^
@@ -250,7 +250,7 @@ LL |     };
    |      +
 
 error: unneeded late initialization
-  --> $DIR/needless_late_init.rs:129:5
+  --> $DIR/needless_late_init.rs:132:5
    |
 LL |     let a;
    |     ^^^^^^
diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed
index f0f1f9298ac..e6ead69d148 100644
--- a/tests/ui/needless_lifetimes.fixed
+++ b/tests/ui/needless_lifetimes.fixed
@@ -1,5 +1,5 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::needless_lifetimes)]
 #![allow(
@@ -12,8 +12,8 @@
     clippy::get_first
 )]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::inline_macros;
 
 fn distinct_lifetimes(_x: &u8, _y: &u8, _z: u8) {}
 
@@ -502,30 +502,29 @@ mod pr_9743_output_lifetime_checks {
     }
 }
 
+#[inline_macros]
 mod in_macro {
-    macro_rules! local_one_input_macro {
-        () => {
-            fn one_input(x: &u8) -> &u8 {
-                unimplemented!()
-            }
-        };
-    }
+    use proc_macros::external;
 
     // lint local macro expands to function with needless lifetimes
-    local_one_input_macro!();
+    inline! {
+        fn one_input(x: &u8) -> &u8 {
+            unimplemented!()
+        }
+    }
 
     // no lint on external macro
-    macro_rules::needless_lifetime!();
-
-    macro_rules! expanded_lifetime {
-        ($l:lifetime) => {
-            fn f<$l>(arg: &$l str) -> &$l str {
-                arg
-            }
+    external! {
+        fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 {
+            unimplemented!()
         }
     }
 
-    expanded_lifetime!('a);
+    inline! {
+        fn f<$'a>(arg: &$'a str) -> &$'a str {
+            arg
+        }
+    }
 }
 
 mod issue5787 {
diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs
index ddfd1043003..06eb430506f 100644
--- a/tests/ui/needless_lifetimes.rs
+++ b/tests/ui/needless_lifetimes.rs
@@ -1,5 +1,5 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::needless_lifetimes)]
 #![allow(
@@ -12,8 +12,8 @@
     clippy::get_first
 )]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::inline_macros;
 
 fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {}
 
@@ -502,30 +502,29 @@ mod pr_9743_output_lifetime_checks {
     }
 }
 
+#[inline_macros]
 mod in_macro {
-    macro_rules! local_one_input_macro {
-        () => {
-            fn one_input<'a>(x: &'a u8) -> &'a u8 {
-                unimplemented!()
-            }
-        };
-    }
+    use proc_macros::external;
 
     // lint local macro expands to function with needless lifetimes
-    local_one_input_macro!();
+    inline! {
+        fn one_input<'a>(x: &'a u8) -> &'a u8 {
+            unimplemented!()
+        }
+    }
 
     // no lint on external macro
-    macro_rules::needless_lifetime!();
-
-    macro_rules! expanded_lifetime {
-        ($l:lifetime) => {
-            fn f<$l>(arg: &$l str) -> &$l str {
-                arg
-            }
+    external! {
+        fn needless_lifetime<'a>(x: &'a u8) -> &'a u8 {
+            unimplemented!()
         }
     }
 
-    expanded_lifetime!('a);
+    inline! {
+        fn f<$'a>(arg: &$'a str) -> &$'a str {
+            arg
+        }
+    }
 }
 
 mod issue5787 {
diff --git a/tests/ui/needless_lifetimes.stderr b/tests/ui/needless_lifetimes.stderr
index 4e3c8f20d8c..86acc4e0046 100644
--- a/tests/ui/needless_lifetimes.stderr
+++ b/tests/ui/needless_lifetimes.stderr
@@ -540,19 +540,16 @@ LL +     fn multiple_inputs_output_not_elided<'b>(x: &u8, y: &'b u8, z: &'b u8)
    |
 
 error: the following explicit lifetimes could be elided: 'a
-  --> $DIR/needless_lifetimes.rs:508:13
+  --> $DIR/needless_lifetimes.rs:511:9
    |
-LL |             fn one_input<'a>(x: &'a u8) -> &'a u8 {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     local_one_input_macro!();
-   |     ------------------------ in this macro invocation
+LL |         fn one_input<'a>(x: &'a u8) -> &'a u8 {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: this error originates in the macro `local_one_input_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_mod_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: elide the lifetimes
    |
-LL -             fn one_input<'a>(x: &'a u8) -> &'a u8 {
-LL +             fn one_input(x: &u8) -> &u8 {
+LL -         fn one_input<'a>(x: &'a u8) -> &'a u8 {
+LL +         fn one_input(x: &u8) -> &u8 {
    |
 
 error: aborting due to 46 previous errors
diff --git a/tests/ui/option_env_unwrap.rs b/tests/ui/option_env_unwrap.rs
index 0141fb7856d..9a56cf40d8a 100644
--- a/tests/ui/option_env_unwrap.rs
+++ b/tests/ui/option_env_unwrap.rs
@@ -1,24 +1,16 @@
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 #![warn(clippy::option_env_unwrap)]
 #![allow(clippy::map_flatten)]
 
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! option_env_unwrap {
-    ($env: expr) => {
-        option_env!($env).unwrap()
-    };
-    ($env: expr, $message: expr) => {
-        option_env!($env).expect($message)
-    };
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
     let _ = option_env!("PATH").unwrap();
     let _ = option_env!("PATH").expect("environment variable PATH isn't set");
-    let _ = option_env_unwrap!("PATH");
-    let _ = option_env_unwrap!("PATH", "environment variable PATH isn't set");
-    let _ = option_env_unwrap_external!("PATH");
-    let _ = option_env_unwrap_external!("PATH", "environment variable PATH isn't set");
+    let _ = inline!(option_env!($"PATH").unwrap());
+    let _ = inline!(option_env!($"PATH").expect($"environment variable PATH isn't set"));
+    let _ = external!(option_env!($"PATH").unwrap());
+    let _ = external!(option_env!($"PATH").expect($"environment variable PATH isn't set"));
 }
diff --git a/tests/ui/option_env_unwrap.stderr b/tests/ui/option_env_unwrap.stderr
index bc188a07e9e..7bba62686ee 100644
--- a/tests/ui/option_env_unwrap.stderr
+++ b/tests/ui/option_env_unwrap.stderr
@@ -1,5 +1,5 @@
 error: this will panic at run-time if the environment variable doesn't exist at compile-time
-  --> $DIR/option_env_unwrap.rs:18:13
+  --> $DIR/option_env_unwrap.rs:10:13
    |
 LL |     let _ = option_env!("PATH").unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let _ = option_env!("PATH").unwrap();
    = note: `-D clippy::option-env-unwrap` implied by `-D warnings`
 
 error: this will panic at run-time if the environment variable doesn't exist at compile-time
-  --> $DIR/option_env_unwrap.rs:19:13
+  --> $DIR/option_env_unwrap.rs:11:13
    |
 LL |     let _ = option_env!("PATH").expect("environment variable PATH isn't set");
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,46 +16,40 @@ LL |     let _ = option_env!("PATH").expect("environment variable PATH isn't set
    = help: consider using the `env!` macro instead
 
 error: this will panic at run-time if the environment variable doesn't exist at compile-time
-  --> $DIR/option_env_unwrap.rs:10:9
+  --> $DIR/option_env_unwrap.rs:12:21
    |
-LL |         option_env!($env).unwrap()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     let _ = option_env_unwrap!("PATH");
-   |             -------------------------- in this macro invocation
+LL |     let _ = inline!(option_env!($"PATH").unwrap());
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using the `env!` macro instead
-   = note: this error originates in the macro `option_env_unwrap` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this will panic at run-time if the environment variable doesn't exist at compile-time
-  --> $DIR/option_env_unwrap.rs:13:9
+  --> $DIR/option_env_unwrap.rs:13:21
    |
-LL |         option_env!($env).expect($message)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL |     let _ = option_env_unwrap!("PATH", "environment variable PATH isn't set");
-   |             ----------------------------------------------------------------- in this macro invocation
+LL |     let _ = inline!(option_env!($"PATH").expect($"environment variable PATH isn't set"));
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using the `env!` macro instead
-   = note: this error originates in the macro `option_env_unwrap` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this will panic at run-time if the environment variable doesn't exist at compile-time
-  --> $DIR/option_env_unwrap.rs:22:13
+  --> $DIR/option_env_unwrap.rs:14:13
    |
-LL |     let _ = option_env_unwrap_external!("PATH");
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let _ = external!(option_env!($"PATH").unwrap());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using the `env!` macro instead
-   = note: this error originates in the macro `option_env_unwrap_external` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `external` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this will panic at run-time if the environment variable doesn't exist at compile-time
-  --> $DIR/option_env_unwrap.rs:23:13
+  --> $DIR/option_env_unwrap.rs:15:13
    |
-LL |     let _ = option_env_unwrap_external!("PATH", "environment variable PATH isn't set");
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let _ = external!(option_env!($"PATH").expect($"environment variable PATH isn't set"));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider using the `env!` macro instead
-   = note: this error originates in the macro `option_env_unwrap_external` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `external` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed
index df36a9b842b..ee7b998a0b2 100644
--- a/tests/ui/ptr_as_ptr.fixed
+++ b/tests/ui/ptr_as_ptr.fixed
@@ -1,16 +1,12 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::ptr_as_ptr)]
 
-extern crate macro_rules;
-
-macro_rules! cast_it {
-    ($ptr: ident) => {
-        $ptr.cast::<i32>()
-    };
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
     let ptr: *const u32 = &42_u32;
     let mut_ptr: *mut u32 = &mut 42_u32;
@@ -38,10 +34,10 @@ fn main() {
     let _: *mut i32 = mut_ptr.cast();
 
     // Make sure the lint is triggered inside a macro
-    let _ = cast_it!(ptr);
+    let _ = inline!($ptr.cast::<i32>());
 
     // Do not lint inside macros from external crates
-    let _ = macro_rules::ptr_as_ptr_cast!(ptr);
+    let _ = external!($ptr as *const i32);
 }
 
 #[clippy::msrv = "1.37"]
diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs
index 302c66462d9..c88329ce4ec 100644
--- a/tests/ui/ptr_as_ptr.rs
+++ b/tests/ui/ptr_as_ptr.rs
@@ -1,16 +1,12 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::ptr_as_ptr)]
 
-extern crate macro_rules;
-
-macro_rules! cast_it {
-    ($ptr: ident) => {
-        $ptr as *const i32
-    };
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
     let ptr: *const u32 = &42_u32;
     let mut_ptr: *mut u32 = &mut 42_u32;
@@ -38,10 +34,10 @@ fn main() {
     let _: *mut i32 = mut_ptr as _;
 
     // Make sure the lint is triggered inside a macro
-    let _ = cast_it!(ptr);
+    let _ = inline!($ptr as *const i32);
 
     // Do not lint inside macros from external crates
-    let _ = macro_rules::ptr_as_ptr_cast!(ptr);
+    let _ = external!($ptr as *const i32);
 }
 
 #[clippy::msrv = "1.37"]
diff --git a/tests/ui/ptr_as_ptr.stderr b/tests/ui/ptr_as_ptr.stderr
index a68e1cab6d3..78d733994ac 100644
--- a/tests/ui/ptr_as_ptr.stderr
+++ b/tests/ui/ptr_as_ptr.stderr
@@ -1,5 +1,5 @@
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:18:13
+  --> $DIR/ptr_as_ptr.rs:14:13
    |
 LL |     let _ = ptr as *const i32;
    |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
@@ -7,48 +7,45 @@ LL |     let _ = ptr as *const i32;
    = note: `-D clippy::ptr-as-ptr` implied by `-D warnings`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:19:13
+  --> $DIR/ptr_as_ptr.rs:15:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:24:17
+  --> $DIR/ptr_as_ptr.rs:20:17
    |
 LL |         let _ = *ptr_ptr as *const i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `(*ptr_ptr).cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:37:25
+  --> $DIR/ptr_as_ptr.rs:33:25
    |
 LL |     let _: *const i32 = ptr as *const _;
    |                         ^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:38:23
+  --> $DIR/ptr_as_ptr.rs:34:23
    |
 LL |     let _: *mut i32 = mut_ptr as _;
    |                       ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:10:9
+  --> $DIR/ptr_as_ptr.rs:37:21
    |
-LL |         $ptr as *const i32
-   |         ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
-...
-LL |     let _ = cast_it!(ptr);
-   |             ------------- in this macro invocation
+LL |     let _ = inline!($ptr as *const i32);
+   |                     ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()`
    |
-   = note: this error originates in the macro `cast_it` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:62:13
+  --> $DIR/ptr_as_ptr.rs:58:13
    |
 LL |     let _ = ptr as *const i32;
    |             ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()`
 
 error: `as` casting between raw pointers without changing its mutability
-  --> $DIR/ptr_as_ptr.rs:63:13
+  --> $DIR/ptr_as_ptr.rs:59:13
    |
 LL |     let _ = mut_ptr as *mut i32;
    |             ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()`
diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs
index 5d03f77e932..3c86f41f3a6 100644
--- a/tests/ui/single_match_else.rs
+++ b/tests/ui/single_match_else.rs
@@ -1,9 +1,9 @@
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 #![warn(clippy::single_match_else)]
 #![allow(clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
 
-extern crate proc_macro_with_span;
-use proc_macro_with_span::with_span;
+extern crate proc_macros;
+use proc_macros::with_span;
 
 enum ExprNode {
     ExprAddrOf,
diff --git a/tests/ui/string_add.rs b/tests/ui/string_add.rs
index 16673c01e63..20edbe31fa9 100644
--- a/tests/ui/string_add.rs
+++ b/tests/ui/string_add.rs
@@ -1,7 +1,7 @@
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::external;
 
 #[warn(clippy::string_add)]
 #[allow(clippy::string_add_assign, unused)]
@@ -22,5 +22,8 @@ fn main() {
     x = x + 1;
     assert_eq!(2, x);
 
-    string_add!();
+    external!({
+        let y = "".to_owned();
+        let z = y + "...";
+    });
 }
diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed
index 09fb66ca37e..174c858a47d 100644
--- a/tests/ui/toplevel_ref_arg.fixed
+++ b/tests/ui/toplevel_ref_arg.fixed
@@ -1,17 +1,12 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 #![warn(clippy::toplevel_ref_arg)]
-#![allow(clippy::uninlined_format_args)]
+#![allow(clippy::uninlined_format_args, unused)]
 
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! gen_binding {
-    () => {
-        let _y = &42;
-    };
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
     // Closures should not warn
     let y = |ref x| println!("{:?}", x);
@@ -38,13 +33,8 @@ fn main() {
     for ref _x in 0..10 {}
 
     // lint in macro
-    #[allow(unused)]
-    {
-        gen_binding!();
-    }
+    inline!(let _y = &42;);
 
     // do not lint in external macro
-    {
-        ref_arg_binding!();
-    }
+    external!(let ref _y = 42;);
 }
diff --git a/tests/ui/toplevel_ref_arg.rs b/tests/ui/toplevel_ref_arg.rs
index 9d1f2f81098..4b81a06112f 100644
--- a/tests/ui/toplevel_ref_arg.rs
+++ b/tests/ui/toplevel_ref_arg.rs
@@ -1,17 +1,12 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 #![warn(clippy::toplevel_ref_arg)]
-#![allow(clippy::uninlined_format_args)]
+#![allow(clippy::uninlined_format_args, unused)]
 
-#[macro_use]
-extern crate macro_rules;
-
-macro_rules! gen_binding {
-    () => {
-        let ref _y = 42;
-    };
-}
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
+#[inline_macros]
 fn main() {
     // Closures should not warn
     let y = |ref x| println!("{:?}", x);
@@ -38,13 +33,8 @@ fn main() {
     for ref _x in 0..10 {}
 
     // lint in macro
-    #[allow(unused)]
-    {
-        gen_binding!();
-    }
+    inline!(let ref _y = 42;);
 
     // do not lint in external macro
-    {
-        ref_arg_binding!();
-    }
+    external!(let ref _y = 42;);
 }
diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr
index 9c853020ab0..407c2d9fcd3 100644
--- a/tests/ui/toplevel_ref_arg.stderr
+++ b/tests/ui/toplevel_ref_arg.stderr
@@ -1,5 +1,5 @@
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:20:9
+  --> $DIR/toplevel_ref_arg.rs:15:9
    |
 LL |     let ref _x = 1;
    |     ----^^^^^^----- help: try: `let _x = &1;`
@@ -7,39 +7,36 @@ LL |     let ref _x = 1;
    = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings`
 
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:22:9
+  --> $DIR/toplevel_ref_arg.rs:17:9
    |
 LL |     let ref _y: (&_, u8) = (&1, 2);
    |     ----^^^^^^--------------------- help: try: `let _y: &(&_, u8) = &(&1, 2);`
 
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:24:9
+  --> $DIR/toplevel_ref_arg.rs:19:9
    |
 LL |     let ref _z = 1 + 2;
    |     ----^^^^^^--------- help: try: `let _z = &(1 + 2);`
 
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:26:9
+  --> $DIR/toplevel_ref_arg.rs:21:9
    |
 LL |     let ref mut _z = 1 + 2;
    |     ----^^^^^^^^^^--------- help: try: `let _z = &mut (1 + 2);`
 
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:31:9
+  --> $DIR/toplevel_ref_arg.rs:26:9
    |
 LL |     let ref _x = vec![1, 2, 3];
    |     ----^^^^^^----------------- help: try: `let _x = &vec![1, 2, 3];`
 
 error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
-  --> $DIR/toplevel_ref_arg.rs:11:13
+  --> $DIR/toplevel_ref_arg.rs:36:17
    |
-LL |         let ref _y = 42;
-   |         ----^^^^^^------ help: try: `let _y = &42;`
-...
-LL |         gen_binding!();
-   |         -------------- in this macro invocation
+LL |     inline!(let ref _y = 42;);
+   |             ----^^^^^^------ help: try: `let _y = &42;`
    |
-   = note: this error originates in the macro `gen_binding` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/toplevel_ref_arg_non_rustfix.rs b/tests/ui/toplevel_ref_arg_non_rustfix.rs
index 1a493fbce0e..2047593e7e4 100644
--- a/tests/ui/toplevel_ref_arg_non_rustfix.rs
+++ b/tests/ui/toplevel_ref_arg_non_rustfix.rs
@@ -1,33 +1,27 @@
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![warn(clippy::toplevel_ref_arg)]
 #![allow(unused)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 fn the_answer(ref mut x: u8) {
     *x = 42;
 }
 
-macro_rules! gen_function {
-    () => {
-        fn fun_example(ref _x: usize) {}
-    };
-}
-
+#[inline_macros]
 fn main() {
     let mut x = 0;
     the_answer(x);
 
     // lint in macro
-    #[allow(unused)]
-    {
-        gen_function!();
+    inline! {
+        fn fun_example(ref _x: usize) {}
     }
 
     // do not lint in external macro
-    {
-        ref_arg_function!();
+    external! {
+        fn fun_example2(ref _x: usize) {}
     }
 }
diff --git a/tests/ui/toplevel_ref_arg_non_rustfix.stderr b/tests/ui/toplevel_ref_arg_non_rustfix.stderr
index e97011c7fd5..7307bd599d9 100644
--- a/tests/ui/toplevel_ref_arg_non_rustfix.stderr
+++ b/tests/ui/toplevel_ref_arg_non_rustfix.stderr
@@ -7,15 +7,12 @@ LL | fn the_answer(ref mut x: u8) {
    = note: `-D clippy::toplevel-ref-arg` implied by `-D warnings`
 
 error: `ref` directly on a function argument is ignored. Consider using a reference type instead
-  --> $DIR/toplevel_ref_arg_non_rustfix.rs:15:24
+  --> $DIR/toplevel_ref_arg_non_rustfix.rs:20:24
    |
 LL |         fn fun_example(ref _x: usize) {}
    |                        ^^^^^^
-...
-LL |         gen_function!();
-   |         --------------- in this macro invocation
    |
-   = note: this error originates in the macro `gen_function` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/try_err.fixed b/tests/ui/try_err.fixed
index 264194419c7..dc497b1690f 100644
--- a/tests/ui/try_err.fixed
+++ b/tests/ui/try_err.fixed
@@ -1,11 +1,11 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![deny(clippy::try_err)]
 #![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 use std::io;
 use std::task::Poll;
@@ -79,36 +79,22 @@ fn nested_error() -> Result<i32, i32> {
     Ok(1)
 }
 
-// Bad suggestion when in macro (see #6242)
-macro_rules! try_validation {
-    ($e: expr) => {{
-        match $e {
+#[inline_macros]
+fn calling_macro() -> Result<i32, i32> {
+    // macro
+    inline!(
+        match $(Ok::<_, i32>(5)) {
             Ok(_) => 0,
             Err(_) => return Err(1),
         }
-    }};
-}
-
-macro_rules! ret_one {
-    () => {
-        1
-    };
-}
-
-macro_rules! try_validation_in_macro {
-    ($e: expr) => {{
-        match $e {
+    );
+    // `Err` arg is another macro
+    inline!(
+        match $(Ok::<_, i32>(5)) {
             Ok(_) => 0,
-            Err(_) => return Err(ret_one!()),
+            Err(_) => return Err(inline!(1)),
         }
-    }};
-}
-
-fn calling_macro() -> Result<i32, i32> {
-    // macro
-    try_validation!(Ok::<_, i32>(5));
-    // `Err` arg is another macro
-    try_validation_in_macro!(Ok::<_, i32>(5));
+    );
     Ok(5)
 }
 
@@ -121,24 +107,19 @@ fn main() {
     calling_macro().unwrap();
 
     // We don't want to lint in external macros
-    try_err!();
-}
-
-macro_rules! bar {
-    () => {
-        String::from("aasdfasdfasdfa")
-    };
-}
-
-macro_rules! foo {
-    () => {
-        bar!()
-    };
+    external! {
+        pub fn try_err_fn() -> Result<i32, i32> {
+            let err: i32 = 1;
+            // To avoid warnings during rustfix
+            if true { Err(err)? } else { Ok(2) }
+        }
+    }
 }
 
+#[inline_macros]
 pub fn macro_inside(fail: bool) -> Result<i32, String> {
     if fail {
-        return Err(foo!());
+        return Err(inline!(inline!(String::from("aasdfasdfasdfa"))));
     }
     Ok(0)
 }
diff --git a/tests/ui/try_err.rs b/tests/ui/try_err.rs
index bc6979bf457..86aeb75cd96 100644
--- a/tests/ui/try_err.rs
+++ b/tests/ui/try_err.rs
@@ -1,11 +1,11 @@
 // run-rustfix
-// aux-build:macro_rules.rs
+// aux-build:proc_macros.rs
 
 #![deny(clippy::try_err)]
 #![allow(clippy::unnecessary_wraps, clippy::needless_question_mark)]
 
-#[macro_use]
-extern crate macro_rules;
+extern crate proc_macros;
+use proc_macros::{external, inline_macros};
 
 use std::io;
 use std::task::Poll;
@@ -79,36 +79,22 @@ fn nested_error() -> Result<i32, i32> {
     Ok(1)
 }
 
-// Bad suggestion when in macro (see #6242)
-macro_rules! try_validation {
-    ($e: expr) => {{
-        match $e {
+#[inline_macros]
+fn calling_macro() -> Result<i32, i32> {
+    // macro
+    inline!(
+        match $(Ok::<_, i32>(5)) {
             Ok(_) => 0,
             Err(_) => Err(1)?,
         }
-    }};
-}
-
-macro_rules! ret_one {
-    () => {
-        1
-    };
-}
-
-macro_rules! try_validation_in_macro {
-    ($e: expr) => {{
-        match $e {
+    );
+    // `Err` arg is another macro
+    inline!(
+        match $(Ok::<_, i32>(5)) {
             Ok(_) => 0,
-            Err(_) => Err(ret_one!())?,
+            Err(_) => Err(inline!(1))?,
         }
-    }};
-}
-
-fn calling_macro() -> Result<i32, i32> {
-    // macro
-    try_validation!(Ok::<_, i32>(5));
-    // `Err` arg is another macro
-    try_validation_in_macro!(Ok::<_, i32>(5));
+    );
     Ok(5)
 }
 
@@ -121,24 +107,19 @@ fn main() {
     calling_macro().unwrap();
 
     // We don't want to lint in external macros
-    try_err!();
-}
-
-macro_rules! bar {
-    () => {
-        String::from("aasdfasdfasdfa")
-    };
-}
-
-macro_rules! foo {
-    () => {
-        bar!()
-    };
+    external! {
+        pub fn try_err_fn() -> Result<i32, i32> {
+            let err: i32 = 1;
+            // To avoid warnings during rustfix
+            if true { Err(err)? } else { Ok(2) }
+        }
+    }
 }
 
+#[inline_macros]
 pub fn macro_inside(fail: bool) -> Result<i32, String> {
     if fail {
-        Err(foo!())?;
+        Err(inline!(inline!(String::from("aasdfasdfasdfa"))))?;
     }
     Ok(0)
 }
diff --git a/tests/ui/try_err.stderr b/tests/ui/try_err.stderr
index 0cb1328fbfc..4ad0e2e56a4 100644
--- a/tests/ui/try_err.stderr
+++ b/tests/ui/try_err.stderr
@@ -29,53 +29,47 @@ LL |                 Err(err)?;
    |                 ^^^^^^^^^ help: try this: `return Err(err.into())`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:87:23
+  --> $DIR/try_err.rs:88:23
    |
 LL |             Err(_) => Err(1)?,
    |                       ^^^^^^^ help: try this: `return Err(1)`
-...
-LL |     try_validation!(Ok::<_, i32>(5));
-   |     -------------------------------- in this macro invocation
    |
-   = note: this error originates in the macro `try_validation` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_calling_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:102:23
+  --> $DIR/try_err.rs:95:23
    |
-LL |             Err(_) => Err(ret_one!())?,
-   |                       ^^^^^^^^^^^^^^^^ help: try this: `return Err(ret_one!())`
-...
-LL |     try_validation_in_macro!(Ok::<_, i32>(5));
-   |     ----------------------------------------- in this macro invocation
+LL |             Err(_) => Err(inline!(1))?,
+   |                       ^^^^^^^^^^^^^^^^ help: try this: `return Err(inline!(1))`
    |
-   = note: this error originates in the macro `try_validation_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `__inline_mac_fn_calling_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:141:9
+  --> $DIR/try_err.rs:122:9
    |
-LL |         Err(foo!())?;
-   |         ^^^^^^^^^^^^ help: try this: `return Err(foo!())`
+LL |         Err(inline!(inline!(String::from("aasdfasdfasdfa"))))?;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Err(inline!(inline!(String::from("aasdfasdfasdfa"))))`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:148:9
+  --> $DIR/try_err.rs:129:9
    |
 LL |         Err(io::ErrorKind::WriteZero)?
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::ErrorKind::WriteZero.into()))`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:150:9
+  --> $DIR/try_err.rs:131:9
    |
 LL |         Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))?
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error")))`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:158:9
+  --> $DIR/try_err.rs:139:9
    |
 LL |         Err(io::ErrorKind::NotFound)?
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into())))`
 
 error: returning an `Err(_)` with the `?` operator
-  --> $DIR/try_err.rs:167:16
+  --> $DIR/try_err.rs:148:16
    |
 LL |         return Err(42)?;
    |                ^^^^^^^^ help: try this: `Err(42)`
diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed
index cbd5cc5fcee..1475d781c67 100644
--- a/tests/ui/uninlined_format_args.fixed
+++ b/tests/ui/uninlined_format_args.fixed
@@ -1,11 +1,11 @@
-// aux-build:proc_macro_with_span.rs
+// aux-build:proc_macros.rs
 // run-rustfix
 #![warn(clippy::uninlined_format_args)]
 #![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)]
 #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
 
-extern crate proc_macro_with_span;
-use proc_macro_with_span::with_span;
+extern crate proc_macros;
+use proc_macros::with_span;
 
 macro_rules! no_param_str {
     () => {
diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs
index cf0ea5be481..835afac393f 100644
--- a/tests/ui/uninlined_format_args.rs
+++ b/tests/ui/uninlined_format_args.rs
@@ -1,11 +1,11 @@
-// aux-build:proc_macro_with_span.rs
+// aux-build:proc_macros.rs
 // run-rustfix
 #![warn(clippy::uninlined_format_args)]
 #![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)]
 #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
 
-extern crate proc_macro_with_span;
-use proc_macro_with_span::with_span;
+extern crate proc_macros;
+use proc_macros::with_span;
 
 macro_rules! no_param_str {
     () => {
diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs
index 07e70873a81..674ae4f1df9 100644
--- a/tests/ui/unit_arg.rs
+++ b/tests/ui/unit_arg.rs
@@ -1,4 +1,4 @@
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 #![warn(clippy::unit_arg)]
 #![allow(unused_must_use, unused_variables)]
 #![allow(
@@ -13,9 +13,9 @@
     clippy::unused_unit
 )]
 
-extern crate proc_macro_with_span;
+extern crate proc_macros;
 
-use proc_macro_with_span::with_span;
+use proc_macros::with_span;
 use std::fmt::Debug;
 
 fn foo<T: Debug>(t: T) {
diff --git a/tests/ui/unnecessary_lazy_eval.fixed b/tests/ui/unnecessary_lazy_eval.fixed
index 22e9bd8bdc5..3b93800f8b7 100644
--- a/tests/ui/unnecessary_lazy_eval.fixed
+++ b/tests/ui/unnecessary_lazy_eval.fixed
@@ -1,12 +1,12 @@
 // run-rustfix
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 #![warn(clippy::unnecessary_lazy_evaluations)]
 #![allow(clippy::redundant_closure)]
 #![allow(clippy::bind_instead_of_map)]
 #![allow(clippy::map_identity)]
 
-extern crate proc_macro_with_span;
-use proc_macro_with_span::with_span;
+extern crate proc_macros;
+use proc_macros::with_span;
 
 struct Deep(Option<usize>);
 
diff --git a/tests/ui/unnecessary_lazy_eval.rs b/tests/ui/unnecessary_lazy_eval.rs
index 8726d84a23f..2851c0c5190 100644
--- a/tests/ui/unnecessary_lazy_eval.rs
+++ b/tests/ui/unnecessary_lazy_eval.rs
@@ -1,12 +1,12 @@
 // run-rustfix
-// aux-build: proc_macro_with_span.rs
+// aux-build: proc_macros.rs
 #![warn(clippy::unnecessary_lazy_evaluations)]
 #![allow(clippy::redundant_closure)]
 #![allow(clippy::bind_instead_of_map)]
 #![allow(clippy::map_identity)]
 
-extern crate proc_macro_with_span;
-use proc_macro_with_span::with_span;
+extern crate proc_macros;
+use proc_macros::with_span;
 
 struct Deep(Option<usize>);
 
diff --git a/tests/ui/unnecessary_unsafety_doc.rs b/tests/ui/unnecessary_unsafety_doc.rs
index c160e31afd3..431093ab369 100644
--- a/tests/ui/unnecessary_unsafety_doc.rs
+++ b/tests/ui/unnecessary_unsafety_doc.rs
@@ -1,10 +1,10 @@
-// aux-build:doc_unsafe_macros.rs
+// aux-build:proc_macros.rs
 
 #![allow(clippy::let_unit_value)]
 #![warn(clippy::unnecessary_safety_doc)]
 
-#[macro_use]
-extern crate doc_unsafe_macros;
+extern crate proc_macros;
+use proc_macros::external;
 
 /// This is has no safety section, and does not need one either
 pub fn destroy_the_planet() {
@@ -129,7 +129,11 @@ macro_rules! very_safe {
 very_safe!();
 
 // we don't lint code from external macros
-undocd_safe!();
+external!(
+    pub fn vey_oy() {
+        unimplemented!();
+    }
+);
 
 fn main() {}
 
diff --git a/tests/ui/unnecessary_unsafety_doc.stderr b/tests/ui/unnecessary_unsafety_doc.stderr
index 72898c93fa1..b0f20fdac5f 100644
--- a/tests/ui/unnecessary_unsafety_doc.stderr
+++ b/tests/ui/unnecessary_unsafety_doc.stderr
@@ -42,7 +42,7 @@ LL | very_safe!();
    = note: this error originates in the macro `very_safe` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: docs for safe trait have unnecessary `# Safety` section
-  --> $DIR/unnecessary_unsafety_doc.rs:147:1
+  --> $DIR/unnecessary_unsafety_doc.rs:151:1
    |
 LL | pub trait DocumentedSafeTraitWithImplementationHeader {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^