about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--compiler/rustc_ast_passes/messages.ftl3
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs7
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs36
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs8
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--library/std/src/sys/pal/unix/net.rs5
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css5
-rw-r--r--tests/crashes/127009.rs11
-rw-r--r--tests/rustdoc-gui/source-code-page-code-scroll.goml4
-rw-r--r--tests/rustdoc-gui/src/test_docs/lib.rs8
-rw-r--r--tests/rustdoc-gui/stab-in-doc.goml9
-rw-r--r--tests/ui/closures/binder/const-bound.rs3
-rw-r--r--tests/ui/closures/binder/const-bound.stderr8
-rw-r--r--tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs3
-rw-r--r--tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr8
-rw-r--r--tests/ui/lto/debuginfo-lto-alloc.rs3
-rw-r--r--tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr9
-rw-r--r--tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr1
-rw-r--r--tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs3
-rw-r--r--tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr8
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs5
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr12
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs5
-rw-r--r--tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr8
-rw-r--r--tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs11
-rw-r--r--tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr17
29 files changed, 172 insertions, 57 deletions
diff --git a/.gitignore b/.gitignore
index f1ca6a79b5c..87d02563ed0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,7 +50,6 @@ build/
 /target
 /src/bootstrap/target
 /src/tools/x/target
-/inc-fat/
 # Created by default with `src/ci/docker/run.sh`
 /obj/
 /rustc-ice*
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 8f7dd774207..ca0b7f2ac3a 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -120,6 +120,9 @@ ast_passes_fn_without_body =
 ast_passes_forbidden_bound =
     bounds cannot be used in this context
 
+ast_passes_forbidden_const_param =
+    late-bound const parameters cannot be used currently
+
 ast_passes_forbidden_default =
     `default` is only allowed on items in trait impls
     .label = `default` because of this
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 783bca6b695..215ccd2ab4d 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -70,6 +70,13 @@ pub struct ForbiddenBound {
 }
 
 #[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_const_param)]
+pub struct ForbiddenConstParam {
+    #[primary_span]
+    pub const_param_spans: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
 #[diag(ast_passes_fn_param_too_many)]
 pub struct FnParamTooMany {
     #[primary_span]
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 2178b65727d..e91dfb27766 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -162,6 +162,22 @@ impl<'a> PostExpansionVisitor<'a> {
             crate::fluent_generated::ast_passes_forbidden_non_lifetime_param
         );
 
+        // FIXME(non_lifetime_binders): Const bound params are pretty broken.
+        // Let's keep users from using this feature accidentally.
+        if self.features.non_lifetime_binders {
+            let const_param_spans: Vec<_> = params
+                .iter()
+                .filter_map(|param| match param.kind {
+                    ast::GenericParamKind::Const { .. } => Some(param.ident.span),
+                    _ => None,
+                })
+                .collect();
+
+            if !const_param_spans.is_empty() {
+                self.sess.dcx().emit_err(errors::ForbiddenConstParam { const_param_spans });
+            }
+        }
+
         for param in params {
             if !param.bounds.is_empty() {
                 let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 7930f54038d..349dc9ad00e 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -2094,11 +2094,7 @@ pub fn deny_non_region_late_bound(
             format!("late-bound {what} parameter not allowed on {where_}"),
         );
 
-        let guar = if tcx.features().non_lifetime_binders && first {
-            diag.emit()
-        } else {
-            diag.delay_as_bug()
-        };
+        let guar = diag.emit_unless(!tcx.features().non_lifetime_binders || !first);
 
         first = false;
         *arg = ResolvedArg::Error(guar);
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 70065b5a2c3..95799cec94b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -16,8 +16,8 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_pattern_analysis::errors::Uncovered;
 use rustc_pattern_analysis::rustc::{
-    Constructor, DeconstructedPat, MatchArm, RustcPatCtxt as PatCtxt, Usefulness, UsefulnessReport,
-    WitnessPat,
+    Constructor, DeconstructedPat, MatchArm, RevealedTy, RustcPatCtxt as PatCtxt, Usefulness,
+    UsefulnessReport, WitnessPat,
 };
 use rustc_session::lint::builtin::{
     BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
@@ -998,27 +998,31 @@ fn report_non_exhaustive_match<'p, 'tcx>(
     err.note(format!("the matched value is of type `{}`", scrut_ty));
 
     if !is_empty_match {
-        let mut non_exhaustive_tys = FxIndexSet::default();
+        let mut special_tys = FxIndexSet::default();
         // Look at the first witness.
-        collect_non_exhaustive_tys(cx, &witnesses[0], &mut non_exhaustive_tys);
+        collect_special_tys(cx, &witnesses[0], &mut special_tys);
 
-        for ty in non_exhaustive_tys {
+        for ty in special_tys {
             if ty.is_ptr_sized_integral() {
-                if ty == cx.tcx.types.usize {
+                if ty.inner() == cx.tcx.types.usize {
                     err.note(format!(
                         "`{ty}` does not have a fixed maximum value, so half-open ranges are necessary to match \
                              exhaustively",
                     ));
-                } else if ty == cx.tcx.types.isize {
+                } else if ty.inner() == cx.tcx.types.isize {
                     err.note(format!(
                         "`{ty}` does not have fixed minimum and maximum values, so half-open ranges are necessary to match \
                              exhaustively",
                     ));
                 }
-            } else if ty == cx.tcx.types.str_ {
+            } else if ty.inner() == cx.tcx.types.str_ {
                 err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary");
-            } else if cx.is_foreign_non_exhaustive_enum(cx.reveal_opaque_ty(ty)) {
+            } else if cx.is_foreign_non_exhaustive_enum(ty) {
                 err.note(format!("`{ty}` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively"));
+            } else if cx.is_uninhabited(ty.inner()) && cx.tcx.features().min_exhaustive_patterns {
+                // The type is uninhabited yet there is a witness: we must be in the `MaybeInvalid`
+                // case.
+                err.note(format!("`{ty}` is uninhabited but is not being matched by value, so a wildcard `_` is required"));
             }
         }
     }
@@ -1168,22 +1172,22 @@ fn joined_uncovered_patterns<'p, 'tcx>(
     }
 }
 
-fn collect_non_exhaustive_tys<'tcx>(
+/// Collect types that require specific explanations when they show up in witnesses.
+fn collect_special_tys<'tcx>(
     cx: &PatCtxt<'_, 'tcx>,
     pat: &WitnessPat<'_, 'tcx>,
-    non_exhaustive_tys: &mut FxIndexSet<Ty<'tcx>>,
+    special_tys: &mut FxIndexSet<RevealedTy<'tcx>>,
 ) {
-    if matches!(pat.ctor(), Constructor::NonExhaustive) {
-        non_exhaustive_tys.insert(pat.ty().inner());
+    if matches!(pat.ctor(), Constructor::NonExhaustive | Constructor::Never) {
+        special_tys.insert(*pat.ty());
     }
     if let Constructor::IntRange(range) = pat.ctor() {
         if cx.is_range_beyond_boundaries(range, *pat.ty()) {
             // The range denotes the values before `isize::MIN` or the values after `usize::MAX`/`isize::MAX`.
-            non_exhaustive_tys.insert(pat.ty().inner());
+            special_tys.insert(*pat.ty());
         }
     }
-    pat.iter_fields()
-        .for_each(|field_pat| collect_non_exhaustive_tys(cx, field_pat, non_exhaustive_tys))
+    pat.iter_fields().for_each(|field_pat| collect_special_tys(cx, field_pat, special_tys))
 }
 
 fn report_adt_defined_here<'tcx>(
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index d17ee8bff50..6ef2d69273e 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -40,9 +40,15 @@ pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat<RustcPatCtxt<'p, 'tcx>>;
 ///
 /// Use `.inner()` or deref to get to the `Ty<'tcx>`.
 #[repr(transparent)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub struct RevealedTy<'tcx>(Ty<'tcx>);
 
+impl<'tcx> fmt::Display for RevealedTy<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(fmt)
+    }
+}
+
 impl<'tcx> fmt::Debug for RevealedTy<'tcx> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.0.fmt(fmt)
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index dc7200465d9..51414d78596 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2763,7 +2763,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             let res = match kind {
                 RibKind::Item(..) | RibKind::AssocItem => Res::Def(def_kind, def_id.to_def_id()),
                 RibKind::Normal => {
-                    if self.r.tcx.features().non_lifetime_binders {
+                    // FIXME(non_lifetime_binders): Stop special-casing
+                    // const params to error out here.
+                    if self.r.tcx.features().non_lifetime_binders
+                        && matches!(param.kind, GenericParamKind::Type { .. })
+                    {
                         Res::Def(def_kind, def_id.to_def_id())
                     } else {
                         Res::Err
diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs
index b8dc1538a63..bedb06043a7 100644
--- a/library/std/src/sys/pal/unix/net.rs
+++ b/library/std/src/sys/pal/unix/net.rs
@@ -4,7 +4,6 @@ use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
 use crate::mem;
 use crate::net::{Shutdown, SocketAddr};
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
-use crate::str;
 use crate::sys::fd::FileDesc;
 use crate::sys::pal::unix::IsMinusOne;
 use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
@@ -47,7 +46,9 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
 
     #[cfg(not(target_os = "espidf"))]
     let detail = unsafe {
-        str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap().to_owned()
+        // We can't always expect a UTF-8 environment. When we don't get that luxury,
+        // it's better to give a low-quality error message than none at all.
+        CStr::from_ptr(libc::gai_strerror(err)).to_string_lossy()
     };
 
     #[cfg(target_os = "espidf")]
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 28ed94432c8..4445c0e9575 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -831,6 +831,10 @@ pre, .rustdoc.src .example-wrap {
 	background: var(--table-alt-row-background-color);
 }
 
+.docblock .stab, .docblock-short .stab {
+	display: inline-block;
+}
+
 /* "where ..." clauses with block display are also smaller */
 div.where {
 	white-space: pre-wrap;
@@ -953,6 +957,7 @@ table,
 	display: table;
 	padding: 0;
 	margin: 0;
+	width: 100%;
 }
 .item-table > li {
 	display: table-row;
diff --git a/tests/crashes/127009.rs b/tests/crashes/127009.rs
deleted file mode 100644
index 74ca14393e4..00000000000
--- a/tests/crashes/127009.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: #127009
-
-#![feature(non_lifetime_binders)]
-
-fn b()
-where
-    for<const C: usize> [(); C]: Copy,
-{
-}
-
-fn main() {}
diff --git a/tests/rustdoc-gui/source-code-page-code-scroll.goml b/tests/rustdoc-gui/source-code-page-code-scroll.goml
index 35f338ea328..31ab281d6ce 100644
--- a/tests/rustdoc-gui/source-code-page-code-scroll.goml
+++ b/tests/rustdoc-gui/source-code-page-code-scroll.goml
@@ -2,7 +2,7 @@
 go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 set-window-size: (800, 1000)
 // "scrollWidth" should be superior than "clientWidth".
-assert-property: ("body", {"scrollWidth": 1047, "clientWidth": 800})
+assert-property: ("body", {"scrollWidth": 1114, "clientWidth": 800})
 
 // Both properties should be equal (ie, no scroll on the code block).
-assert-property: (".example-wrap .rust", {"scrollWidth": 933, "clientWidth": 933})
+assert-property: (".example-wrap .rust", {"scrollWidth": 1000, "clientWidth": 1000})
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 6c638dc3b9d..244c1b9c5cd 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -20,10 +20,10 @@ Also, stop using `bar` as it's <span class="stab deprecated" title="">deprecated
 Also, stop using `bar` as it's <span class="stab deprecated" title="">deprecated</span>.
 Also, stop using `bar` as it's <span class="stab deprecated" title="">deprecated</span>.
 
-Finally, you can use `quz` only on <span class="stab portability"><code>Unix or x86-64</code>
-</span>.
-Finally, you can use `quz` only on <span class="stab portability"><code>Unix or x86-64</code>
-</span>.
+Finally, you can use `quz` only on <span class="stab portability" data-span="1"><code>Unix or x86-64
+</code></span>.
+Finally, you can use `quz` only on <span class="stab portability" data-span="2"><code>Unix or x86-64
+</code></span>.
 */
 
 use std::convert::AsRef;
diff --git a/tests/rustdoc-gui/stab-in-doc.goml b/tests/rustdoc-gui/stab-in-doc.goml
new file mode 100644
index 00000000000..6a03a51fe9f
--- /dev/null
+++ b/tests/rustdoc-gui/stab-in-doc.goml
@@ -0,0 +1,9 @@
+// This test ensure that `stab` elements if used in doc blocks are not breaking the text layout.
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+// We make the window wide enough for the two stabs who are looking into to be on the same line.
+set-window-size: (1100, 600)
+compare-elements-position: (
+    ".top-doc .docblock span[data-span='1']",
+    ".top-doc .docblock span[data-span='2']",
+    ["y"],
+)
diff --git a/tests/ui/closures/binder/const-bound.rs b/tests/ui/closures/binder/const-bound.rs
index b1c79db1375..10d869fcc85 100644
--- a/tests/ui/closures/binder/const-bound.rs
+++ b/tests/ui/closures/binder/const-bound.rs
@@ -3,5 +3,6 @@
 
 fn main()  {
     for<const N: i32> || -> () {};
-    //~^ ERROR late-bound const parameter not allowed on closures
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR late-bound const parameter not allowed on closures
 }
diff --git a/tests/ui/closures/binder/const-bound.stderr b/tests/ui/closures/binder/const-bound.stderr
index 9c4fd95ed76..b805879f7fa 100644
--- a/tests/ui/closures/binder/const-bound.stderr
+++ b/tests/ui/closures/binder/const-bound.stderr
@@ -1,3 +1,9 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/const-bound.rs:5:15
+   |
+LL |     for<const N: i32> || -> () {};
+   |               ^
+
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/const-bound.rs:1:37
    |
@@ -13,5 +19,5 @@ error: late-bound const parameter not allowed on closures
 LL |     for<const N: i32> || -> () {};
    |         ^^^^^^^^^^^^
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs b/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs
index 5673f1dd073..ffa9d960e04 100644
--- a/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs
+++ b/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.rs
@@ -7,7 +7,8 @@
 pub fn foo()
 where
     for<const N: usize = { const fn bar() {} bar(); 1 }> ():,
-    //~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
 {}
 
 fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr b/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr
index 5924a673da9..814022f26b9 100644
--- a/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/no-entry-found-for-key-ice-gce-nlb-113133.stderr
@@ -1,8 +1,14 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/no-entry-found-for-key-ice-gce-nlb-113133.rs:9:15
+   |
+LL |     for<const N: usize = { const fn bar() {} bar(); 1 }> ():,
+   |               ^
+
 error: defaults for generic parameters are not allowed in `for<...>` binders
   --> $DIR/no-entry-found-for-key-ice-gce-nlb-113133.rs:9:9
    |
 LL |     for<const N: usize = { const fn bar() {} bar(); 1 }> ():,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lto/debuginfo-lto-alloc.rs b/tests/ui/lto/debuginfo-lto-alloc.rs
index 459103c354c..89043275329 100644
--- a/tests/ui/lto/debuginfo-lto-alloc.rs
+++ b/tests/ui/lto/debuginfo-lto-alloc.rs
@@ -9,7 +9,8 @@
 // that compilation is successful.
 
 //@ check-pass
-//@ compile-flags: --test -C debuginfo=2 -C lto=fat -C incremental=inc-fat
+//@ compile-flags: --test -C debuginfo=2 -C lto=fat
+//@ incremental
 
 extern crate alloc;
 
diff --git a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr
index 6e50dfe6a26..9b57c895eea 100644
--- a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr
@@ -204,6 +204,7 @@ note: `Option<Void>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Option<Void>`
+   = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~             None => {},
@@ -349,6 +350,7 @@ LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[_, ..]` not covered
    |
    = note: the matched value is of type `&[!]`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         [] => {},
@@ -484,6 +486,7 @@ note: `Option<!>` defined here
    |
    = note: not covered
    = note: the matched value is of type `&Option<!>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         &None => {},
@@ -502,6 +505,7 @@ note: `Option<!>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Option<!>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         None => {},
@@ -520,6 +524,7 @@ note: `Result<!, !>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Result<!, !>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         Ok(_) => {},
@@ -538,6 +543,7 @@ note: `Result<!, !>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Result<!, !>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         Ok(_a) => {},
@@ -589,6 +595,7 @@ LL |     match ref_never {
    |           ^^^^^^^^^ pattern `&_` not covered
    |
    = note: the matched value is of type `&!`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
    = note: references are always considered inhabited
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
@@ -609,6 +616,7 @@ note: `Result<!, !>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Result<!, !>`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         Err(_) => {},
@@ -627,6 +635,7 @@ note: `Option<Result<!, !>>` defined here
    |
    = note: not covered
    = note: the matched value is of type `Option<Result<!, !>>`
+   = note: `Result<!, !>` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         None => {},
diff --git a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr
index a1239466c9c..f24ce154d14 100644
--- a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr
@@ -5,6 +5,7 @@ LL |     match nevers {
    |           ^^^^^^ pattern `&[_, ..]` not covered
    |
    = note: the matched value is of type `&[!]`
+   = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         &[] => (),
diff --git a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs
index fc64381b961..b61a21eab41 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs
+++ b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.rs
@@ -18,7 +18,8 @@ trait TraitC {}
 fn foo<T>()
 where
     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>,
-    //~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
     //~| ERROR `impl Trait` is not allowed in bounds
 {
 }
diff --git a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr
index a4a79413a9b..e891df3f0c0 100644
--- a/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr
+++ b/tests/ui/traits/non_lifetime_binders/bad-suggestion-on-missing-assoc.stderr
@@ -1,3 +1,9 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/bad-suggestion-on-missing-assoc.rs:20:15
+   |
+LL |     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>,
+   |               ^
+
 warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/bad-suggestion-on-missing-assoc.rs:1:12
    |
@@ -29,6 +35,6 @@ LL |     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl Trai
    |
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
-error: aborting due to 2 previous errors; 2 warnings emitted
+error: aborting due to 3 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
index c6bf0dc1f72..13f9f196970 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
@@ -4,10 +4,11 @@
 pub fn bar()
 where
     for<const N: usize = {
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
     (||1usize)()
 }> V: IntoIterator
-//~^^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
-//~^^ ERROR cannot find type `V` in this scope
+//~^ ERROR cannot find type `V` in this scope
 {
 }
 
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
index edc55a3c8e6..d9e77dec794 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
@@ -1,5 +1,5 @@
 error[E0412]: cannot find type `V` in this scope
-  --> $DIR/binder-defaults-112547.rs:8:4
+  --> $DIR/binder-defaults-112547.rs:10:4
    |
 LL | }> V: IntoIterator
    |    ^ not found in this scope
@@ -9,6 +9,12 @@ help: you might be missing a type parameter
 LL | pub fn bar<V>()
    |           +++
 
+error: late-bound const parameters cannot be used currently
+  --> $DIR/binder-defaults-112547.rs:6:15
+   |
+LL |     for<const N: usize = {
+   |               ^
+
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/binder-defaults-112547.rs:1:12
    |
@@ -23,10 +29,12 @@ error: defaults for generic parameters are not allowed in `for<...>` binders
    |
 LL |       for<const N: usize = {
    |  _________^
+LL | |
+LL | |
 LL | |     (||1usize)()
 LL | | }> V: IntoIterator
    | |_^
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 3 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
index f33da416ad8..bdfe41ca11b 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
@@ -5,8 +5,9 @@
 fn fun()
 where
     for<T = (), const N: usize = 1> ():,
-//~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
-//~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~^ ERROR late-bound const parameters cannot be used currently
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
+    //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
 {}
 
 fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
index 7fe82f1f097..947dd3a73bf 100644
--- a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
@@ -1,3 +1,9 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/binder-defaults-119489.rs:7:23
+   |
+LL |     for<T = (), const N: usize = 1> ():,
+   |                       ^
+
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/binder-defaults-119489.rs:1:12
    |
@@ -27,5 +33,5 @@ error: defaults for generic parameters are not allowed in `for<...>` binders
 LL |     for<T = (), const N: usize = 1> ():,
    |                 ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 2 warnings emitted
+error: aborting due to 3 previous errors; 2 warnings emitted
 
diff --git a/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs
new file mode 100644
index 00000000000..2d44388f875
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.rs
@@ -0,0 +1,11 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn b()
+where
+    for<const C: usize> [(); C]: Copy,
+    //~^ ERROR late-bound const parameters cannot be used currently
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr
new file mode 100644
index 00000000000..136d533a03c
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/late-const-param-wf.stderr
@@ -0,0 +1,17 @@
+error: late-bound const parameters cannot be used currently
+  --> $DIR/late-const-param-wf.rs:6:15
+   |
+LL |     for<const C: usize> [(); C]: Copy,
+   |               ^
+
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/late-const-param-wf.rs:1: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: aborting due to 1 previous error; 1 warning emitted
+