about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/crashes/124833.rs10
-rw-r--r--tests/crashes/124857.rs11
-rw-r--r--tests/crashes/124891.rs22
-rw-r--r--tests/crashes/124894.rs11
-rw-r--r--tests/crashes/125081.rs7
-rw-r--r--tests/crashes/125099.rs24
-rw-r--r--tests/crashes/125155.rs17
-rw-r--r--tests/crashes/125185.rs16
-rw-r--r--tests/crashes/125249.rs8
-rw-r--r--tests/debuginfo/empty-string.rs2
-rw-r--r--tests/debuginfo/pretty-slices.rs4
-rw-r--r--tests/debuginfo/strings-and-strs.rs63
-rw-r--r--tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs2
-rw-r--r--tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs2
-rw-r--r--tests/run-make/rustdoc-scrape-examples-remap/rmake.rs2
-rw-r--r--tests/run-make/rustdoc-scrape-examples-remap/scrape.rs3
-rw-r--r--tests/run-make/rustdoc-scrape-examples-test/Makefile6
-rw-r--r--tests/run-make/rustdoc-scrape-examples-test/rmake.rs6
-rw-r--r--tests/ui/associated-types/associated-types-eq-2.rs2
-rw-r--r--tests/ui/coherence/associated-type2.rs2
-rw-r--r--tests/ui/coroutine/static-move-suggestion.fixed19
-rw-r--r--tests/ui/coroutine/static-move-suggestion.rs19
-rw-r--r--tests/ui/coroutine/static-move-suggestion.stderr26
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr12
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr21
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs60
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr11
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/simple.rs5
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr15
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr15
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs21
-rw-r--r--tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs19
-rw-r--r--tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs2
-rw-r--r--tests/ui/macros/issue-98790.rs24
-rw-r--r--tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs10
-rw-r--r--tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr38
-rw-r--r--tests/ui/parser/label-is-actually-char.rs2
-rw-r--r--tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs2
-rw-r--r--tests/ui/unpretty/auxiliary/data.txt1
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.rs888
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.stdout719
-rw-r--r--tests/ui/unpretty/expanded-interpolation.rs106
-rw-r--r--tests/ui/unpretty/expanded-interpolation.stdout92
-rw-r--r--tests/ui/unpretty/let-else.rs11
-rw-r--r--tests/ui/unpretty/let-else.stdout15
48 files changed, 2288 insertions, 103 deletions
diff --git a/tests/crashes/124833.rs b/tests/crashes/124833.rs
new file mode 100644
index 00000000000..f1c4847b544
--- /dev/null
+++ b/tests/crashes/124833.rs
@@ -0,0 +1,10 @@
+//@ known-bug: rust-lang/rust#124833
+#![feature(generic_const_items)]
+
+trait Trait {
+    const C<'a>: &'a str;
+}
+
+impl Trait for () {
+    const C<'a>:  = "C";
+}
diff --git a/tests/crashes/124857.rs b/tests/crashes/124857.rs
new file mode 100644
index 00000000000..4b952fd64cc
--- /dev/null
+++ b/tests/crashes/124857.rs
@@ -0,0 +1,11 @@
+//@ known-bug: rust-lang/rust#124857
+//@ compile-flags: -Znext-solver=coherence
+
+#![feature(effects)]
+
+#[const_trait]
+trait Foo {}
+
+impl const Foo for i32 {}
+
+impl<T> const Foo for T where T: ~const Foo {}
diff --git a/tests/crashes/124891.rs b/tests/crashes/124891.rs
new file mode 100644
index 00000000000..9b5892418c8
--- /dev/null
+++ b/tests/crashes/124891.rs
@@ -0,0 +1,22 @@
+//@ known-bug: rust-lang/rust#124891
+
+type Tait = impl FnOnce() -> ();
+
+fn reify_as_tait() -> Thunk<Tait> {
+    Thunk::new(|cont| cont)
+}
+
+struct Thunk<F>(F);
+
+impl<F> Thunk<F> {
+    fn new(f: F)
+    where
+        F: ContFn,
+    {
+        todo!();
+    }
+}
+
+trait ContFn {}
+
+impl<F: FnOnce(Tait) -> ()> ContFn for F {}
diff --git a/tests/crashes/124894.rs b/tests/crashes/124894.rs
new file mode 100644
index 00000000000..230cf4a89c1
--- /dev/null
+++ b/tests/crashes/124894.rs
@@ -0,0 +1,11 @@
+//@ known-bug: rust-lang/rust#124894
+//@ compile-flags: -Znext-solver=coherence
+
+#![feature(generic_const_exprs)]
+
+pub trait IsTrue<const mem: bool> {}
+impl<T> IsZST for T where (): IsTrue<{ std::mem::size_of::<T>() == 0 }> {}
+
+pub trait IsZST {}
+
+impl IsZST for IsZST {}
diff --git a/tests/crashes/125081.rs b/tests/crashes/125081.rs
new file mode 100644
index 00000000000..7139caaa00d
--- /dev/null
+++ b/tests/crashes/125081.rs
@@ -0,0 +1,7 @@
+//@ known-bug: rust-lang/rust#125081
+
+use std::cell::Cell;
+
+fn main() {
+    let _: Cell<&str, "a"> = Cell::new('β);
+}
diff --git a/tests/crashes/125099.rs b/tests/crashes/125099.rs
new file mode 100644
index 00000000000..bfc8c8fdcf6
--- /dev/null
+++ b/tests/crashes/125099.rs
@@ -0,0 +1,24 @@
+//@ known-bug: rust-lang/rust#125099
+
+pub trait ContFn<T>: Fn(T) -> Self::Future {
+    type Future;
+}
+impl<T, F> ContFn<T> for F
+where
+    F: Fn(T),
+{
+    type Future = ();
+}
+
+pub trait SeqHandler {
+    type Requires;
+    fn process<F: ContFn<Self::Requires>>() -> impl Sized;
+}
+
+pub struct ConvertToU64;
+impl SeqHandler for ConvertToU64 {
+    type Requires = u64;
+    fn process<F: ContFn<Self::Requires>>() -> impl Sized {}
+}
+
+fn main() {}
diff --git a/tests/crashes/125155.rs b/tests/crashes/125155.rs
new file mode 100644
index 00000000000..165061d4b52
--- /dev/null
+++ b/tests/crashes/125155.rs
@@ -0,0 +1,17 @@
+//@ known-bug: rust-lang/rust#125155
+
+enum NestedEnum {
+    First,
+    Second,
+    Third
+}
+enum Enum {
+    Variant2(Option<*mut &'a &'b ()>)
+}
+
+
+fn foo(x: Enum) -> isize {
+    match x {
+      Enum::Variant2(NestedEnum::Third) => 4,
+    }
+}
diff --git a/tests/crashes/125185.rs b/tests/crashes/125185.rs
new file mode 100644
index 00000000000..8693d6c7662
--- /dev/null
+++ b/tests/crashes/125185.rs
@@ -0,0 +1,16 @@
+//@ known-bug: rust-lang/rust#125185
+//@ compile-flags: -Zvalidate-mir
+
+type Foo = impl Send;
+
+struct A;
+
+const VALUE: Foo = value();
+
+fn test(foo: Foo<'a>, f: impl for<'b> FnMut()) {
+    match VALUE {
+        0 | 0 => {}
+
+        _ => (),
+    }
+}
diff --git a/tests/crashes/125249.rs b/tests/crashes/125249.rs
new file mode 100644
index 00000000000..18196d7b34f
--- /dev/null
+++ b/tests/crashes/125249.rs
@@ -0,0 +1,8 @@
+//@ known-bug: rust-lang/rust#125185
+#![feature(return_position_impl_trait_in_trait, return_type_notation)]
+
+trait IntFactory {
+    fn stream(&self) -> impl IntFactory<stream(): IntFactory<stream(): Send> + Send>;
+}
+
+pub fn main() {}
diff --git a/tests/debuginfo/empty-string.rs b/tests/debuginfo/empty-string.rs
index 36240730e19..35b68ed91c0 100644
--- a/tests/debuginfo/empty-string.rs
+++ b/tests/debuginfo/empty-string.rs
@@ -23,7 +23,7 @@
 // lldb-check:[...] empty_string = "" { vec = size=0 }
 
 // lldb-command:fr v empty_str
-// lldb-check:[...] empty_str = "" { data_ptr = [...] length = 0 }
+// lldb-check:[...] empty_str = ""
 
 fn main() {
     let empty_string = String::new();
diff --git a/tests/debuginfo/pretty-slices.rs b/tests/debuginfo/pretty-slices.rs
index 5d2086fa478..9defa344be0 100644
--- a/tests/debuginfo/pretty-slices.rs
+++ b/tests/debuginfo/pretty-slices.rs
@@ -27,10 +27,10 @@
 // lldb-check:(&mut [i32]) mut_slice = size=4 { [0] = 2 [1] = 3 [2] = 5 [3] = 7 }
 
 // lldb-command:v str_slice
-// lldb-check:(&str) str_slice = "string slice" { data_ptr = [...] length = 12 }
+// lldb-check:(&str) str_slice = "string slice" { [0] = 's' [1] = 't' [2] = 'r' [3] = 'i' [4] = 'n' [5] = 'g' [6] = ' ' [7] = 's' [8] = 'l' [9] = 'i' [10] = 'c' [11] = 'e' }
 
 // lldb-command:v mut_str_slice
-// lldb-check:(&mut str) mut_str_slice = "mutable string slice" { data_ptr = [...] length = 20 }
+// lldb-check:(&mut str) mut_str_slice = "mutable string slice" { [0] = 'm' [1] = 'u' [2] = 't' [3] = 'a' [4] = 'b' [5] = 'l' [6] = 'e' [7] = ' ' [8] = 's' [9] = 't' [10] = 'r' [11] = 'i' [12] = 'n' [13] = 'g' [14] = ' ' [15] = 's' [16] = 'l' [17] = 'i' [18] = 'c' [19] = 'e' }
 
 fn b() {}
 
diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs
new file mode 100644
index 00000000000..48d40d167ba
--- /dev/null
+++ b/tests/debuginfo/strings-and-strs.rs
@@ -0,0 +1,63 @@
+//@ min-gdb-version: 14.0
+//@ min-lldb-version: 1800
+
+//@ compile-flags:-g
+
+// === GDB TESTS ===================================================================================
+// gdb-command:run
+
+// gdb-command:print plain_string
+// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x55555555ab80}, _marker: core::marker::PhantomData<u8>}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, len: 5}}
+
+// gdb-command:print plain_str
+// gdbr-check:$2 = "Hello"
+
+// gdb-command:print str_in_struct
+// gdbr-check:$3 = strings_and_strs::Foo {inner: "Hello"}
+
+// gdb-command:print str_in_tuple
+// gdbr-check:$4 = ("Hello", "World")
+
+// gdb-command:print str_in_rc
+// gdbr-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull<alloc::rc::RcBox<&str>> {pointer: 0x55555555aae0}, phantom: core::marker::PhantomData<alloc::rc::RcBox<&str>>, alloc: alloc::alloc::Global}
+
+
+// === LLDB TESTS ==================================================================================
+// lldb-command:run
+// lldb-command:v plain_string
+// lldbg-check:(alloc::string::String) plain_string = "Hello" { vec = size=5 { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } }
+
+// lldb-command:v plain_str
+// lldbg-check:(&str) plain_str = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' }
+
+// lldb-command:v str_in_struct
+// lldbg-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } }
+
+// lldb-command:v str_in_tuple
+// lldbg-check:((&str, &str)) str_in_tuple = { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } }
+
+// lldb-command:v str_in_rc
+// lldbg-check:(alloc::rc::Rc<&str, alloc::alloc::Global>) str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } }
+
+
+#![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
+#![omit_gdb_pretty_printer_section]
+
+pub struct Foo<'a> {
+    inner: &'a str,
+}
+
+fn main() {
+    let plain_string = String::from("Hello");
+    let plain_str = "Hello";
+    let str_in_struct = Foo { inner: "Hello" };
+    let str_in_tuple = ("Hello", "World");
+
+    let str_in_rc = std::rc::Rc::new("Hello");
+    zzz(); // #break
+}
+
+fn zzz() {
+    ()
+}
diff --git a/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs b/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs
index 537d3e2d724..e9c54fa3922 100644
--- a/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs
+++ b/tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs
@@ -2,5 +2,5 @@
 mod scrape;
 
 fn main() {
-    scrape::scrape();
+    scrape::scrape(&[]);
 }
diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs
index 537d3e2d724..e9c54fa3922 100644
--- a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs
+++ b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs
@@ -2,5 +2,5 @@
 mod scrape;
 
 fn main() {
-    scrape::scrape();
+    scrape::scrape(&[]);
 }
diff --git a/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs b/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs
index d9deaf279ce..4e3b895aef0 100644
--- a/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs
+++ b/tests/run-make/rustdoc-scrape-examples-remap/rmake.rs
@@ -1,5 +1,5 @@
 mod scrape;
 
 fn main() {
-    scrape::scrape();
+    scrape::scrape(&[]);
 }
diff --git a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
index 709388b5492..563e3aca9ae 100644
--- a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
+++ b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
@@ -2,7 +2,7 @@ use run_make_support::{htmldocck, rustc, rustdoc, source_path, tmp_dir};
 use std::fs::read_dir;
 use std::path::Path;
 
-pub fn scrape() {
+pub fn scrape(extra_args: &[&str]) {
     let lib_dir = tmp_dir();
     let out_dir = tmp_dir().join("rustdoc");
     let crate_name = "foobar";
@@ -29,6 +29,7 @@ pub fn scrape() {
             .arg(&out_example)
             .arg("--scrape-examples-target-crate")
             .arg(crate_name)
+            .args(extra_args)
             .run();
         out_deps.push(out_example);
     }
diff --git a/tests/run-make/rustdoc-scrape-examples-test/Makefile b/tests/run-make/rustdoc-scrape-examples-test/Makefile
deleted file mode 100644
index 1235ead6751..00000000000
--- a/tests/run-make/rustdoc-scrape-examples-test/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-extra_flags := --scrape-tests
-deps := ex
-
-include ../rustdoc-scrape-examples-multiple/scrape.mk
-
-all: scrape
diff --git a/tests/run-make/rustdoc-scrape-examples-test/rmake.rs b/tests/run-make/rustdoc-scrape-examples-test/rmake.rs
new file mode 100644
index 00000000000..f96ba113ff7
--- /dev/null
+++ b/tests/run-make/rustdoc-scrape-examples-test/rmake.rs
@@ -0,0 +1,6 @@
+#[path = "../rustdoc-scrape-examples-remap/scrape.rs"]
+mod scrape;
+
+fn main() {
+    scrape::scrape(&["--scrape-tests"]);
+}
diff --git a/tests/ui/associated-types/associated-types-eq-2.rs b/tests/ui/associated-types/associated-types-eq-2.rs
index d71697e9a83..43b0208461e 100644
--- a/tests/ui/associated-types/associated-types-eq-2.rs
+++ b/tests/ui/associated-types/associated-types-eq-2.rs
@@ -4,7 +4,7 @@
 struct Bar;
 struct Qux;
 
-// Tests for a a non generic trait
+// Tests for a non generic trait
 pub trait Tr1 {
     type A;
     fn boo(&self) -> <Self as Tr1>::A;
diff --git a/tests/ui/coherence/associated-type2.rs b/tests/ui/coherence/associated-type2.rs
index 2aadfb04af0..68e98b62953 100644
--- a/tests/ui/coherence/associated-type2.rs
+++ b/tests/ui/coherence/associated-type2.rs
@@ -1,6 +1,6 @@
 //! A regression test for #120343. The overlap error was previously
 //! silenced in coherence because projecting `<() as ToUnit>::Unit`
-//! failed. Then then silenced the missing items error in the `ToUnit`
+//! failed. Then silenced the missing items error in the `ToUnit`
 //! impl, causing us to not emit any errors and ICEing due to a
 //! `span_delay_bug`.
 
diff --git a/tests/ui/coroutine/static-move-suggestion.fixed b/tests/ui/coroutine/static-move-suggestion.fixed
new file mode 100644
index 00000000000..56445be4715
--- /dev/null
+++ b/tests/ui/coroutine/static-move-suggestion.fixed
@@ -0,0 +1,19 @@
+//@ run-rustfix
+
+// check to make sure that we suggest adding `move` after `static`
+
+#![feature(coroutines)]
+
+fn check() -> impl Sized {
+    let x = 0;
+    #[coroutine]
+    static move || {
+        //~^ ERROR E0373
+        yield;
+        x
+    }
+}
+
+fn main() {
+    check();
+}
diff --git a/tests/ui/coroutine/static-move-suggestion.rs b/tests/ui/coroutine/static-move-suggestion.rs
new file mode 100644
index 00000000000..1d6e4a62883
--- /dev/null
+++ b/tests/ui/coroutine/static-move-suggestion.rs
@@ -0,0 +1,19 @@
+//@ run-rustfix
+
+// check to make sure that we suggest adding `move` after `static`
+
+#![feature(coroutines)]
+
+fn check() -> impl Sized {
+    let x = 0;
+    #[coroutine]
+    static || {
+        //~^ ERROR E0373
+        yield;
+        x
+    }
+}
+
+fn main() {
+    check();
+}
diff --git a/tests/ui/coroutine/static-move-suggestion.stderr b/tests/ui/coroutine/static-move-suggestion.stderr
new file mode 100644
index 00000000000..6d890468b32
--- /dev/null
+++ b/tests/ui/coroutine/static-move-suggestion.stderr
@@ -0,0 +1,26 @@
+error[E0373]: coroutine may outlive the current function, but it borrows `x`, which is owned by the current function
+  --> $DIR/static-move-suggestion.rs:10:5
+   |
+LL |     static || {
+   |     ^^^^^^^^^ may outlive borrowed value `x`
+...
+LL |         x
+   |         - `x` is borrowed here
+   |
+note: coroutine is returned here
+  --> $DIR/static-move-suggestion.rs:10:5
+   |
+LL | /     static || {
+LL | |
+LL | |         yield;
+LL | |         x
+LL | |     }
+   | |_____^
+help: to force the coroutine to take ownership of `x` (and any other referenced variables), use the `move` keyword
+   |
+LL |     static move || {
+   |            ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0373`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr
new file mode 100644
index 00000000000..41f222e46a7
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
+  --> $DIR/as_expression.rs:57:15
+   |
+LL |     SelectInt.check("bar");
+   |               ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
+   |
+   = help: the trait `AsExpression<Text>` is implemented for `&str`
+   = help: for that trait implementation, expected `Text`, found `Integer`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
new file mode 100644
index 00000000000..47acf5b968b
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
+  --> $DIR/as_expression.rs:57:21
+   |
+LL |     SelectInt.check("bar");
+   |               ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str`
+   |               |
+   |               required by a bound introduced by this call
+   |
+   = help: the trait `AsExpression<Text>` is implemented for `&str`
+note: required by a bound in `Foo::check`
+  --> $DIR/as_expression.rs:48:12
+   |
+LL |     fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
+   |        ----- required by a bound in this associated function
+LL |     where
+LL |         T: AsExpression<Self::SqlType>,
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
new file mode 100644
index 00000000000..9cdc193d386
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs
@@ -0,0 +1,60 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#![feature(do_not_recommend)]
+
+pub trait Expression {
+    type SqlType;
+}
+
+pub trait AsExpression<ST> {
+    type Expression: Expression<SqlType = ST>;
+}
+
+pub struct Text;
+pub struct Integer;
+
+pub struct Bound<T>(T);
+pub struct SelectInt;
+
+impl Expression for SelectInt {
+    type SqlType = Integer;
+}
+
+impl<T> Expression for Bound<T> {
+    type SqlType = T;
+}
+
+#[do_not_recommend]
+impl<T, ST> AsExpression<ST> for T
+where
+    T: Expression<SqlType = ST>,
+{
+    type Expression = T;
+}
+
+impl AsExpression<Integer> for i32 {
+    type Expression = Bound<Integer>;
+}
+
+impl AsExpression<Text> for &'_ str {
+    type Expression = Bound<Text>;
+}
+
+trait Foo: Expression + Sized {
+    fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
+    where
+        T: AsExpression<Self::SqlType>,
+    {
+        todo!()
+    }
+}
+
+impl<T> Foo for T where T: Expression {}
+
+fn main() {
+    SelectInt.check("bar");
+    //[next]~^ ERROR the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
+    //[current]~^^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
+}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
index a4d4b7b359e..729cb5694e2 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.current.stderr
@@ -1,16 +1,11 @@
 error[E0277]: the trait bound `*mut (): Foo` is not satisfied
-  --> $DIR/simple.rs:19:17
+  --> $DIR/simple.rs:17:17
    |
 LL |     needs_foo::<*mut ()>();
-   |                 ^^^^^^^ the trait `Send` is not implemented for `*mut ()`, which is required by `*mut (): Foo`
+   |                 ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
    |
-note: required for `*mut ()` to implement `Foo`
-  --> $DIR/simple.rs:10:9
-   |
-LL | impl<T> Foo for T where T: Send {}
-   |         ^^^     ^          ---- unsatisfied trait bound introduced here
 note: required by a bound in `needs_foo`
-  --> $DIR/simple.rs:14:17
+  --> $DIR/simple.rs:12:17
    |
 LL | fn needs_foo<T: Foo>() {}
    |                 ^^^ required by this bound in `needs_foo`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
index 1341ca8175a..729cb5694e2 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.next.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `*mut (): Foo` is not satisfied
-  --> $DIR/simple.rs:19:17
+  --> $DIR/simple.rs:17:17
    |
 LL |     needs_foo::<*mut ()>();
    |                 ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
    |
 note: required by a bound in `needs_foo`
-  --> $DIR/simple.rs:14:17
+  --> $DIR/simple.rs:12:17
    |
 LL | fn needs_foo<T: Foo>() {}
    |                 ^^^ required by this bound in `needs_foo`
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
index 15ff80ae4d9..6fb15b90138 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/simple.rs
@@ -8,8 +8,6 @@ trait Foo {}
 
 #[do_not_recommend]
 impl<T> Foo for T where T: Send {}
-//[current]~^ NOTE required for `*mut ()` to implement `Foo`
-//[current]~| NOTE unsatisfied trait bound introduced here
 
 fn needs_foo<T: Foo>() {}
 //~^ NOTE required by a bound in `needs_foo`
@@ -18,6 +16,5 @@ fn needs_foo<T: Foo>() {}
 fn main() {
     needs_foo::<*mut ()>();
     //~^ ERROR the trait bound `*mut (): Foo` is not satisfied
-    //[current]~| NOTE the trait `Send` is not implemented for `*mut ()`
-    //[next]~| NOTE the trait `Foo` is not implemented for `*mut ()`
+    //~| NOTE the trait `Foo` is not implemented for `*mut ()`
 }
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr
new file mode 100644
index 00000000000..41a10a61e1d
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.current.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): Root` is not satisfied
+  --> $DIR/stacked.rs:19:18
+   |
+LL |     needs_root::<()>();
+   |                  ^^ the trait `Root` is not implemented for `()`
+   |
+note: required by a bound in `needs_root`
+  --> $DIR/stacked.rs:16:18
+   |
+LL | fn needs_root<T: Root>() {}
+   |                  ^^^^ required by this bound in `needs_root`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr
new file mode 100644
index 00000000000..41a10a61e1d
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.next.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `(): Root` is not satisfied
+  --> $DIR/stacked.rs:19:18
+   |
+LL |     needs_root::<()>();
+   |                  ^^ the trait `Root` is not implemented for `()`
+   |
+note: required by a bound in `needs_root`
+  --> $DIR/stacked.rs:16:18
+   |
+LL | fn needs_root<T: Root>() {}
+   |                  ^^^^ required by this bound in `needs_root`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs
new file mode 100644
index 00000000000..695660d3596
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/stacked.rs
@@ -0,0 +1,21 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#![feature(do_not_recommend)]
+
+trait Root {}
+trait DontRecommend {}
+trait Other {}
+
+#[do_not_recommend]
+impl<T> Root for T where T: DontRecommend {}
+
+impl<T> DontRecommend for T where T: Other {}
+
+fn needs_root<T: Root>() {}
+
+fn main() {
+    needs_root::<()>();
+    //~^ ERROR the trait bound `(): Root` is not satisfied
+}
diff --git a/tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs b/tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs
new file mode 100644
index 00000000000..96a0f2f40bf
--- /dev/null
+++ b/tests/ui/generic-associated-types/guide-inference-in-gat-arg-deeper.rs
@@ -0,0 +1,19 @@
+// Fix for <https://github.com/rust-lang/rust/issues/125196>.
+//@ check-pass
+
+trait Tr {
+    type Gat<T>;
+}
+
+struct W<T>(T);
+
+fn foo<T: Tr>() where for<'a> &'a T: Tr<Gat<W<i32>> = i32> {
+    let x: <&T as Tr>::Gat<W<_>> = 1i32;
+    // Previously, `match_projection_projections` only checked that
+    // `shallow_resolve(W<?0>) = W<?0>`. This won't prevent *all* inference guidance
+    // from projection predicates in the environment, just ones that guide the
+    // outermost type of each GAT constructor. This is definitely wrong, but there is
+    // code that relies on it in the wild :/
+}
+
+fn main() {}
diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs
index 2f53bd019b7..e0d2e44e6e7 100644
--- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs
+++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs
@@ -49,7 +49,7 @@ fn function3<T: Trait<'static, Assoc = usize>>() {
     // Trying to normalize the type `for<'a> fn(<T as Trait<'a>>::Assoc)`
     // only gets to `<T as Trait<'a>>::Assoc` once `'a` has been already
     // instantiated, causing us to prefer the where-bound over the impl
-    // resulting in a placeholder error. Even if were were to also use the
+    // resulting in a placeholder error. Even if we were to also use the
     // leak check during candidate selection for normalization, this
     // case would still not compile.
     let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
diff --git a/tests/ui/macros/issue-98790.rs b/tests/ui/macros/issue-98790.rs
deleted file mode 100644
index b489efe9ce9..00000000000
--- a/tests/ui/macros/issue-98790.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//@ run-pass
-
-macro_rules! stringify_item {
-    ($item:item) => {
-        stringify!($item)
-    };
-}
-
-macro_rules! repro {
-    ($expr:expr) => {
-        stringify_item! {
-            pub fn repro() -> bool {
-                $expr
-            }
-        }
-    };
-}
-
-fn main() {
-    assert_eq!(
-        repro!(match () { () => true } | true),
-        "pub fn repro() -> bool { (match () { () => true, }) | true }"
-    );
-}
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs
index 0ae498c134f..d65bfee843e 100644
--- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs
+++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs
@@ -7,6 +7,7 @@ fn _zero() {
     if false {
         unsafe { mem::zeroed() }
         //~^ warn: never type fallback affects this call to an `unsafe` function
+        //~| warn: this will change its meaning in a future release!
     } else {
         return;
     };
@@ -21,6 +22,7 @@ fn _trans() {
             struct Zst;
             core::mem::transmute(Zst)
             //~^ warn: never type fallback affects this call to an `unsafe` function
+            //~| warn: this will change its meaning in a future release!
         }
     } else {
         return;
@@ -36,6 +38,7 @@ fn _union() {
 
         unsafe { Union { a: () }.b }
         //~^ warn: never type fallback affects this union access
+        //~| warn: this will change its meaning in a future release!
     } else {
         return;
     };
@@ -45,6 +48,7 @@ fn _deref() {
     if false {
         unsafe { *ptr::from_ref(&()).cast() }
         //~^ warn: never type fallback affects this raw pointer dereference
+        //~| warn: this will change its meaning in a future release!
     } else {
         return;
     };
@@ -62,6 +66,7 @@ fn _only_generics() {
 
         unsafe { internally_create(x) }
         //~^ warn: never type fallback affects this call to an `unsafe` function
+        //~| warn: this will change its meaning in a future release!
 
         x.unwrap()
     } else {
@@ -73,9 +78,11 @@ fn _stored_function() {
     if false {
         let zeroed = mem::zeroed;
         //~^ warn: never type fallback affects this `unsafe` function
+        //~| warn: this will change its meaning in a future release!
 
         unsafe { zeroed() }
         //~^ warn: never type fallback affects this call to an `unsafe` function
+        //~| warn: this will change its meaning in a future release!
     } else {
         return;
     };
@@ -90,6 +97,7 @@ fn _only_generics_stored_function() {
         let x = None;
         let f = internally_create;
         //~^ warn: never type fallback affects this `unsafe` function
+        //~| warn: this will change its meaning in a future release!
 
         unsafe { f(x) }
 
@@ -113,6 +121,7 @@ fn _method() {
         unsafe {
             S(marker::PhantomData).create_out_of_thin_air()
             //~^ warn: never type fallback affects this call to an `unsafe` method
+            //~| warn: this will change its meaning in a future release!
         }
     } else {
         return;
@@ -129,6 +138,7 @@ fn _objc() {
         () => {
             match send_message::<_ /* ?0 */>() {
                 //~^ warn: never type fallback affects this call to an `unsafe` function
+                //~| warn: this will change its meaning in a future release!
                 Ok(x) => x,
                 Err(_) => loop {},
             }
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr
index 84c9385fd13..fbd92f8f662 100644
--- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr
+++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.stderr
@@ -4,75 +4,93 @@ warning: never type fallback affects this call to an `unsafe` function
 LL |         unsafe { mem::zeroed() }
    |                  ^^^^^^^^^^^^^
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
    = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default
 
 warning: never type fallback affects this call to an `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:22:13
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:23:13
    |
 LL |             core::mem::transmute(Zst)
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
 
 warning: never type fallback affects this union access
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:37:18
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:39:18
    |
 LL |         unsafe { Union { a: () }.b }
    |                  ^^^^^^^^^^^^^^^^^
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
 
 warning: never type fallback affects this raw pointer dereference
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:49:18
    |
 LL |         unsafe { *ptr::from_ref(&()).cast() }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
 
 warning: never type fallback affects this call to an `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:63:18
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:67:18
    |
 LL |         unsafe { internally_create(x) }
    |                  ^^^^^^^^^^^^^^^^^^^^
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
 
 warning: never type fallback affects this call to an `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:77:18
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:83:18
    |
 LL |         unsafe { zeroed() }
    |                  ^^^^^^^^
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
 
 warning: never type fallback affects this `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:74:22
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:79:22
    |
 LL |         let zeroed = mem::zeroed;
    |                      ^^^^^^^^^^^
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
 
 warning: never type fallback affects this `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:17
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:98:17
    |
 LL |         let f = internally_create;
    |                 ^^^^^^^^^^^^^^^^^
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
 
 warning: never type fallback affects this call to an `unsafe` method
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:13
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:122:13
    |
 LL |             S(marker::PhantomData).create_out_of_thin_air()
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
 
 warning: never type fallback affects this call to an `unsafe` function
-  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:130:19
+  --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:19
    |
 LL |             match send_message::<_ /* ?0 */>() {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -80,6 +98,8 @@ LL |             match send_message::<_ /* ?0 */>() {
 LL |         msg_send!();
    |         ----------- in this macro invocation
    |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
    = help: specify the type explicitly
    = note: this warning originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/tests/ui/parser/label-is-actually-char.rs b/tests/ui/parser/label-is-actually-char.rs
index 74df898d191..915ce86d269 100644
--- a/tests/ui/parser/label-is-actually-char.rs
+++ b/tests/ui/parser/label-is-actually-char.rs
@@ -1,4 +1,4 @@
-// Note: it's ok to interpret 'a as 'a', but but not ok to interpret 'abc as
+// Note: it's ok to interpret 'a as 'a', but not ok to interpret 'abc as
 // 'abc' because 'abc' is not a valid char literal.
 
 fn main() {
diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
index 284dacf7000..e6f199445bf 100644
--- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
+++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr
@@ -2,18 +2,8 @@ error[E0277]: the trait bound `u8: Bar` is not satisfied
   --> $DIR/feature-gate-do_not_recommend.rs:19:11
    |
 LL |     stuff(1u8);
-   |     ----- ^^^ the trait `Foo` is not implemented for `u8`, which is required by `u8: Bar`
-   |     |
-   |     required by a bound introduced by this call
+   |           ^^^ the trait `Bar` is not implemented for `u8`
    |
-   = help: the trait `Foo` is implemented for `i32`
-note: required for `u8` to implement `Bar`
-  --> $DIR/feature-gate-do_not_recommend.rs:13:14
-   |
-LL | impl<T: Foo> Bar for T {
-   |         ---  ^^^     ^
-   |         |
-   |         unsatisfied trait bound introduced here
 note: required by a bound in `stuff`
   --> $DIR/feature-gate-do_not_recommend.rs:16:13
    |
diff --git a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
index 0e1d44e7bb3..75a4fbdb5d6 100644
--- a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
+++ b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
@@ -1,4 +1,4 @@
-// User type annotation in fn bodies is a a valid defining site for opaque types.
+// User type annotation in fn bodies is a valid defining site for opaque types.
 //@ check-pass
 #![feature(type_alias_impl_trait)]
 
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
index 59ba2694a76..b209b4bc89d 100644
--- a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
@@ -25,7 +25,7 @@ mod mod3 {
 }
 
 // This is similar to the previous cases in that 'a is equal to 'static,
-// which is is some sense an implicit parameter to `Opaque`.
+// which is some sense an implicit parameter to `Opaque`.
 // For example, given a defining use `Opaque<'a> := &'a ()`,
 // it is ambiguous whether `Opaque<'a> := &'a ()` or `Opaque<'a> := &'static ()`
 mod mod4 {
diff --git a/tests/ui/unpretty/auxiliary/data.txt b/tests/ui/unpretty/auxiliary/data.txt
new file mode 100644
index 00000000000..2f62e4609f4
--- /dev/null
+++ b/tests/ui/unpretty/auxiliary/data.txt
@@ -0,0 +1 @@
+data for include_bytes in ../expanded-exhaustive.rs
diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs
new file mode 100644
index 00000000000..6aa032d7ed8
--- /dev/null
+++ b/tests/ui/unpretty/expanded-exhaustive.rs
@@ -0,0 +1,888 @@
+//@ compile-flags: -Zunpretty=expanded -Zunstable-options
+//@ edition:2024
+//@ check-pass
+
+#![feature(async_closure)]
+#![feature(auto_traits)]
+#![feature(box_patterns)]
+#![feature(builtin_syntax)]
+#![feature(concat_idents)]
+#![feature(const_trait_impl)]
+#![feature(core_pattern_type)]
+#![feature(decl_macro)]
+#![feature(deref_patterns)]
+#![feature(explicit_tail_calls)]
+#![feature(gen_blocks)]
+#![feature(let_chains)]
+#![feature(more_qualified_paths)]
+#![feature(never_patterns)]
+#![feature(never_type)]
+#![feature(pattern_types)]
+#![feature(prelude_import)]
+#![feature(raw_ref_op)]
+#![feature(specialization)]
+#![feature(trace_macros)]
+#![feature(trait_alias)]
+#![feature(try_blocks)]
+#![feature(unnamed_fields)]
+#![feature(yeet_expr)]
+#![allow(incomplete_features)]
+
+#[prelude_import]
+use self::prelude::*;
+
+mod prelude {
+    pub use std::prelude::rust_2024::*;
+
+    pub type T = _;
+
+    pub trait Trait {
+        const CONST: ();
+    }
+}
+
+mod attributes {
+    //! inner single-line doc comment
+    /*!
+     * inner multi-line doc comment
+     */
+    #![doc = "inner doc attribute"]
+    #![allow(dead_code, unused_variables)]
+    #![no_std]
+
+    /// outer single-line doc comment
+    /**
+     * outer multi-line doc comment
+     */
+    #[doc = "outer doc attribute"]
+    #[doc = concat!("mac", "ro")]
+    #[allow()]
+    #[repr(C)]
+    struct Struct;
+}
+
+mod expressions {
+    /// ExprKind::Array
+    fn expr_array() {
+        [];
+        [true];
+        [true,];
+        [true, true];
+        ["long........................................................................"];
+        ["long............................................................", true];
+    }
+
+    /// ExprKind::ConstBlock
+    fn expr_const_block() {
+        const {};
+        const { 1 };
+        const { struct S; };
+    }
+
+    /// ExprKind::Call
+    fn expr_call() {
+        let f;
+        f();
+        f::<u8>();
+        f::<1>();
+        f::<'static, u8, 1>();
+        f(true);
+        f(true,);
+        ()();
+    }
+
+    /// ExprKind::MethodCall
+    fn expr_method_call() {
+        let x;
+        x.f();
+        x.f::<u8>();
+        x.collect::<Vec<_>>();
+    }
+
+    /// ExprKind::Tup
+    fn expr_tup() {
+        ();
+        (true,);
+        (true, false);
+        (true, false,);
+    }
+
+    /// ExprKind::Binary
+    fn expr_binary() {
+        let (a, b, c, d, x, y);
+        true || false;
+        true || false && false;
+        a < 1 && 2 < b && c > 3 && 4 > d;
+        a & b & !c;
+        a + b * c - d + -1 * -2 - -3;
+        x = !y;
+    }
+
+    /// ExprKind::Unary
+    fn expr_unary() {
+        let expr;
+        *expr;
+        !expr;
+        -expr;
+    }
+
+    /// ExprKind::Lit
+    fn expr_lit() {
+        'x';
+        1_000_i8;
+        1.00000000000000000000001;
+    }
+
+    /// ExprKind::Cast
+    fn expr_cast() {
+        let expr;
+        expr as T;
+        expr as T<u8>;
+    }
+
+    /// ExprKind::Type
+    fn expr_type() {
+        let expr;
+        builtin # type_ascribe(expr, T);
+    }
+
+    /// ExprKind::Let
+    fn expr_let() {
+        let b;
+        if let Some(a) = b {}
+        if let _ = true && false {}
+        if let _ = (true && false) {}
+    }
+
+    /// ExprKind::If
+    fn expr_if() {
+        if true {}
+        if !true {}
+        if let true = true {} else {}
+        if true {} else if false {}
+        if true {} else if false {} else {}
+        if true { return; } else if false { 0 } else { 0 }
+    }
+
+    /// ExprKind::While
+    fn expr_while() {
+        while false {}
+        'a: while false {}
+        while let true = true {}
+    }
+
+    /// ExprKind::ForLoop
+    fn expr_for_loop() {
+        let x;
+        for _ in x {}
+        'a: for _ in x {}
+    }
+
+    /// ExprKind::Loop
+    fn expr_loop() {
+        loop {}
+        'a: loop {}
+    }
+
+    /// ExprKind::Match
+    fn expr_match() {
+        let value;
+        match value {}
+        match value { ok => 1 }
+        match value {
+            ok => 1,
+            err => 0,
+        }
+    }
+
+    /// ExprKind::Closure
+    fn expr_closure() {
+        let value;
+        || {};
+        |x| {};
+        |x: u8| {};
+        || ();
+        move || value;
+        async || value;
+        async move || value;
+        static || value;
+        static move || value;
+        (static async || value);
+        (static async move || value);
+        || -> u8 { value };
+        1 + || {};
+    }
+
+    /// ExprKind::Block
+    fn expr_block() {
+        {}
+        unsafe {}
+        'a: {}
+        #[allow()] {}
+        { #![allow()] }
+    }
+
+    /// ExprKind::Gen
+    fn expr_gen() {
+        async {};
+        async move {};
+        gen {};
+        gen move {};
+        async gen {};
+        async gen move {};
+    }
+
+    /// ExprKind::Await
+    fn expr_await() {
+        let fut;
+        fut.await;
+    }
+
+    /// ExprKind::TryBlock
+    fn expr_try_block() {
+        try {}
+        try { return; }
+    }
+
+    /// ExprKind::Assign
+    fn expr_assign() {
+        let expr;
+        expr = true;
+    }
+
+    /// ExprKind::AssignOp
+    fn expr_assign_op() {
+        let expr;
+        expr += true;
+    }
+
+    /// ExprKind::Field
+    fn expr_field() {
+        let expr;
+        expr.field;
+        expr.0;
+    }
+
+    /// ExprKind::Index
+    fn expr_index() {
+        let expr;
+        expr[true];
+    }
+
+    /// ExprKind::Range
+    fn expr_range() {
+        let (lo, hi);
+        ..;
+        ..hi;
+        lo..;
+        lo..hi;
+        lo .. hi;
+        ..=hi;
+        lo..=hi;
+        -2..=-1;
+    }
+
+    /// ExprKind::Underscore
+    fn expr_underscore() {
+        _;
+    }
+
+    /// ExprKind::Path
+    fn expr_path() {
+        let x;
+        crate::expressions::expr_path;
+        crate::expressions::expr_path::<'static>;
+        <T as Default>::default;
+        <T as ::core::default::Default>::default::<>;
+        x::();
+        x::(T, T) -> T;
+        crate::() -> ()::expressions::() -> ()::expr_path;
+        core::()::marker::()::PhantomData;
+    }
+
+    /// ExprKind::AddrOf
+    fn expr_addr_of() {
+        let expr;
+        &expr;
+        &mut expr;
+        &raw const expr;
+        &raw mut expr;
+    }
+
+    /// ExprKind::Break
+    fn expr_break() {
+        'a: {
+            break;
+            break 'a;
+            break true;
+            break 'a true;
+        }
+    }
+
+    /// ExprKind::Continue
+    fn expr_continue() {
+        'a: {
+            continue;
+            continue 'a;
+        }
+    }
+
+    /// ExprKind::Ret
+    fn expr_ret() {
+        return;
+        return true;
+    }
+
+    /// ExprKind::InlineAsm
+    fn expr_inline_asm() {
+        let x;
+        core::arch::asm!(
+            "mov {tmp}, {x}",
+            "shl {tmp}, 1",
+            "shl {x}, 2",
+            "add {x}, {tmp}",
+            x = inout(reg) x,
+            tmp = out(reg) _,
+        );
+    }
+
+    /// ExprKind::OffsetOf
+    fn expr_offset_of() {
+        core::mem::offset_of!(T, field);
+    }
+
+    /// ExprKind::MacCall
+    fn expr_mac_call() {
+        stringify!(...);
+        stringify![...];
+        stringify! { ... };
+    }
+
+    /// ExprKind::Struct
+    fn expr_struct() {
+        struct Struct {}
+        let (x, base);
+        Struct {};
+        <Struct as ToOwned>::Owned {};
+        Struct { .. };
+        Struct { .. base };
+        Struct { x };
+        Struct { x, ..base };
+        Struct { x: true };
+        Struct { x: true, .. };
+        Struct { x: true, ..base };
+        Struct { 0: true, ..base };
+    }
+
+    /// ExprKind::Repeat
+    fn expr_repeat() {
+        [(); 0];
+    }
+
+    /// ExprKind::Paren
+    fn expr_paren() {
+        let expr;
+        (expr);
+    }
+
+    /// ExprKind::Try
+    fn expr_try() {
+        let expr;
+        expr?;
+    }
+
+    /// ExprKind::Yield
+    fn expr_yield() {
+        yield;
+        yield true;
+    }
+
+    /// ExprKind::Yeet
+    fn expr_yeet() {
+        do yeet;
+        do yeet 0;
+    }
+
+    /// ExprKind::Become
+    fn expr_become() {
+        become true;
+    }
+
+    /// ExprKind::IncludedBytes
+    fn expr_include_bytes() {
+        include_bytes!("auxiliary/data.txt");
+    }
+
+    /// ExprKind::FormatArgs
+    fn expr_format_args() {
+        let expr;
+        format_args!("");
+        format_args!("{}", expr);
+    }
+}
+
+mod items {
+    /// ItemKind::ExternCrate
+    mod item_extern_crate {
+        extern crate core;
+        extern crate self as unpretty;
+        pub extern crate core as _;
+    }
+
+    /// ItemKind::Use
+    mod item_use {
+        use crate::{expressions, items::item_use};
+        pub use core::*;
+    }
+
+    /// ItemKind::Static
+    mod item_static {
+        pub static A: () = {};
+        static mut B: () = {};
+    }
+
+    /// ItemKind::Const
+    mod item_const {
+        pub const A: () = {};
+
+        trait TraitItems {
+            const B: ();
+            const C: () = {};
+        }
+    }
+
+    /// ItemKind::Fn
+    mod item_fn {
+        pub const unsafe extern "C" fn f() {}
+        pub async unsafe extern fn g() {}
+        fn h<'a, T>() where T: 'a {}
+
+        trait TraitItems {
+            unsafe extern fn f();
+        }
+
+        impl TraitItems for _ {
+            default unsafe extern fn f() {}
+        }
+    }
+
+    /// ItemKind::Mod
+    mod item_mod {
+        // ...
+    }
+
+    /// ItemKind::ForeignMod
+    mod item_foreign_mod {
+        extern "C++" {}
+        extern {}
+    }
+
+    /// ItemKind::GlobalAsm
+    mod item_global_asm {
+        core::arch::global_asm!(".globl my_asm_func");
+    }
+
+    /// ItemKind::TyAlias
+    mod item_ty_alias {
+        pub type Type<'a> where T: 'a, = T;
+    }
+
+    /// ItemKind::Enum
+    mod item_enum {
+        pub enum Void {}
+        enum Empty {
+            Unit,
+            Tuple(),
+            Struct {},
+        }
+        enum Generic<'a, T>
+        where
+            T: 'a,
+        {
+            Tuple(T),
+            Struct { t: T },
+        }
+    }
+
+    /// ItemKind::Struct
+    mod item_struct {
+        pub struct Unit;
+        struct Tuple();
+        struct Newtype(Unit);
+        struct Struct {}
+        struct Generic<'a, T>
+        where
+            T: 'a,
+        {
+            t: T,
+        }
+    }
+
+    /// ItemKind::Union
+    mod item_union {
+        union Generic<'a, T>
+        where
+            T: 'a,
+        {
+            t: T,
+        }
+    }
+
+    /// ItemKind::Trait
+    mod item_trait {
+        pub unsafe auto trait Send {}
+        trait Trait<'a>: Sized
+        where
+            Self: 'a,
+        {
+        }
+    }
+
+    /// ItemKind::TraitAlias
+    mod item_trait_alias {
+        pub trait Trait<T> = Sized where for<'a> T: 'a;
+    }
+
+    /// ItemKind::Impl
+    mod item_impl {
+        impl () {}
+        impl<T> () {}
+        impl Default for () {}
+        impl<T> const Default for () {}
+    }
+
+    /// ItemKind::MacCall
+    mod item_mac_call {
+        trace_macros!(false);
+        trace_macros![false];
+        trace_macros! { false }
+    }
+
+    /// ItemKind::MacroDef
+    mod item_macro_def {
+        macro_rules! mac { () => {...}; }
+        pub macro stringify() {}
+    }
+
+    /// ItemKind::Delegation
+    mod item_delegation {
+        /*! FIXME: todo */
+    }
+
+    /// ItemKind::DelegationMac
+    mod item_delegation_mac {
+        /*! FIXME: todo */
+    }
+}
+
+mod patterns {
+    /// PatKind::Wild
+    fn pat_wild() {
+        let _;
+    }
+
+    /// PatKind::Ident
+    fn pat_ident() {
+        let x;
+        let ref x;
+        let mut x;
+        let ref mut x;
+        let ref mut x @ _;
+    }
+
+    /// PatKind::Struct
+    fn pat_struct() {
+        let T {};
+        let T::<T> {};
+        let T::<'static> {};
+        let T { x };
+        let T { x: _x };
+        let T { .. };
+        let T { x, .. };
+        let T { x: _x, .. };
+        let T { 0: _x, .. };
+        let <T as ToOwned>::Owned {};
+    }
+
+    /// PatKind::TupleStruct
+    fn pat_tuple_struct() {
+        struct Tuple();
+        let Tuple();
+        let Tuple::<T>();
+        let Tuple::<'static>();
+        let Tuple(x);
+        let Tuple(..);
+        let Tuple(x, ..);
+    }
+
+    /// PatKind::Or
+    fn pat_or() {
+        let (true | false);
+        let (| true);
+        let (|true| false);
+    }
+
+    /// PatKind::Path
+    fn pat_path() {
+        let core::marker::PhantomData;
+        let core::marker::PhantomData::<T>;
+        let core::marker::PhantomData::<'static>;
+        let <T as Trait>::CONST;
+    }
+
+    /// PatKind::Tuple
+    fn pat_tuple() {
+        let ();
+        let (true,);
+        let (true, false);
+    }
+
+    /// PatKind::Box
+    fn pat_box() {
+        let box pat;
+    }
+
+    /// PatKind::Deref
+    fn pat_deref() {
+        let deref!(pat);
+    }
+
+    /// PatKind::Ref
+    fn pat_ref() {
+        let &pat;
+        let &mut pat;
+    }
+
+    /// PatKind::Lit
+    fn pat_lit() {
+        let 1_000_i8;
+        let -"";
+    }
+
+    /// PatKind::Range
+    fn pat_range() {
+        let ..1;
+        let 0..;
+        let 0..1;
+        let 0..=1;
+        let -2..=-1;
+    }
+
+    /// PatKind::Slice
+    fn pat_slice() {
+        let [];
+        let [true];
+        let [true,];
+        let [true, false];
+    }
+
+    /// PatKind::Rest
+    fn pat_rest() {
+        let ..;
+    }
+
+    /// PatKind::Never
+    fn pat_never() {
+        let !;
+        let Some(!);
+    }
+
+    /// PatKind::Paren
+    fn pat_paren() {
+        let (pat);
+    }
+
+    /// PatKind::MacCall
+    fn pat_mac_call() {
+        let stringify!();
+        let stringify![];
+        let stringify! {};
+    }
+}
+
+mod statements {
+    /// StmtKind::Let
+    fn stmt_let() {
+        let _;
+        let _ = true;
+        let _: T = true;
+        let _ = true else { return; };
+    }
+
+    /// StmtKind::Item
+    fn stmt_item() {
+        struct Struct {}
+        struct Unit;
+    }
+
+    /// StmtKind::Expr
+    fn stmt_expr() {
+        ()
+    }
+
+    /// StmtKind::Semi
+    fn stmt_semi() {
+        1 + 1;
+    }
+
+    /// StmtKind::Empty
+    fn stmt_empty() {
+        ;
+    }
+
+    /// StmtKind::MacCall
+    fn stmt_mac_call() {
+        stringify!(...);
+        stringify![...];
+        stringify! { ... };
+    }
+}
+
+mod types {
+    /// TyKind::Slice
+    fn ty_slice() {
+        let _: [T];
+    }
+
+    /// TyKind::Array
+    fn ty_array() {
+        let _: [T; 0];
+    }
+
+    /// TyKind::Ptr
+    fn ty_ptr() {
+        let _: *const T;
+        let _: *mut T;
+    }
+
+    /// TyKind::Ref
+    fn ty_ref() {
+        let _: &T;
+        let _: &mut T;
+        let _: &'static T;
+        let _: &'static mut [T];
+        let _: &T<T<T<T<T>>>>;
+        let _: &T<T<T<T<T> > > >;
+    }
+
+    /// TyKind::BareFn
+    fn ty_bare_fn() {
+        let _: fn();
+        let _: fn() -> ();
+        let _: fn(T);
+        let _: fn(t: T);
+        let _: for<> fn();
+        let _: for<'a> fn();
+    }
+
+    /// TyKind::Never
+    fn ty_never() {
+        let _: !;
+    }
+
+    /// TyKind::Tup
+    fn ty_tup() {
+        let _: ();
+        let _: (T,);
+        let _: (T, T);
+    }
+
+    /// TyKind::AnonStruct
+    fn ty_anon_struct() {
+        struct Struct {
+            _: struct { t: T },
+        }
+    }
+
+    /// TyKind::AnonUnion
+    fn ty_anon_union() {
+        struct Struct {
+            _: union { t: T },
+        }
+    }
+
+    /// TyKind::Path
+    fn ty_path() {
+        let _: T;
+        let _: T<'static>;
+        let _: T<T>;
+        let _: T::<T>;
+        let _: T() -> !;
+        let _: <T as ToOwned>::Owned;
+    }
+
+    /// TyKind::TraitObject
+    fn ty_trait_object() {
+        let _: dyn Send;
+        let _: dyn Send + 'static;
+        let _: dyn 'static + Send;
+        let _: dyn for<'a> Send;
+    }
+
+    /// TyKind::ImplTrait
+    const fn ty_impl_trait() {
+        let _: impl Send;
+        let _: impl Send + 'static;
+        let _: impl 'static + Send;
+        let _: impl ?Sized;
+        let _: impl ~const Clone;
+        let _: impl for<'a> Send;
+    }
+
+    /// TyKind::Paren
+    fn ty_paren() {
+        let _: (T);
+    }
+
+    /// TyKind::Typeof
+    fn ty_typeof() {
+        /*! unused for now */
+    }
+
+    /// TyKind::Infer
+    fn ty_infer() {
+        let _: _;
+    }
+
+    /// TyKind::ImplicitSelf
+    fn ty_implicit_self() {
+        /*! there is no syntax for this */
+    }
+
+    /// TyKind::MacCall
+    fn ty_mac_call() {
+        let _: concat_idents!(T);
+        let _: concat_idents![T];
+        let _: concat_idents! { T };
+    }
+
+    /// TyKind::CVarArgs
+    fn ty_c_var_args() {
+        /*! FIXME: todo */
+    }
+
+    /// TyKind::Pat
+    fn ty_pat() {
+        let _: core::pattern_type!(u32 is 1..);
+    }
+}
+
+mod visibilities {
+    /// VisibilityKind::Public
+    mod visibility_public {
+        pub struct Pub;
+    }
+
+    /// VisibilityKind::Restricted
+    mod visibility_restricted {
+        pub(crate) struct PubCrate;
+        pub(self) struct PubSelf;
+        pub(super) struct PubSuper;
+        pub(in crate) struct PubInCrate;
+        pub(in self) struct PubInSelf;
+        pub(in super) struct PubInSuper;
+        pub(in crate::visibilities) struct PubInCrateVisibilities;
+        pub(in self::super) struct PubInSelfSuper;
+        pub(in super::visibility_restricted) struct PubInSuperMod;
+    }
+}
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
new file mode 100644
index 00000000000..325bace7b56
--- /dev/null
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -0,0 +1,719 @@
+#![feature(prelude_import)]
+//@ compile-flags: -Zunpretty=expanded -Zunstable-options
+//@ edition:2024
+//@ check-pass
+
+#![feature(async_closure)]
+#![feature(auto_traits)]
+#![feature(box_patterns)]
+#![feature(builtin_syntax)]
+#![feature(concat_idents)]
+#![feature(const_trait_impl)]
+#![feature(core_pattern_type)]
+#![feature(decl_macro)]
+#![feature(deref_patterns)]
+#![feature(explicit_tail_calls)]
+#![feature(gen_blocks)]
+#![feature(let_chains)]
+#![feature(more_qualified_paths)]
+#![feature(never_patterns)]
+#![feature(never_type)]
+#![feature(pattern_types)]
+#![feature(prelude_import)]
+#![feature(raw_ref_op)]
+#![feature(specialization)]
+#![feature(trace_macros)]
+#![feature(trait_alias)]
+#![feature(try_blocks)]
+#![feature(unnamed_fields)]
+#![feature(yeet_expr)]
+#![allow(incomplete_features)]
+#[prelude_import]
+use std::prelude::rust_2024::*;
+#[macro_use]
+extern crate std;
+
+#[prelude_import]
+use self::prelude::*;
+
+mod prelude {
+    pub use std::prelude::rust_2024::*;
+
+    pub type T = _;
+
+    pub trait Trait {
+        const CONST: ();
+    }
+}
+
+mod attributes {
+    //! inner single-line doc comment
+    /*!
+     * inner multi-line doc comment
+     */
+    #![doc = "inner doc attribute"]
+    #![allow(dead_code, unused_variables)]
+    #![no_std]
+
+    /// outer single-line doc comment
+    /**
+     * outer multi-line doc comment
+     */
+    #[doc = "outer doc attribute"]
+    #[doc = "macro"]
+    #[allow()]
+    #[repr(C)]
+    struct Struct;
+}
+
+mod expressions {
+    /// ExprKind::Array
+    fn expr_array() {
+        [];
+        [true];
+        [true];
+        [true, true];
+        ["long........................................................................"];
+        ["long............................................................",
+                true];
+    }
+
+    /// ExprKind::ConstBlock
+    fn expr_const_block() {
+        const {};
+        const { 1 };
+        const {
+                struct S;
+            };
+    }
+
+    /// ExprKind::Call
+    fn expr_call() {
+        let f;
+        f();
+        f::<u8>();
+        f::<1>();
+        f::<'static, u8, 1>();
+        f(true);
+        f(true);
+        ()();
+    }
+
+    /// ExprKind::MethodCall
+    fn expr_method_call() {
+        let x;
+        x.f();
+        x.f::<u8>();
+        x.collect::<Vec<_>>();
+    }
+
+    /// ExprKind::Tup
+    fn expr_tup() { (); (true,); (true, false); (true, false); }
+
+    /// ExprKind::Binary
+    fn expr_binary() {
+        let (a, b, c, d, x, y);
+        true || false;
+        true || false && false;
+        a < 1 && 2 < b && c > 3 && 4 > d;
+        a & b & !c;
+        a + b * c - d + -1 * -2 - -3;
+        x = !y;
+    }
+
+    /// ExprKind::Unary
+    fn expr_unary() { let expr; *expr; !expr; -expr; }
+
+    /// ExprKind::Lit
+    fn expr_lit() { 'x'; 1_000_i8; 1.00000000000000000000001; }
+
+    /// ExprKind::Cast
+    fn expr_cast() { let expr; expr as T; expr as T<u8>; }
+
+    /// ExprKind::Type
+    fn expr_type() { let expr; builtin # type_ascribe(expr, T); }
+
+    /// ExprKind::Let
+    fn expr_let() {
+        let b;
+        if let Some(a) = b {}
+        if let _ = true && false {}
+        if let _ = (true && false) {}
+    }
+
+    /// ExprKind::If
+    fn expr_if() {
+        if true {}
+        if !true {}
+        if let true = true {} else {}
+        if true {} else if false {}
+        if true {} else if false {} else {}
+        if true { return; } else if false { 0 } else { 0 }
+    }
+
+    /// ExprKind::While
+    fn expr_while() {
+        while false {}
+        'a: while false {}
+        while let true = true {}
+    }
+
+    /// ExprKind::ForLoop
+    fn expr_for_loop() { let x; for _ in x {} 'a: for _ in x {} }
+
+    /// ExprKind::Loop
+    fn expr_loop() { loop {} 'a: loop {} }
+
+    /// ExprKind::Match
+    fn expr_match() {
+        let value;
+        match value {}
+        match value { ok => 1, }
+        match value { ok => 1, err => 0, }
+    }
+
+    /// ExprKind::Closure
+    fn expr_closure() {
+        let value;
+        || {};
+        |x| {};
+        |x: u8| {};
+        || ();
+        move || value;
+        async || value;
+        async move || value;
+        static || value;
+        static move || value;
+        (static async || value);
+        (static async move || value);
+        || -> u8 { value };
+        1 + (|| {});
+    }
+
+    /// ExprKind::Block
+    fn expr_block() {
+        {}
+        unsafe {}
+        'a: {}
+
+        #[allow()]
+        {}
+        {
+            #![allow()]
+        }
+    }
+
+    /// ExprKind::Gen
+    fn expr_gen() {
+        async {};
+        async move {};
+        gen {};
+        gen move {};
+        async gen {};
+        async gen move {};
+    }
+
+    /// ExprKind::Await
+    fn expr_await() { let fut; fut.await; }
+
+    /// ExprKind::TryBlock
+    fn expr_try_block() { try {} try { return; } }
+
+    /// ExprKind::Assign
+    fn expr_assign() { let expr; expr = true; }
+
+    /// ExprKind::AssignOp
+    fn expr_assign_op() { let expr; expr += true; }
+
+    /// ExprKind::Field
+    fn expr_field() { let expr; expr.field; expr.0; }
+
+    /// ExprKind::Index
+    fn expr_index() { let expr; expr[true]; }
+
+    /// ExprKind::Range
+    fn expr_range() {
+        let (lo, hi);
+        ..;
+        ..hi;
+        lo..;
+        lo..hi;
+        lo..hi;
+        ..=hi;
+        lo..=hi;
+        -2..=-1;
+    }
+
+    /// ExprKind::Underscore
+    fn expr_underscore() { _; }
+
+    /// ExprKind::Path
+    fn expr_path() {
+        let x;
+        crate::expressions::expr_path;
+        crate::expressions::expr_path::<'static>;
+        <T as Default>::default;
+        <T as ::core::default::Default>::default::<>;
+        x::();
+        x::(T, T) -> T;
+        crate::() -> ()::expressions::() -> ()::expr_path;
+        core::()::marker::()::PhantomData;
+    }
+
+    /// ExprKind::AddrOf
+    fn expr_addr_of() {
+        let expr;
+        &expr;
+        &mut expr;
+        &raw const expr;
+        &raw mut expr;
+    }
+
+    /// ExprKind::Break
+    fn expr_break() { 'a: { break; break 'a; break true; break 'a true; } }
+
+    /// ExprKind::Continue
+    fn expr_continue() { 'a: { continue; continue 'a; } }
+
+    /// ExprKind::Ret
+    fn expr_ret() { return; return true; }
+
+    /// ExprKind::InlineAsm
+    fn expr_inline_asm() {
+        let x;
+        asm!("mov {1}, {0}\nshl {1}, 1\nshl {0}, 2\nadd {0}, {1}",
+            inout(reg)
+            x,
+            out(reg)
+            _);
+    }
+
+    /// ExprKind::OffsetOf
+    fn expr_offset_of() {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        // ...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        { builtin # offset_of(T, field) };
+    }
+    /// ExprKind::MacCall
+    fn expr_mac_call() { "..."; "..."; "..."; }
+    /// ExprKind::Struct
+    fn expr_struct() {
+        struct Struct {}
+        let (x, base);
+        Struct {};
+        <Struct as ToOwned>::Owned {};
+        Struct { .. };
+        Struct { ..base };
+        Struct { x };
+        Struct { x, ..base };
+        Struct { x: true };
+        Struct { x: true, .. };
+        Struct { x: true, ..base };
+        Struct { 0: true, ..base };
+    }
+    /// ExprKind::Repeat
+    fn expr_repeat() { [(); 0]; }
+    /// ExprKind::Paren
+    fn expr_paren() { let expr; (expr); }
+    /// ExprKind::Try
+    fn expr_try() { let expr; expr?; }
+    /// ExprKind::Yield
+    fn expr_yield() { yield; yield true; }
+    /// ExprKind::Yeet
+    fn expr_yeet() { do yeet; do yeet 0; }
+    /// ExprKind::Become
+    fn expr_become() { become true; }
+    /// ExprKind::IncludedBytes
+    fn expr_include_bytes() {
+        b"data for include_bytes in ../expanded-exhaustive.rs\n";
+    }
+    /// ExprKind::FormatArgs
+    fn expr_format_args() {
+        let expr;
+        format_args!("");
+        format_args!("{0}", expr);
+    }
+}
+mod items {
+    /// ItemKind::ExternCrate
+    mod item_extern_crate {
+        extern crate core;
+        extern crate self as unpretty;
+        pub extern crate core as _;
+    }
+    /// ItemKind::Use
+    mod item_use {
+        use crate::{expressions, items::item_use};
+        pub use core::*;
+    }
+    /// ItemKind::Static
+    mod item_static {
+        pub static A: () = {};
+        static mut B: () = {};
+    }
+    /// ItemKind::Const
+    mod item_const {
+        pub const A: () = {};
+        trait TraitItems {
+            const B: ();
+            const C: () = {};
+        }
+    }
+    /// ItemKind::Fn
+    mod item_fn {
+        pub const unsafe extern "C" fn f() {}
+        pub async unsafe extern fn g() {}
+        fn h<'a, T>() where T: 'a {}
+        trait TraitItems {
+            unsafe extern fn f();
+        }
+        impl TraitItems for _ {
+            default unsafe extern fn f() {}
+        }
+    }
+    /// ItemKind::Mod
+    mod item_mod { }
+    /// ItemKind::ForeignMod
+    mod item_foreign_mod {
+        extern "C++" {}
+        extern {}
+    }
+    /// ItemKind::GlobalAsm
+    mod item_global_asm {
+        global_asm! (".globl my_asm_func");
+    }
+    /// ItemKind::TyAlias
+    mod item_ty_alias {
+        pub type Type<'a> where T: 'a = T;
+    }
+    /// ItemKind::Enum
+    mod item_enum {
+        pub enum Void {}
+        enum Empty { Unit, Tuple(), Struct {}, }
+        enum Generic<'a, T> where T: 'a {
+            Tuple(T),
+            Struct {
+                t: T,
+            },
+        }
+    }
+    /// ItemKind::Struct
+    mod item_struct {
+        pub struct Unit;
+        struct Tuple();
+        struct Newtype(Unit);
+        struct Struct {}
+        struct Generic<'a, T> where T: 'a {
+            t: T,
+        }
+    }
+    /// ItemKind::Union
+    mod item_union {
+        union Generic<'a, T> where T: 'a {
+            t: T,
+        }
+    }
+    /// ItemKind::Trait
+    mod item_trait {
+        pub unsafe auto trait Send {}
+        trait Trait<'a>: Sized where Self: 'a {}
+    }
+    /// ItemKind::TraitAlias
+    mod item_trait_alias {
+        pub trait Trait<T> = Sized where for<'a> T: 'a;
+    }
+    /// ItemKind::Impl
+    mod item_impl {
+        impl () {}
+        impl<T> () {}
+        impl Default for () {}
+        impl<T> const Default for () {}
+    }
+    /// ItemKind::MacCall
+    mod item_mac_call { }
+    /// ItemKind::MacroDef
+    mod item_macro_def {
+        macro_rules! mac { () => { ... }; }
+        pub macro stringify { () => {} }
+    }
+    /// ItemKind::Delegation
+    mod item_delegation {
+        /*! FIXME: todo */
+    }
+    /// ItemKind::DelegationMac
+    mod item_delegation_mac {
+        /*! FIXME: todo */
+    }
+}
+mod patterns {
+    /// PatKind::Wild
+    fn pat_wild() { let _; }
+    /// PatKind::Ident
+    fn pat_ident() {
+        let x;
+        let ref x;
+        let mut x;
+        let ref mut x;
+        let ref mut x @ _;
+    }
+    /// PatKind::Struct
+    fn pat_struct() {
+        let T {};
+        let T::<T> {};
+        let T::<'static> {};
+        let T { x };
+        let T { x: _x };
+        let T { .. };
+        let T { x, .. };
+        let T { x: _x, .. };
+        let T { 0: _x, .. };
+        let <T as ToOwned>::Owned {};
+    }
+    /// PatKind::TupleStruct
+    fn pat_tuple_struct() {
+        struct Tuple();
+        let Tuple();
+        let Tuple::<T>();
+        let Tuple::<'static>();
+        let Tuple(x);
+        let Tuple(..);
+        let Tuple(x, ..);
+    }
+    /// PatKind::Or
+    fn pat_or() { let (true | false); let (true); let (true | false); }
+    /// PatKind::Path
+    fn pat_path() {
+        let core::marker::PhantomData;
+        let core::marker::PhantomData::<T>;
+        let core::marker::PhantomData::<'static>;
+        let <T as Trait>::CONST;
+    }
+    /// PatKind::Tuple
+    fn pat_tuple() { let (); let (true,); let (true, false); }
+    /// PatKind::Box
+    fn pat_box() { let box pat; }
+    /// PatKind::Deref
+    fn pat_deref() { let deref!(pat); }
+    /// PatKind::Ref
+    fn pat_ref() { let &pat; let &mut pat; }
+    /// PatKind::Lit
+    fn pat_lit() { let 1_000_i8; let -""; }
+    /// PatKind::Range
+    fn pat_range() { let ..1; let 0..; let 0..1; let 0..=1; let -2..=-1; }
+    /// PatKind::Slice
+    fn pat_slice() { let []; let [true]; let [true]; let [true, false]; }
+    /// PatKind::Rest
+    fn pat_rest() { let ..; }
+    /// PatKind::Never
+    fn pat_never() { let !; let Some(!); }
+    /// PatKind::Paren
+    fn pat_paren() { let (pat); }
+    /// PatKind::MacCall
+    fn pat_mac_call() { let ""; let ""; let ""; }
+}
+mod statements {
+    /// StmtKind::Let
+    fn stmt_let() {
+        let _;
+        let _ = true;
+        let _: T = true;
+        let _ = true else { return; };
+    }
+    /// StmtKind::Item
+    fn stmt_item() {
+        struct Struct {}
+        struct Unit;
+    }
+    /// StmtKind::Expr
+    fn stmt_expr() { () }
+    /// StmtKind::Semi
+    fn stmt_semi() { 1 + 1; }
+    /// StmtKind::Empty
+    fn stmt_empty() { ; }
+    /// StmtKind::MacCall
+    fn stmt_mac_call() { "..."; "..."; "..."; }
+}
+mod types {
+    /// TyKind::Slice
+    fn ty_slice() { let _: [T]; }
+    /// TyKind::Array
+    fn ty_array() { let _: [T; 0]; }
+    /// TyKind::Ptr
+    fn ty_ptr() { let _: *const T; let _: *mut T; }
+    /// TyKind::Ref
+    fn ty_ref() {
+        let _: &T;
+        let _: &mut T;
+        let _: &'static T;
+        let _: &'static mut [T];
+        let _: &T<T<T<T<T>>>>;
+        let _: &T<T<T<T<T>>>>;
+    }
+    /// TyKind::BareFn
+    fn ty_bare_fn() {
+        let _: fn();
+        let _: fn() -> ();
+        let _: fn(T);
+        let _: fn(t: T);
+        let _: fn();
+        let _: for<'a> fn();
+    }
+    /// TyKind::Never
+    fn ty_never() { let _: !; }
+    /// TyKind::Tup
+    fn ty_tup() { let _: (); let _: (T,); let _: (T, T); }
+    /// TyKind::AnonStruct
+    fn ty_anon_struct() {
+        struct Struct {
+            _: struct  {
+                t: T,
+            },
+        }
+    }
+    /// TyKind::AnonUnion
+    fn ty_anon_union() {
+        struct Struct {
+            _: union  {
+                t: T,
+            },
+        }
+    }
+    /// TyKind::Path
+    fn ty_path() {
+        let _: T;
+        let _: T<'static>;
+        let _: T<T>;
+        let _: T<T>;
+        let _: T() -> !;
+        let _: <T as ToOwned>::Owned;
+    }
+    /// TyKind::TraitObject
+    fn ty_trait_object() {
+        let _: dyn Send;
+        let _: dyn Send + 'static;
+        let _: dyn 'static + Send;
+        let _: dyn for<'a> Send;
+    }
+    /// TyKind::ImplTrait
+    const fn ty_impl_trait() {
+        let _: impl Send;
+        let _: impl Send + 'static;
+        let _: impl 'static + Send;
+        let _: impl ?Sized;
+        let _: impl ~const Clone;
+        let _: impl for<'a> Send;
+    }
+    /// TyKind::Paren
+    fn ty_paren() { let _: (T); }
+    /// TyKind::Typeof
+    fn ty_typeof() {
+        /*! unused for now */
+    }
+    /// TyKind::Infer
+    fn ty_infer() { let _: _; }
+    /// TyKind::ImplicitSelf
+    fn ty_implicit_self() {
+        /*! there is no syntax for this */
+    }
+    /// TyKind::MacCall
+    fn ty_mac_call() { let _: T; let _: T; let _: T; }
+    /// TyKind::CVarArgs
+    fn ty_c_var_args() {
+        /*! FIXME: todo */
+    }
+    /// TyKind::Pat
+    fn ty_pat() { let _: u32 is 1..; }
+}
+mod visibilities {
+    /// VisibilityKind::Public
+    mod visibility_public {
+        pub struct Pub;
+    }
+    /// VisibilityKind::Restricted
+    mod visibility_restricted {
+        pub(crate) struct PubCrate;
+        pub(self) struct PubSelf;
+        pub(super) struct PubSuper;
+        pub(in crate) struct PubInCrate;
+        pub(in self) struct PubInSelf;
+        pub(in super) struct PubInSuper;
+        pub(in crate::visibilities) struct PubInCrateVisibilities;
+        pub(in self::super) struct PubInSelfSuper;
+        pub(in super::visibility_restricted) struct PubInSuperMod;
+    }
+}
diff --git a/tests/ui/unpretty/expanded-interpolation.rs b/tests/ui/unpretty/expanded-interpolation.rs
new file mode 100644
index 00000000000..8f0e21ce870
--- /dev/null
+++ b/tests/ui/unpretty/expanded-interpolation.rs
@@ -0,0 +1,106 @@
+//@ compile-flags: -Zunpretty=expanded
+//@ check-pass
+
+// This test covers the AST pretty-printer's insertion of parentheses in some
+// macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in
+// the syntax tree) need to be printed in order for the printed code to be valid
+// Rust syntax. We also test negative cases: the pretty-printer should not be
+// synthesizing parentheses indiscriminately; only where necessary.
+
+#![feature(let_chains)]
+#![feature(if_let_guard)]
+
+macro_rules! expr {
+    ($expr:expr) => { $expr };
+}
+
+macro_rules! stmt {
+    ($stmt:stmt) => { $stmt };
+}
+
+fn if_let() {
+    macro_rules! if_let {
+        ($pat:pat, $expr:expr) => {
+            if let $pat = $expr {}
+        };
+    }
+
+    if let no_paren = true && false {}
+    if_let!(paren_around_binary, true && false);
+    if_let!(no_paren, true);
+
+    struct Struct {}
+    match () {
+        _ if let no_paren = Struct {} => {}
+    }
+}
+
+fn let_else() {
+    let no_paren = expr!(1 + 1) else { return; };
+    let paren_around_loop = expr!(loop {}) else { return; };
+}
+
+fn local() {
+    macro_rules! let_expr_minus_one {
+        ($pat:pat, $expr:expr) => {
+            let $pat = $expr - 1;
+        };
+    }
+
+    let void;
+    let_expr_minus_one!(no_paren, match void {});
+
+    macro_rules! let_expr_else_return {
+        ($pat:pat, $expr:expr) => {
+            let $pat = $expr else { return; };
+        };
+    }
+
+    let_expr_else_return!(no_paren, void());
+}
+
+fn match_arm() {
+    macro_rules! match_arm {
+        ($pat:pat, $expr:expr) => {
+            match () { $pat => $expr }
+        };
+    }
+
+    match_arm!(no_paren, 1 - 1);
+    match_arm!(paren_around_brace, { 1 } - 1);
+}
+
+/// https://github.com/rust-lang/rust/issues/98790
+fn stmt_boundary() {
+    macro_rules! expr_as_stmt {
+        ($expr:expr) => {
+            stmt!($expr)
+        };
+    }
+
+    let paren_around_match;
+    expr_as_stmt!(match paren_around_match {} | true);
+
+    macro_rules! minus_one {
+        ($expr:expr) => {
+            expr_as_stmt!($expr - 1)
+        };
+    }
+
+    let (no_paren, paren_around_loop);
+    minus_one!(no_paren);
+    minus_one!(match paren_around_match {});
+    minus_one!(match paren_around_match {}());
+    minus_one!(match paren_around_match {}[0]);
+    minus_one!(loop { break paren_around_loop; });
+}
+
+fn vis_inherited() {
+    macro_rules! vis_inherited {
+        ($vis:vis struct) => {
+            $vis struct Struct;
+        };
+    }
+
+    vis_inherited!(struct);
+}
diff --git a/tests/ui/unpretty/expanded-interpolation.stdout b/tests/ui/unpretty/expanded-interpolation.stdout
new file mode 100644
index 00000000000..73322b50f2d
--- /dev/null
+++ b/tests/ui/unpretty/expanded-interpolation.stdout
@@ -0,0 +1,92 @@
+#![feature(prelude_import)]
+#![no_std]
+//@ compile-flags: -Zunpretty=expanded
+//@ check-pass
+
+// This test covers the AST pretty-printer's insertion of parentheses in some
+// macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in
+// the syntax tree) need to be printed in order for the printed code to be valid
+// Rust syntax. We also test negative cases: the pretty-printer should not be
+// synthesizing parentheses indiscriminately; only where necessary.
+
+#![feature(let_chains)]
+#![feature(if_let_guard)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+macro_rules! expr { ($expr:expr) => { $expr }; }
+
+macro_rules! stmt { ($stmt:stmt) => { $stmt }; }
+
+fn if_let() {
+    macro_rules! if_let {
+        ($pat:pat, $expr:expr) => { if let $pat = $expr {} };
+    }
+
+    if let no_paren = true && false {}
+    if let paren_around_binary = (true && false) {};
+    if let no_paren = true {};
+
+    struct Struct {}
+    match () { _ if let no_paren = Struct {} => {} }
+}
+
+fn let_else() {
+    let no_paren = 1 + 1 else { return; };
+    let paren_around_loop = (loop {}) else { return; };
+}
+
+fn local() {
+    macro_rules! let_expr_minus_one {
+        ($pat:pat, $expr:expr) => { let $pat = $expr - 1; };
+    }
+
+    let void;
+    let no_paren = match void {} - 1;
+
+    macro_rules! let_expr_else_return {
+        ($pat:pat, $expr:expr) => { let $pat = $expr else { return; }; };
+    }
+    let 
+
+            no_paren = void() else { return; };
+}
+
+fn match_arm() {
+    macro_rules! match_arm {
+        ($pat:pat, $expr:expr) => { match () { $pat => $expr } };
+    }
+    match () {
+
+
+            no_paren => 1 - 1,
+    };
+    match () { paren_around_brace => ({ 1 }) - 1, };
+}
+
+/// https://github.com/rust-lang/rust/issues/98790
+fn stmt_boundary() {
+    macro_rules! expr_as_stmt { ($expr:expr) => { stmt!($expr) }; }
+
+    let paren_around_match;
+    (match paren_around_match {}) | true;
+
+    macro_rules! minus_one { ($expr:expr) => { expr_as_stmt!($expr - 1) }; }
+
+    let (no_paren, paren_around_loop);
+    no_paren - 1;
+    (match paren_around_match {}) - 1;
+    (match paren_around_match {})() - 1;
+    (match paren_around_match {})[0] - 1;
+    (loop { break paren_around_loop; }) - 1;
+}
+
+fn vis_inherited() {
+    macro_rules! vis_inherited {
+        ($vis:vis struct) => { $vis struct Struct; };
+    }
+    struct Struct;
+
+}
diff --git a/tests/ui/unpretty/let-else.rs b/tests/ui/unpretty/let-else.rs
deleted file mode 100644
index 4db6eca99b1..00000000000
--- a/tests/ui/unpretty/let-else.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ compile-flags: -Zunpretty=expanded
-//@ check-pass
-
-macro_rules! expr {
-    ($e:expr) => { $e };
-}
-
-fn main() {
-    let _ = expr!(1 + 1) else { return; };
-    let _ = expr!(loop {}) else { return; };
-}
diff --git a/tests/ui/unpretty/let-else.stdout b/tests/ui/unpretty/let-else.stdout
deleted file mode 100644
index 4bc4d9e085f..00000000000
--- a/tests/ui/unpretty/let-else.stdout
+++ /dev/null
@@ -1,15 +0,0 @@
-#![feature(prelude_import)]
-#![no_std]
-#[prelude_import]
-use ::std::prelude::rust_2015::*;
-#[macro_use]
-extern crate std;
-//@ compile-flags: -Zunpretty=expanded
-//@ check-pass
-
-macro_rules! expr { ($e:expr) => { $e }; }
-
-fn main() {
-    let _ = 1 + 1 else { return; };
-    let _ = (loop {}) else { return; };
-}