about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/codegen/enum/enum-match.rs396
-rw-r--r--tests/codegen/enum/enum-two-variants-match.rs79
-rw-r--r--tests/ui/dyn-compatibility/trait-alias-self-projection.rs12
-rw-r--r--tests/ui/dyn-compatibility/trait-alias-self-projection.stderr9
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr4
-rw-r--r--tests/ui/implied-bounds/issue-100690.stderr4
-rw-r--r--tests/ui/implied-bounds/overflow.rs11
-rw-r--r--tests/ui/implied-bounds/overflow.stderr8
-rw-r--r--tests/ui/macros/failed-to-reparse-issue-139445.rs6
-rw-r--r--tests/ui/macros/failed-to-reparse-issue-139445.stderr24
-rw-r--r--tests/ui/macros/no-close-delim-issue-139248.rs14
-rw-r--r--tests/ui/macros/no-close-delim-issue-139248.stderr33
-rw-r--r--tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr8
-rw-r--r--tests/ui/pattern/non-structural-match-types-cycle-err.rs24
-rw-r--r--tests/ui/pattern/non-structural-match-types-cycle-err.stderr64
-rw-r--r--tests/ui/pattern/non-structural-match-types.rs8
-rw-r--r--tests/ui/pattern/non-structural-match-types.stderr22
-rw-r--r--tests/ui/structs/default-field-values/failures.rs5
-rw-r--r--tests/ui/structs/default-field-values/failures.stderr26
-rw-r--r--tests/ui/trait-bounds/mismatch-fn-trait.stderr8
-rw-r--r--tests/ui/traits/dyn-drop-principal-with-projections.rs13
-rw-r--r--tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs18
-rw-r--r--tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr65
23 files changed, 792 insertions, 69 deletions
diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs
index a24b98050d2..6e185cf8932 100644
--- a/tests/codegen/enum/enum-match.rs
+++ b/tests/codegen/enum/enum-match.rs
@@ -1,21 +1,26 @@
 //@ compile-flags: -Copt-level=1
-//@ only-x86_64
+//@ only-64bit
 
 #![crate_type = "lib"]
+#![feature(core_intrinsics)]
 
 // Check each of the 3 cases for `codegen_get_discr`.
 
+// FIXME: once our min-bar LLVM has `range` attributes, update the various
+// tests here to no longer have the `range`s and `nsw`s as optional.
+
 // Case 0: One tagged variant.
 pub enum Enum0 {
     A(bool),
     B,
 }
 
-// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0{{.*}}
+// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0(i8{{.+}}%0)
 // CHECK-NEXT: start:
-// CHECK-NEXT: %1 = icmp eq i8 %0, 2
-// CHECK-NEXT: %2 = and i8 %0, 1
-// CHECK-NEXT: %{{.+}} = select i1 %1, i8 13, i8 %2
+// CHECK-NEXT: %[[IS_B:.+]] = icmp eq i8 %0, 2
+// CHECK-NEXT: %[[TRUNC:.+]] = and i8 %0, 1
+// CHECK-NEXT: %[[R:.+]] = select i1 %[[IS_B]], i8 13, i8 %[[TRUNC]]
+// CHECK-NEXT: ret i8 %[[R]]
 #[no_mangle]
 pub fn match0(e: Enum0) -> u8 {
     use Enum0::*;
@@ -32,13 +37,14 @@ pub enum Enum1 {
     C,
 }
 
-// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1{{.*}}
+// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1(i8{{.+}}%0)
 // CHECK-NEXT: start:
-// CHECK-NEXT: %1 = add{{( nsw)?}} i8 %0, -2
-// CHECK-NEXT: %2 = zext i8 %1 to i64
-// CHECK-NEXT: %3 = icmp ult i8 %1, 2
-// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1
-// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0
+// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
+// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 2
+// CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 1
+// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 0
+// CHECK-NEXT: switch i64 %[[DISCR]]
 #[no_mangle]
 pub fn match1(e: Enum1) -> u8 {
     use Enum1::*;
@@ -92,14 +98,14 @@ pub enum Enum2 {
     E,
 }
 
-// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2{{.*}}
+// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2(i8{{.+}}%0)
 // CHECK-NEXT: start:
-// CHECK-NEXT: %1 = add i8 %0, 2
-// CHECK-NEXT: %2 = zext i8 %1 to i64
-// CHECK-NEXT: %3 = icmp ult i8 %1, 4
-// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1
-// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0
-// CHECK-NEXT: switch i64 %_2, label {{.*}} [
+// CHECK-NEXT: %[[REL_VAR:.+]] = add i8 %0, 2
+// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 4
+// CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 1
+// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 0
+// CHECK-NEXT: switch i64 %[[DISCR]]
 #[no_mangle]
 pub fn match2(e: Enum2) -> u8 {
     use Enum2::*;
@@ -111,3 +117,357 @@ pub fn match2(e: Enum2) -> u8 {
         E => 250,
     }
 }
+
+// And make sure it works even if the niched scalar is a pointer.
+// (For example, that we don't try to `sub` on pointers.)
+
+// CHECK-LABEL: define noundef{{( range\(i16 -?[0-9]+, -?[0-9]+\))?}} i16 @match3(ptr{{.+}}%0)
+// CHECK-NEXT: start:
+// CHECK-NEXT: %[[IS_NULL:.+]] = icmp eq ptr %0, null
+// CHECK-NEXT: br i1 %[[IS_NULL]]
+#[no_mangle]
+pub fn match3(e: Option<&u8>) -> i16 {
+    match e {
+        Some(r) => *r as _,
+        None => -1,
+    }
+}
+
+// If the untagged variant is in the middle, there's an impossible value that's
+// not reflected in the `range` parameter attribute, so we assume it away.
+
+#[derive(PartialEq)]
+pub enum MiddleNiche {
+    A,
+    B,
+    C(bool),
+    D,
+    E,
+}
+
+// CHECK-LABEL: define noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0)
+// CHECK-NEXT: start:
+// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 5
+// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2
+// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
+// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i8 %[[REL_VAR]], i8 2
+// CHECK-NEXT: switch i8 %[[DISCR]]
+#[no_mangle]
+pub fn match4(e: MiddleNiche) -> u8 {
+    use MiddleNiche::*;
+    match e {
+        A => 13,
+        B => 100,
+        C(b) => b as u8,
+        D => 200,
+        E => 250,
+    }
+}
+
+// CHECK-LABEL: define{{.+}}i1 @match4_is_c(i8{{.+}}%e)
+// CHECK-NEXT: start
+// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %e, -2
+// CHECK-NEXT: %[[NOT_NICHE:.+]] = icmp ugt i8 %[[REL_VAR]], 4
+// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2
+// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
+// CHECK-NEXT: ret i1 %[[NOT_NICHE]]
+#[no_mangle]
+pub fn match4_is_c(e: MiddleNiche) -> bool {
+    // Before #139098, this couldn't optimize out the `select` because it looked
+    // like it was possible for a `2` to be produced on both sides.
+
+    std::intrinsics::discriminant_value(&e) == 2
+}
+
+// You have to do something pretty obnoxious to get a variant index that doesn't
+// fit in the tag size, but it's possible
+
+pub enum Never {}
+
+pub enum HugeVariantIndex {
+    V000(Never),
+    V001(Never),
+    V002(Never),
+    V003(Never),
+    V004(Never),
+    V005(Never),
+    V006(Never),
+    V007(Never),
+    V008(Never),
+    V009(Never),
+    V010(Never),
+    V011(Never),
+    V012(Never),
+    V013(Never),
+    V014(Never),
+    V015(Never),
+    V016(Never),
+    V017(Never),
+    V018(Never),
+    V019(Never),
+    V020(Never),
+    V021(Never),
+    V022(Never),
+    V023(Never),
+    V024(Never),
+    V025(Never),
+    V026(Never),
+    V027(Never),
+    V028(Never),
+    V029(Never),
+    V030(Never),
+    V031(Never),
+    V032(Never),
+    V033(Never),
+    V034(Never),
+    V035(Never),
+    V036(Never),
+    V037(Never),
+    V038(Never),
+    V039(Never),
+    V040(Never),
+    V041(Never),
+    V042(Never),
+    V043(Never),
+    V044(Never),
+    V045(Never),
+    V046(Never),
+    V047(Never),
+    V048(Never),
+    V049(Never),
+    V050(Never),
+    V051(Never),
+    V052(Never),
+    V053(Never),
+    V054(Never),
+    V055(Never),
+    V056(Never),
+    V057(Never),
+    V058(Never),
+    V059(Never),
+    V060(Never),
+    V061(Never),
+    V062(Never),
+    V063(Never),
+    V064(Never),
+    V065(Never),
+    V066(Never),
+    V067(Never),
+    V068(Never),
+    V069(Never),
+    V070(Never),
+    V071(Never),
+    V072(Never),
+    V073(Never),
+    V074(Never),
+    V075(Never),
+    V076(Never),
+    V077(Never),
+    V078(Never),
+    V079(Never),
+    V080(Never),
+    V081(Never),
+    V082(Never),
+    V083(Never),
+    V084(Never),
+    V085(Never),
+    V086(Never),
+    V087(Never),
+    V088(Never),
+    V089(Never),
+    V090(Never),
+    V091(Never),
+    V092(Never),
+    V093(Never),
+    V094(Never),
+    V095(Never),
+    V096(Never),
+    V097(Never),
+    V098(Never),
+    V099(Never),
+    V100(Never),
+    V101(Never),
+    V102(Never),
+    V103(Never),
+    V104(Never),
+    V105(Never),
+    V106(Never),
+    V107(Never),
+    V108(Never),
+    V109(Never),
+    V110(Never),
+    V111(Never),
+    V112(Never),
+    V113(Never),
+    V114(Never),
+    V115(Never),
+    V116(Never),
+    V117(Never),
+    V118(Never),
+    V119(Never),
+    V120(Never),
+    V121(Never),
+    V122(Never),
+    V123(Never),
+    V124(Never),
+    V125(Never),
+    V126(Never),
+    V127(Never),
+    V128(Never),
+    V129(Never),
+    V130(Never),
+    V131(Never),
+    V132(Never),
+    V133(Never),
+    V134(Never),
+    V135(Never),
+    V136(Never),
+    V137(Never),
+    V138(Never),
+    V139(Never),
+    V140(Never),
+    V141(Never),
+    V142(Never),
+    V143(Never),
+    V144(Never),
+    V145(Never),
+    V146(Never),
+    V147(Never),
+    V148(Never),
+    V149(Never),
+    V150(Never),
+    V151(Never),
+    V152(Never),
+    V153(Never),
+    V154(Never),
+    V155(Never),
+    V156(Never),
+    V157(Never),
+    V158(Never),
+    V159(Never),
+    V160(Never),
+    V161(Never),
+    V162(Never),
+    V163(Never),
+    V164(Never),
+    V165(Never),
+    V166(Never),
+    V167(Never),
+    V168(Never),
+    V169(Never),
+    V170(Never),
+    V171(Never),
+    V172(Never),
+    V173(Never),
+    V174(Never),
+    V175(Never),
+    V176(Never),
+    V177(Never),
+    V178(Never),
+    V179(Never),
+    V180(Never),
+    V181(Never),
+    V182(Never),
+    V183(Never),
+    V184(Never),
+    V185(Never),
+    V186(Never),
+    V187(Never),
+    V188(Never),
+    V189(Never),
+    V190(Never),
+    V191(Never),
+    V192(Never),
+    V193(Never),
+    V194(Never),
+    V195(Never),
+    V196(Never),
+    V197(Never),
+    V198(Never),
+    V199(Never),
+    V200(Never),
+    V201(Never),
+    V202(Never),
+    V203(Never),
+    V204(Never),
+    V205(Never),
+    V206(Never),
+    V207(Never),
+    V208(Never),
+    V209(Never),
+    V210(Never),
+    V211(Never),
+    V212(Never),
+    V213(Never),
+    V214(Never),
+    V215(Never),
+    V216(Never),
+    V217(Never),
+    V218(Never),
+    V219(Never),
+    V220(Never),
+    V221(Never),
+    V222(Never),
+    V223(Never),
+    V224(Never),
+    V225(Never),
+    V226(Never),
+    V227(Never),
+    V228(Never),
+    V229(Never),
+    V230(Never),
+    V231(Never),
+    V232(Never),
+    V233(Never),
+    V234(Never),
+    V235(Never),
+    V236(Never),
+    V237(Never),
+    V238(Never),
+    V239(Never),
+    V240(Never),
+    V241(Never),
+    V242(Never),
+    V243(Never),
+    V244(Never),
+    V245(Never),
+    V246(Never),
+    V247(Never),
+    V248(Never),
+    V249(Never),
+    V250(Never),
+    V251(Never),
+    V252(Never),
+    V253(Never),
+    V254(Never),
+    V255(Never),
+    V256(Never),
+
+    Possible257,
+    Bool258(bool),
+    Possible259,
+}
+
+// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match5(i8{{.+}}%0)
+// CHECK-NEXT: start:
+// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
+// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 3
+// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 1
+// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
+// CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 257
+// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 258
+// CHECK-NEXT: switch i64 %[[DISCR]],
+// CHECK-NEXT:   i64 257,
+// CHECK-NEXT:   i64 258,
+// CHECK-NEXT:   i64 259,
+#[no_mangle]
+pub fn match5(e: HugeVariantIndex) -> u8 {
+    use HugeVariantIndex::*;
+    match e {
+        Possible257 => 13,
+        Bool258(b) => b as u8,
+        Possible259 => 100,
+    }
+}
diff --git a/tests/codegen/enum/enum-two-variants-match.rs b/tests/codegen/enum/enum-two-variants-match.rs
index 21ae1f96bca..12d9edc4d62 100644
--- a/tests/codegen/enum/enum-two-variants-match.rs
+++ b/tests/codegen/enum/enum-two-variants-match.rs
@@ -1,8 +1,12 @@
 //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes
-//@ only-x86_64 (because these discriminants are isize)
+//@ only-64bit (because these discriminants are isize)
 
 #![crate_type = "lib"]
 
+// This directly tests what we emit for these matches, rather than what happens
+// after optimization, so it doesn't need to worry about extra flags on the
+// instructions and is less susceptible to being broken on LLVM updates.
+
 // CHECK-LABEL: @option_match
 #[no_mangle]
 pub fn option_match(x: Option<i32>) -> u16 {
@@ -51,3 +55,76 @@ pub fn result_match(x: Result<u64, i64>) -> u16 {
         Ok(_) => 42,
     }
 }
+
+// CHECK-LABEL: @option_bool_match(
+#[no_mangle]
+pub fn option_bool_match(x: Option<bool>) -> char {
+    // CHECK: %[[RAW:.+]] = load i8, ptr %x
+    // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], 2
+    // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1
+    // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1
+    // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]]
+
+    // CHECK: [[BB_SOME]]:
+    // CHECK: %[[FIELD:.+]] = load i8, ptr %x
+    // CHECK: %[[FIELD_T:.+]] = trunc nuw i8 %[[FIELD]] to i1
+    // CHECK: br i1 %[[FIELD_T]]
+    match x {
+        None => 'n',
+        Some(false) => 'f',
+        Some(true) => 't',
+    }
+}
+
+use std::cmp::Ordering::{self, *};
+// CHECK-LABEL: @option_ordering_match(
+#[no_mangle]
+pub fn option_ordering_match(x: Option<Ordering>) -> char {
+    // CHECK: %[[RAW:.+]] = load i8, ptr %x
+    // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], 2
+    // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1
+    // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1
+    // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]]
+
+    // CHECK: [[BB_SOME]]:
+    // CHECK: %[[FIELD:.+]] = load i8, ptr %x
+    // CHECK: switch i8 %[[FIELD]], label %[[UNREACHABLE:.+]] [
+    // CHECK-NEXT: i8 -1, label
+    // CHECK-NEXT: i8 0, label
+    // CHECK-NEXT: i8 1, label
+    // CHECK-NEXT: ]
+
+    // CHECK: [[UNREACHABLE]]:
+    // CHECK-NEXT: unreachable
+    match x {
+        None => '?',
+        Some(Less) => '<',
+        Some(Equal) => '=',
+        Some(Greater) => '>',
+    }
+}
+
+// CHECK-LABEL: @option_nonzero_match(
+#[no_mangle]
+pub fn option_nonzero_match(x: Option<std::num::NonZero<u16>>) -> u16 {
+    // CHECK: %[[OUT:.+]] = alloca [2 x i8]
+
+    // CHECK: %[[IS_NONE:.+]] = icmp eq i16 %x, 0
+    // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1
+    // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1
+    // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]]
+
+    // CHECK: [[BB_SOME]]:
+    // CHECK: store i16 987, ptr %[[OUT]]
+
+    // CHECK: [[BB_NONE]]:
+    // CHECK: store i16 123, ptr %[[OUT]]
+
+    // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]]
+    // CHECK: ret i16 %[[RET]]
+
+    match x {
+        None => 123,
+        Some(_) => 987,
+    }
+}
diff --git a/tests/ui/dyn-compatibility/trait-alias-self-projection.rs b/tests/ui/dyn-compatibility/trait-alias-self-projection.rs
new file mode 100644
index 00000000000..0badb738809
--- /dev/null
+++ b/tests/ui/dyn-compatibility/trait-alias-self-projection.rs
@@ -0,0 +1,12 @@
+#![feature(trait_alias)]
+trait B = Fn() -> Self;
+type D = &'static dyn B;
+//~^ ERROR E0411
+
+fn a() -> D {
+    unreachable!();
+}
+
+fn main() {
+    _ = a();
+}
diff --git a/tests/ui/dyn-compatibility/trait-alias-self-projection.stderr b/tests/ui/dyn-compatibility/trait-alias-self-projection.stderr
new file mode 100644
index 00000000000..dccee02e9cd
--- /dev/null
+++ b/tests/ui/dyn-compatibility/trait-alias-self-projection.stderr
@@ -0,0 +1,9 @@
+error[E0411]: `Self` is not allowed in type aliases
+  --> $DIR/trait-alias-self-projection.rs:3:19
+   |
+LL | type D = &'static dyn B;
+   |                   ^^^^^ `Self` is only available in impls, traits, and concrete type definitions
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0411`.
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr
index 64707642eeb..36264b0d997 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr
@@ -6,8 +6,8 @@ LL |         call(f, ());
    |         |
    |         required by a bound introduced by this call
    |
-   = note: expected a closure with arguments `((),)`
-              found a closure with arguments `(<_ as ATC<'a>>::Type,)`
+   = note: expected a closure with signature `for<'a> fn(<_ as ATC<'a>>::Type)`
+              found a closure with signature `fn(())`
 note: this is a known limitation of the trait solver that will be lifted in the future
   --> $DIR/issue-62529-3.rs:25:14
    |
diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr
index 4964dccd551..d00895d8fc9 100644
--- a/tests/ui/implied-bounds/issue-100690.stderr
+++ b/tests/ui/implied-bounds/issue-100690.stderr
@@ -6,8 +6,8 @@ LL |         real_dispatch(f)
    |         |
    |         required by a bound introduced by this call
    |
-   = note: expected a closure with arguments `(&mut UIView<'a, _>,)`
-              found a closure with arguments `(&mut UIView<'_, _>,)`
+   = note: expected a closure with signature `for<'a, 'b> fn(&'a mut UIView<'b, _>)`
+              found a closure with signature `fn(&mut UIView<'a, _>)`
 note: required by a bound in `real_dispatch`
   --> $DIR/issue-100690.rs:8:8
    |
diff --git a/tests/ui/implied-bounds/overflow.rs b/tests/ui/implied-bounds/overflow.rs
new file mode 100644
index 00000000000..7c36998dd4d
--- /dev/null
+++ b/tests/ui/implied-bounds/overflow.rs
@@ -0,0 +1,11 @@
+trait Tailed<'a>: 'a {
+    type Tail: Tailed<'a>;
+}
+
+struct List<'a, T: Tailed<'a>> {
+    //~^ ERROR overflow computing implied lifetime bounds for `List`
+    next: Box<List<'a, T::Tail>>,
+    node: &'a T,
+}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/overflow.stderr b/tests/ui/implied-bounds/overflow.stderr
new file mode 100644
index 00000000000..2e5a9ab141c
--- /dev/null
+++ b/tests/ui/implied-bounds/overflow.stderr
@@ -0,0 +1,8 @@
+error: overflow computing implied lifetime bounds for `List`
+  --> $DIR/overflow.rs:5:1
+   |
+LL | struct List<'a, T: Tailed<'a>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/failed-to-reparse-issue-139445.rs b/tests/ui/macros/failed-to-reparse-issue-139445.rs
new file mode 100644
index 00000000000..babe26b9d29
--- /dev/null
+++ b/tests/ui/macros/failed-to-reparse-issue-139445.rs
@@ -0,0 +1,6 @@
+fn main() {
+    assert_eq!(3, 'a,)
+    //~^ ERROR expected `while`, `for`, `loop` or `{` after a label
+    //~| ERROR expected `while`, `for`, `loop` or `{` after a label
+    //~| ERROR expected expression, found ``
+}
diff --git a/tests/ui/macros/failed-to-reparse-issue-139445.stderr b/tests/ui/macros/failed-to-reparse-issue-139445.stderr
new file mode 100644
index 00000000000..6f7d88fb344
--- /dev/null
+++ b/tests/ui/macros/failed-to-reparse-issue-139445.stderr
@@ -0,0 +1,24 @@
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/failed-to-reparse-issue-139445.rs:2:21
+   |
+LL |     assert_eq!(3, 'a,)
+   |                     ^ expected `while`, `for`, `loop` or `{` after a label
+
+error: expected `while`, `for`, `loop` or `{` after a label
+  --> $DIR/failed-to-reparse-issue-139445.rs:2:5
+   |
+LL |     assert_eq!(3, 'a,)
+   |     ^^^^^^^^^^^^^^^^^^ expected `while`, `for`, `loop` or `{` after a label
+   |
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected expression, found ``
+  --> $DIR/failed-to-reparse-issue-139445.rs:2:5
+   |
+LL |     assert_eq!(3, 'a,)
+   |     ^^^^^^^^^^^^^^^^^^ expected expression
+   |
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/macros/no-close-delim-issue-139248.rs b/tests/ui/macros/no-close-delim-issue-139248.rs
new file mode 100644
index 00000000000..86583b2724e
--- /dev/null
+++ b/tests/ui/macros/no-close-delim-issue-139248.rs
@@ -0,0 +1,14 @@
+// This code caused a "no close delim when reparsing Expr" ICE in #139248.
+
+macro_rules! m {
+    (static a : () = $e:expr) => {
+        static a : () = $e;
+        //~^ ERROR macro expansion ends with an incomplete expression: expected expression
+    }
+}
+
+m! { static a : () = (if b) }
+//~^ ERROR expected `{`, found `)`
+//~| ERROR expected `{`, found `)`
+
+fn main() {}
diff --git a/tests/ui/macros/no-close-delim-issue-139248.stderr b/tests/ui/macros/no-close-delim-issue-139248.stderr
new file mode 100644
index 00000000000..6ed41ae9b46
--- /dev/null
+++ b/tests/ui/macros/no-close-delim-issue-139248.stderr
@@ -0,0 +1,33 @@
+error: expected `{`, found `)`
+  --> $DIR/no-close-delim-issue-139248.rs:10:27
+   |
+LL | m! { static a : () = (if b) }
+   |                           ^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/no-close-delim-issue-139248.rs:10:26
+   |
+LL | m! { static a : () = (if b) }
+   |                          ^
+
+error: expected `{`, found `)`
+  --> $DIR/no-close-delim-issue-139248.rs:10:27
+   |
+LL | m! { static a : () = (if b) }
+   |                           ^ expected `{`
+   |
+note: the `if` expression is missing a block after this condition
+  --> $DIR/no-close-delim-issue-139248.rs:10:26
+   |
+LL | m! { static a : () = (if b) }
+   |                          ^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: macro expansion ends with an incomplete expression: expected expression
+  --> $DIR/no-close-delim-issue-139248.rs:5:28
+   |
+LL |         static a : () = $e;
+   |                            ^ expected expression
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
index b7161310619..7912ed4d707 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
@@ -7,8 +7,8 @@ LL |     let _ = (-10..=10).find(|x: i32| x.signum() == 0);
    |                        required by a bound introduced by this call
    |
    = help: the trait `for<'a> FnMut(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
-   = note: expected a closure with arguments `(i32,)`
-              found a closure with arguments `(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item,)`
+   = note: expected a closure with signature `for<'a> fn(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)`
+              found a closure with signature `fn(i32)`
 note: required by a bound in `find`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
@@ -27,8 +27,8 @@ LL |     let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
    |                        required by a bound introduced by this call
    |
    = help: the trait `for<'a> FnMut(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
-   = note: expected a closure with arguments `(&&&i32,)`
-              found a closure with arguments `(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item,)`
+   = note: expected a closure with signature `for<'a> fn(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)`
+              found a closure with signature `fn(&&&i32)`
 note: required by a bound in `find`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
diff --git a/tests/ui/pattern/non-structural-match-types-cycle-err.rs b/tests/ui/pattern/non-structural-match-types-cycle-err.rs
new file mode 100644
index 00000000000..a8e494c35b0
--- /dev/null
+++ b/tests/ui/pattern/non-structural-match-types-cycle-err.rs
@@ -0,0 +1,24 @@
+//@ edition:2021
+
+struct AnyOption<T>(T);
+impl<T> AnyOption<T> {
+    const NONE: Option<T> = None;
+}
+
+// This is an unfortunate side-effect of borrowchecking nested items
+// together with their parent. Evaluating the `AnyOption::<_>::NONE`
+// pattern for exhaustiveness checking relies on the layout of the
+// async block. This layout relies on `optimized_mir` of the nested
+// item which is now borrowck'd together with its parent. As
+// borrowck of the parent requires us to have already lowered the match,
+// this is a query cycle.
+
+fn uwu() {}
+fn defines() {
+    match Some(async {}) {
+        AnyOption::<_>::NONE => {}
+        //~^ ERROR cycle detected when building THIR for `defines`
+        _ => {}
+    }
+}
+fn main() {}
diff --git a/tests/ui/pattern/non-structural-match-types-cycle-err.stderr b/tests/ui/pattern/non-structural-match-types-cycle-err.stderr
new file mode 100644
index 00000000000..2f4ac63fc57
--- /dev/null
+++ b/tests/ui/pattern/non-structural-match-types-cycle-err.stderr
@@ -0,0 +1,64 @@
+error[E0391]: cycle detected when building THIR for `defines`
+  --> $DIR/non-structural-match-types-cycle-err.rs:19:9
+   |
+LL |         AnyOption::<_>::NONE => {}
+   |         ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires evaluating type-level constant...
+  --> $DIR/non-structural-match-types-cycle-err.rs:5:5
+   |
+LL |     const NONE: Option<T> = None;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires const-evaluating + checking `<impl at $DIR/non-structural-match-types-cycle-err.rs:4:1: 4:21>::NONE`...
+  --> $DIR/non-structural-match-types-cycle-err.rs:5:5
+   |
+LL |     const NONE: Option<T> = None;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing layout of `core::option::Option<{async block@$DIR/non-structural-match-types-cycle-err.rs:18:16: 18:21}>`...
+   = note: ...which requires computing layout of `{async block@$DIR/non-structural-match-types-cycle-err.rs:18:16: 18:21}`...
+note: ...which requires optimizing MIR for `defines::{closure#0}`...
+  --> $DIR/non-structural-match-types-cycle-err.rs:18:16
+   |
+LL |     match Some(async {}) {
+   |                ^^^^^
+note: ...which requires elaborating drops for `defines::{closure#0}`...
+  --> $DIR/non-structural-match-types-cycle-err.rs:18:16
+   |
+LL |     match Some(async {}) {
+   |                ^^^^^
+note: ...which requires borrow-checking `defines`...
+  --> $DIR/non-structural-match-types-cycle-err.rs:17:1
+   |
+LL | fn defines() {
+   | ^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `defines`...
+  --> $DIR/non-structural-match-types-cycle-err.rs:17:1
+   |
+LL | fn defines() {
+   | ^^^^^^^^^^^^
+note: ...which requires checking if `defines` contains FFI-unwind calls...
+  --> $DIR/non-structural-match-types-cycle-err.rs:17:1
+   |
+LL | fn defines() {
+   | ^^^^^^^^^^^^
+note: ...which requires building MIR for `defines`...
+  --> $DIR/non-structural-match-types-cycle-err.rs:17:1
+   |
+LL | fn defines() {
+   | ^^^^^^^^^^^^
+note: ...which requires match-checking `defines`...
+  --> $DIR/non-structural-match-types-cycle-err.rs:17:1
+   |
+LL | fn defines() {
+   | ^^^^^^^^^^^^
+   = note: ...which again requires building THIR for `defines`, completing the cycle
+note: cycle used when unsafety-checking `defines`
+  --> $DIR/non-structural-match-types-cycle-err.rs:17:1
+   |
+LL | fn defines() {
+   | ^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs
index 5869767c936..a5ff7fcdb5e 100644
--- a/tests/ui/pattern/non-structural-match-types.rs
+++ b/tests/ui/pattern/non-structural-match-types.rs
@@ -1,6 +1,4 @@
 //@ edition:2021
-#![feature(const_async_blocks)]
-
 struct AnyOption<T>(T);
 impl<T> AnyOption<T> {
     const NONE: Option<T> = None;
@@ -19,11 +17,5 @@ fn defines() {
         //~^ ERROR constant of non-structural type
         _ => {}
     }
-
-    match Some(async {}) {
-        AnyOption::<_>::NONE => {}
-        //~^ ERROR constant of non-structural type
-        _ => {}
-    }
 }
 fn main() {}
diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr
index da675a9f3ff..3b74ffe7cb7 100644
--- a/tests/ui/pattern/non-structural-match-types.stderr
+++ b/tests/ui/pattern/non-structural-match-types.stderr
@@ -1,5 +1,5 @@
 error: constant of non-structural type `Option<fn() {uwu}>` in a pattern
-  --> $DIR/non-structural-match-types.rs:12:9
+  --> $DIR/non-structural-match-types.rs:10:9
    |
 LL | impl<T> AnyOption<T> {
    | --------------------
@@ -11,8 +11,8 @@ LL |         AnyOption::<_>::NONE => {}
    |
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
-error: constant of non-structural type `Option<{closure@$DIR/non-structural-match-types.rs:17:16: 17:18}>` in a pattern
-  --> $DIR/non-structural-match-types.rs:18:9
+error: constant of non-structural type `Option<{closure@$DIR/non-structural-match-types.rs:15:16: 15:18}>` in a pattern
+  --> $DIR/non-structural-match-types.rs:16:9
    |
 LL | impl<T> AnyOption<T> {
    | --------------------
@@ -24,19 +24,5 @@ LL |         AnyOption::<_>::NONE => {}
    |
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
-error: constant of non-structural type `Option<{async block@$DIR/non-structural-match-types.rs:23:16: 23:21}>` in a pattern
-  --> $DIR/non-structural-match-types.rs:24:9
-   |
-LL | impl<T> AnyOption<T> {
-   | --------------------
-LL |     const NONE: Option<T> = None;
-   |     --------------------- constant defined here
-...
-LL |         AnyOption::<_>::NONE => {}
-   |         ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type
-   |
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-   = note: `ResumeTy` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/structs/default-field-values/failures.rs b/tests/ui/structs/default-field-values/failures.rs
index 1e94eecb4f8..4461302e841 100644
--- a/tests/ui/structs/default-field-values/failures.rs
+++ b/tests/ui/structs/default-field-values/failures.rs
@@ -1,4 +1,4 @@
-#![feature(default_field_values)]
+ #![feature(default_field_values)]
 
 #[derive(Debug)]
 pub struct S;
@@ -50,7 +50,8 @@ enum E {
 fn main () {
     let _ = Foo { .. }; // ok
     let _ = Foo::default(); // ok
-    let _ = Bar { .. }; //~ ERROR mandatory field
+    let _ = Bar { .. }; //~ ERROR missing field
+    let _ = Bar { baz: 0, .. }; //~ ERROR missing field
     let _ = Bar::default(); // silenced
     let _ = Bar { bar: S, .. }; // ok
     let _ = Qux::<4> { .. };
diff --git a/tests/ui/structs/default-field-values/failures.stderr b/tests/ui/structs/default-field-values/failures.stderr
index 58f7baee4b2..21c9bfb44b4 100644
--- a/tests/ui/structs/default-field-values/failures.stderr
+++ b/tests/ui/structs/default-field-values/failures.stderr
@@ -27,14 +27,20 @@ LL + #[derive(Default)]
 LL | pub struct S;
    |
 
-error: missing mandatory field `bar`
-  --> $DIR/failures.rs:53:21
+error: missing field `bar` in initializer
+  --> $DIR/failures.rs:53:19
    |
 LL |     let _ = Bar { .. };
-   |                     ^
+   |                   ^ fields that do not have a defaulted value must be provided explicitly
+
+error: missing field `bar` in initializer
+  --> $DIR/failures.rs:54:27
+   |
+LL |     let _ = Bar { baz: 0, .. };
+   |                           ^ fields that do not have a defaulted value must be provided explicitly
 
 error[E0308]: mismatched types
-  --> $DIR/failures.rs:57:17
+  --> $DIR/failures.rs:58:17
    |
 LL |     let _ = Rak(..);
    |             --- ^^ expected `i32`, found `RangeFull`
@@ -47,19 +53,19 @@ note: tuple struct defined here
 LL | pub struct Rak(i32 = 42);
    |            ^^^
 help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal
-  --> $DIR/failures.rs:57:17
+  --> $DIR/failures.rs:58:17
    |
 LL |     let _ = Rak(..);
    |                 ^^
 
 error[E0061]: this struct takes 1 argument but 2 arguments were supplied
-  --> $DIR/failures.rs:59:13
+  --> $DIR/failures.rs:60:13
    |
 LL |     let _ = Rak(0, ..);
    |             ^^^    -- unexpected argument #2 of type `RangeFull`
    |
 help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal
-  --> $DIR/failures.rs:59:20
+  --> $DIR/failures.rs:60:20
    |
 LL |     let _ = Rak(0, ..);
    |                    ^^
@@ -75,13 +81,13 @@ LL +     let _ = Rak(0);
    |
 
 error[E0061]: this struct takes 1 argument but 2 arguments were supplied
-  --> $DIR/failures.rs:61:13
+  --> $DIR/failures.rs:62:13
    |
 LL |     let _ = Rak(.., 0);
    |             ^^^ -- unexpected argument #1 of type `RangeFull`
    |
 help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal
-  --> $DIR/failures.rs:61:17
+  --> $DIR/failures.rs:62:17
    |
 LL |     let _ = Rak(.., 0);
    |                 ^^
@@ -96,7 +102,7 @@ LL -     let _ = Rak(.., 0);
 LL +     let _ = Rak(0);
    |
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0061, E0277, E0308.
 For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/trait-bounds/mismatch-fn-trait.stderr b/tests/ui/trait-bounds/mismatch-fn-trait.stderr
index 519aa9ea3f3..051e660c2d1 100644
--- a/tests/ui/trait-bounds/mismatch-fn-trait.stderr
+++ b/tests/ui/trait-bounds/mismatch-fn-trait.stderr
@@ -6,8 +6,8 @@ LL |     take(f)
    |     |
    |     required by a bound introduced by this call
    |
-   = note: expected a closure with arguments `(u32,)`
-              found a closure with arguments `(i32,)`
+   = note: expected a closure with signature `fn(i32)`
+              found a closure with signature `fn(u32)`
 note: required by a bound in `take`
   --> $DIR/mismatch-fn-trait.rs:1:18
    |
@@ -68,8 +68,8 @@ LL |     take(f)
    |     required by a bound introduced by this call
    |
    = note: `impl FnOnce(u32)` implements `FnOnce`, but it must implement `FnMut`, which is more general
-   = note: expected a closure with arguments `(u32,)`
-              found a closure with arguments `(i32,)`
+   = note: expected a closure with signature `fn(i32)`
+              found a closure with signature `fn(u32)`
 note: required by a bound in `take`
   --> $DIR/mismatch-fn-trait.rs:1:18
    |
diff --git a/tests/ui/traits/dyn-drop-principal-with-projections.rs b/tests/ui/traits/dyn-drop-principal-with-projections.rs
new file mode 100644
index 00000000000..912061847c6
--- /dev/null
+++ b/tests/ui/traits/dyn-drop-principal-with-projections.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+
+trait Tr {
+    type Assoc;
+}
+
+impl Tr for () {
+    type Assoc = ();
+}
+
+fn main() {
+    let x = &() as &(dyn Tr<Assoc = ()> + Send) as &dyn Send;
+}
diff --git a/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs
new file mode 100644
index 00000000000..74c23a59bee
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs
@@ -0,0 +1,18 @@
+// Make sure not to construct predicates with escaping bound vars in `diagnostic_hir_wf_check`.
+// Regression test for <https://github.com/rust-lang/rust/issues/139330>.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait A<T: ?Sized> {}
+impl<T: ?Sized> A<T> for () {}
+
+trait B {}
+struct W<T: B>(T);
+
+fn b() -> (W<()>, impl for<C> A<C>) { (W(()), ()) }
+//~^ ERROR the trait bound `(): B` is not satisfied
+//~| ERROR the trait bound `(): B` is not satisfied
+//~| ERROR the trait bound `(): B` is not satisfied
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr
new file mode 100644
index 00000000000..df99f4a67ab
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr
@@ -0,0 +1,65 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/diagnostic-hir-wf-check.rs:4:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `(): B` is not satisfied
+  --> $DIR/diagnostic-hir-wf-check.rs:13:12
+   |
+LL | fn b() -> (W<()>, impl for<C> A<C>) { (W(()), ()) }
+   |            ^^^^^ the trait `B` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/diagnostic-hir-wf-check.rs:10:1
+   |
+LL | trait B {}
+   | ^^^^^^^
+note: required by a bound in `W`
+  --> $DIR/diagnostic-hir-wf-check.rs:11:13
+   |
+LL | struct W<T: B>(T);
+   |             ^ required by this bound in `W`
+
+error[E0277]: the trait bound `(): B` is not satisfied
+  --> $DIR/diagnostic-hir-wf-check.rs:13:42
+   |
+LL | fn b() -> (W<()>, impl for<C> A<C>) { (W(()), ()) }
+   |                                        - ^^ the trait `B` is not implemented for `()`
+   |                                        |
+   |                                        required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/diagnostic-hir-wf-check.rs:10:1
+   |
+LL | trait B {}
+   | ^^^^^^^
+note: required by a bound in `W`
+  --> $DIR/diagnostic-hir-wf-check.rs:11:13
+   |
+LL | struct W<T: B>(T);
+   |             ^ required by this bound in `W`
+
+error[E0277]: the trait bound `(): B` is not satisfied
+  --> $DIR/diagnostic-hir-wf-check.rs:13:40
+   |
+LL | fn b() -> (W<()>, impl for<C> A<C>) { (W(()), ()) }
+   |                                        ^^^^^ the trait `B` is not implemented for `()`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/diagnostic-hir-wf-check.rs:10:1
+   |
+LL | trait B {}
+   | ^^^^^^^
+note: required by a bound in `W`
+  --> $DIR/diagnostic-hir-wf-check.rs:11:13
+   |
+LL | struct W<T: B>(T);
+   |             ^ required by this bound in `W`
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.