Rollup merge of #140848 - kornelski:not-a-dead-end, r=compiler-errors

Improved error message for top-level or-patterns

I was confused by "top-level or-patterns are not allowed in `let` bindings" error, because it sounded like or-patterns were completely unsupported.

This error has an auto-fix suggestion that shows otherwise, but the auto-fix isn't always visible in IDEs.

I've changed the wording to be consistent with "`Fn` bounds require arguments in parentheses", and it doesn't sound like a dead-end any more.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f2f6d1a..b6cb611 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -2099,7 +2099,6 @@
         three_way_compare,
         thumb2,
         thumb_mode: "thumb-mode",
-        time,
         tmm_reg,
         to_owned_method,
         to_string,
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index cf6dd40..00922c6 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -452,8 +452,6 @@
 }
     .label = type must be known at this point
 
-trait_selection_type_annotations_needed_error_time = this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update`
-
 trait_selection_types_declared_different = these two types are declared with different lifetimes...
 
 trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index de9a50f..cb1c9c7 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -6,7 +6,7 @@
 use rustc_errors::{Diag, IntoDiagArg};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
 use rustc_middle::bug;
@@ -17,7 +17,7 @@
     self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind,
     Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypeckResults,
 };
-use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym};
+use rustc_span::{BytePos, DUMMY_SP, Ident, Span, sym};
 use tracing::{debug, instrument, warn};
 
 use super::nice_region_error::placeholder_error::Highlighted;
@@ -438,7 +438,6 @@ fn bad_inference_failure_err(
                 bad_label,
                 was_written: false,
                 path: Default::default(),
-                time_version: false,
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -630,10 +629,6 @@ pub fn emit_inference_failure_err(
                 }
             }
         }
-
-        let time_version =
-            self.detect_old_time_crate_version(failure_span, &kind, &mut infer_subdiags);
-
         match error_code {
             TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
                 span,
@@ -645,7 +640,6 @@ pub fn emit_inference_failure_err(
                 bad_label: None,
                 was_written: path.is_some(),
                 path: path.unwrap_or_default(),
-                time_version,
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -671,42 +665,6 @@ pub fn emit_inference_failure_err(
             }),
         }
     }
-
-    /// Detect the inference regression on crate `time` <= 0.3.35 and emit a more targeted error.
-    /// <https://github.com/rust-lang/rust/issues/127343>
-    // FIXME: we should figure out a more generic version of doing this, ideally in cargo itself.
-    fn detect_old_time_crate_version(
-        &self,
-        span: Option<Span>,
-        kind: &InferSourceKind<'_>,
-        // We will clear the non-actionable suggestion from the error to reduce noise.
-        infer_subdiags: &mut Vec<SourceKindSubdiag<'_>>,
-    ) -> bool {
-        // FIXME(#129461): We are time-boxing this code in the compiler. It'll start failing
-        // compilation once we promote 1.89 to beta, which will happen in 9 months from now.
-        #[cfg(not(version("1.89")))]
-        const fn version_check() {}
-        #[cfg(version("1.89"))]
-        const fn version_check() {
-            panic!("remove this check as presumably the ecosystem has moved from needing it");
-        }
-        const { version_check() };
-        // Only relevant when building the `time` crate.
-        if self.infcx.tcx.crate_name(LOCAL_CRATE) == sym::time
-            && let Some(span) = span
-            && let InferSourceKind::LetBinding { pattern_name, .. } = kind
-            && let Some(name) = pattern_name
-            && name.as_str() == "items"
-            && let FileName::Real(file) = self.infcx.tcx.sess.source_map().span_to_filename(span)
-        {
-            let path = file.local_path_if_available().to_string_lossy();
-            if path.contains("format_description") && path.contains("parse") {
-                infer_subdiags.clear();
-                return true;
-            }
-        }
-        false
-    }
 }
 
 #[derive(Debug)]
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 04cae1c..8ab4d79 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -219,8 +219,6 @@ pub struct AnnotationRequired<'a> {
     #[note(trait_selection_full_type_written)]
     pub was_written: bool,
     pub path: PathBuf,
-    #[note(trait_selection_type_annotations_needed_error_time)]
-    pub time_version: bool,
 }
 
 // Copy of `AnnotationRequired` for E0283
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 4ef73ff..f93aa8f 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -174,7 +174,7 @@ pub(crate) struct Options {
     pub(crate) expanded_args: Vec<String>,
 
     /// Arguments to be used when compiling doctests.
-    pub(crate) doctest_compilation_args: Vec<String>,
+    pub(crate) doctest_build_args: Vec<String>,
 }
 
 impl fmt::Debug for Options {
@@ -802,7 +802,7 @@ fn println_condition(condition: Condition) {
         let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
         let with_examples = matches.opt_strs("with-examples");
         let call_locations = crate::scrape_examples::load_call_locations(with_examples, dcx);
-        let doctest_compilation_args = matches.opt_strs("doctest-compilation-args");
+        let doctest_build_args = matches.opt_strs("doctest-build-arg");
 
         let unstable_features =
             rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
@@ -851,7 +851,7 @@ fn println_condition(condition: Condition) {
             scrape_examples_options,
             unstable_features,
             expanded_args: args,
-            doctest_compilation_args,
+            doctest_build_args,
         };
         let render_options = RenderOptions {
             output,
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 0cdf2f9..ef70b86 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -51,46 +51,6 @@ pub(crate) struct GlobalTestOptions {
     pub(crate) args_file: PathBuf,
 }
 
-/// Function used to split command line arguments just like a shell would.
-fn split_args(args: &str) -> Vec<String> {
-    let mut out = Vec::new();
-    let mut iter = args.chars();
-    let mut current = String::new();
-
-    while let Some(c) = iter.next() {
-        if c == '\\' {
-            if let Some(c) = iter.next() {
-                // If it's escaped, even a quote or a whitespace will be ignored.
-                current.push(c);
-            }
-        } else if c == '"' || c == '\'' {
-            while let Some(new_c) = iter.next() {
-                if new_c == c {
-                    break;
-                } else if new_c == '\\' {
-                    if let Some(c) = iter.next() {
-                        // If it's escaped, even a quote will be ignored.
-                        current.push(c);
-                    }
-                } else {
-                    current.push(new_c);
-                }
-            }
-        } else if " \n\t\r".contains(c) {
-            if !current.is_empty() {
-                out.push(current.clone());
-                current.clear();
-            }
-        } else {
-            current.push(c);
-        }
-    }
-    if !current.is_empty() {
-        out.push(current);
-    }
-    out
-}
-
 pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) -> Result<(), String> {
     let mut file = File::create(file_path)
         .map_err(|error| format!("failed to create args file: {error:?}"))?;
@@ -119,9 +79,7 @@ pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) ->
         content.push(format!("-Z{unstable_option_str}"));
     }
 
-    for compilation_args in &options.doctest_compilation_args {
-        content.extend(split_args(compilation_args));
-    }
+    content.extend(options.doctest_build_args.clone());
 
     let content = content.join("\n");
 
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index 49add73..618c204 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -382,28 +382,6 @@ fn main() {
 }
 
 #[test]
-fn check_split_args() {
-    fn compare(input: &str, expected: &[&str]) {
-        let output = super::split_args(input);
-        let expected = expected.iter().map(|s| s.to_string()).collect::<Vec<_>>();
-        assert_eq!(expected, output, "test failed for {input:?}");
-    }
-
-    compare("'a' \"b\"c", &["a", "bc"]);
-    compare("'a' \"b \"c d", &["a", "b c", "d"]);
-    compare("'a' \"b\\\"c\"", &["a", "b\"c"]);
-    compare("'a\"'", &["a\""]);
-    compare("\"a'\"", &["a'"]);
-    compare("\\ a", &[" a"]);
-    compare("\\\\", &["\\"]);
-    compare("a'", &["a"]);
-    compare("a          ", &["a"]);
-    compare("a          b", &["a", "b"]);
-    compare("a\n\t \rb", &["a", "b"]);
-    compare("a\n\t1 \rb", &["a", "1", "b"]);
-}
-
-#[test]
 fn comment_in_attrs() {
     // If there is an inline code comment after attributes, we need to ensure that
     // a backline will be added to prevent generating code "inside" it (and thus generating)
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index bca40b8..b4210e7 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -73,9 +73,11 @@
 
 use std::env::{self, VarError};
 use std::io::{self, IsTerminal};
+use std::path::Path;
 use std::process;
 
 use rustc_errors::DiagCtxtHandle;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::interface;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option};
@@ -654,9 +656,9 @@ fn opts() -> Vec<RustcOptGroup> {
             Unstable,
             Multi,
             "",
-            "doctest-compilation-args",
-            "",
-            "add arguments to be used when compiling doctests",
+            "doctest-build-arg",
+            "One argument (of possibly many) to be used when compiling doctests",
+            "ARG",
         ),
         opt(
             Unstable,
@@ -904,6 +906,10 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
                 rustc_interface::passes::write_dep_info(tcx);
             }
 
+            if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir {
+                dump_feature_usage_metrics(tcx, metrics_dir);
+            }
+
             if run_check {
                 // Since we're in "check" mode, no need to generate anything beyond this point.
                 return;
@@ -923,3 +929,16 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
         })
     })
 }
+
+fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) {
+    let hash = tcxt.crate_hash(LOCAL_CRATE);
+    let crate_name = tcxt.crate_name(LOCAL_CRATE);
+    let metrics_file_name = format!("unstable_feature_usage_metrics-{crate_name}-{hash}.json");
+    let metrics_path = metrics_dir.join(metrics_file_name);
+    if let Err(error) = tcxt.features().dump_feature_usage_metrics(metrics_path) {
+        // FIXME(yaahc): once metrics can be enabled by default we will want "failure to emit
+        // default metrics" to only produce a warning when metrics are enabled by default and emit
+        // an error only when the user manually enables metrics
+        tcxt.dcx().err(format!("cannot emit feature usage metrics: {error}"));
+    }
+}
diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
index 70a72bd..b46ddd1 100644
--- a/src/tools/run-make-support/src/command.rs
+++ b/src/tools/run-make-support/src/command.rs
@@ -63,6 +63,12 @@ pub fn new<P: AsRef<OsStr>>(program: P) -> Self {
         }
     }
 
+    // Internal-only.
+    pub(crate) fn into_raw_command(mut self) -> std::process::Command {
+        self.drop_bomb.defuse();
+        self.cmd
+    }
+
     /// Specify a stdin input buffer. This is a convenience helper,
     pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
         self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice());
diff --git a/src/tools/run-make-support/src/external_deps/rustdoc.rs b/src/tools/run-make-support/src/external_deps/rustdoc.rs
index 433a57c..7040fb6 100644
--- a/src/tools/run-make-support/src/external_deps/rustdoc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
@@ -5,7 +5,7 @@
 use crate::env::env_var;
 use crate::util::set_host_compiler_dylib_path;
 
-/// Construct a new `rustdoc` invocation.
+/// Construct a new `rustdoc` invocation. This will configure the host compiler runtime libs.
 #[track_caller]
 pub fn rustdoc() -> Rustdoc {
     Rustdoc::new()
@@ -28,7 +28,7 @@ fn setup_common() -> Command {
 }
 
 impl Rustdoc {
-    /// Construct a bare `rustdoc` invocation.
+    /// Construct a bare `rustdoc` invocation. This will configure the host compiler runtime libs.
     #[track_caller]
     pub fn new() -> Self {
         let cmd = setup_common();
diff --git a/src/tools/run-make-support/src/macros.rs b/src/tools/run-make-support/src/macros.rs
index 94955ae..9d5cc4e 100644
--- a/src/tools/run-make-support/src/macros.rs
+++ b/src/tools/run-make-support/src/macros.rs
@@ -28,6 +28,18 @@
 macro_rules! impl_common_helpers {
     ($wrapper: ident) => {
         impl $wrapper {
+            /// In very rare circumstances, you may need a e.g. `bare_rustc()` or `bare_rustdoc()`
+            /// with host runtime libs configured, but want the underlying raw
+            /// [`std::process::Command`] (e.g. for manipulating pipes or whatever). This function
+            /// will consume the command wrapper and extract the underlying
+            /// [`std::process::Command`].
+            ///
+            /// Caution: this will mean that you can no longer use the convenience methods on the
+            /// command wrapper. Use as a last resort.
+            pub fn into_raw_command(self) -> ::std::process::Command {
+                self.cmd.into_raw_command()
+            }
+
             /// Specify an environment variable.
             pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Self
             where
diff --git a/src/version b/src/version
index 59be592..636ea71 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.88.0
+1.89.0
diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs
index 0521b39..b0a28b6 100644
--- a/tests/run-make/broken-pipe-no-ice/rmake.rs
+++ b/tests/run-make/broken-pipe-no-ice/rmake.rs
@@ -14,7 +14,7 @@
 use std::io::Read;
 use std::process::{Command, Stdio};
 
-use run_make_support::env_var;
+use run_make_support::{bare_rustc, rustdoc};
 
 #[derive(Debug, PartialEq)]
 enum Binary {
@@ -67,11 +67,13 @@ fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) {
 }
 
 fn main() {
-    let mut rustc = Command::new(env_var("RUSTC"));
+    let mut rustc = bare_rustc();
     rustc.arg("--print=sysroot");
+    let rustc = rustc.into_raw_command();
     check_broken_pipe_handled_gracefully(Binary::Rustc, rustc);
 
-    let mut rustdoc = Command::new(env_var("RUSTDOC"));
+    let mut rustdoc = rustdoc();
     rustdoc.arg("--version");
+    let rustdoc = rustdoc.into_raw_command();
     check_broken_pipe_handled_gracefully(Binary::Rustdoc, rustdoc);
 }
diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout
index 78ca8c8..506f135 100644
--- a/tests/run-make/rustdoc-default-output/output-default.stdout
+++ b/tests/run-make/rustdoc-default-output/output-default.stdout
@@ -188,8 +188,9 @@
                         from provided path. Only use with --merge=finalize
         --html-no-source 
                         Disable HTML source code pages generation
-        --doctest-compilation-args add arguments to be used when compiling doctests
-                        
+        --doctest-build-arg ARG
+                        One argument (of possibly many) to be used when
+                        compiling doctests
         --disable-minification 
                         disable the minification of CSS/JS files
                         (perma-unstable, do not use with cached files)
diff --git a/tests/rustdoc-ui/doctest/rustflags-multiple-args.rs b/tests/rustdoc-ui/doctest/rustflags-multiple-args.rs
index 8d8c60e..88e2e0c 100644
--- a/tests/rustdoc-ui/doctest/rustflags-multiple-args.rs
+++ b/tests/rustdoc-ui/doctest/rustflags-multiple-args.rs
@@ -1,9 +1,8 @@
-// This test checks that the test behave when `--doctest-compilation-args` is passed
-// multiple times.
+// This test checks that the test behave when `--doctest-build-arg` is passed multiple times.
 
 //@ check-pass
-//@ compile-flags: --test -Zunstable-options --doctest-compilation-args=--cfg=testcase_must_be_present
-//@ compile-flags: --doctest-compilation-args=--cfg=another
+//@ compile-flags: --test -Zunstable-options --doctest-build-arg=--cfg=testcase_must_be_present
+//@ compile-flags: --doctest-build-arg=--cfg=another
 //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
 //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
 
diff --git a/tests/rustdoc-ui/doctest/rustflags-multiple-args.stdout b/tests/rustdoc-ui/doctest/rustflags-multiple-args.stdout
index 0e8a9e1..f6b8ad6 100644
--- a/tests/rustdoc-ui/doctest/rustflags-multiple-args.stdout
+++ b/tests/rustdoc-ui/doctest/rustflags-multiple-args.stdout
@@ -1,6 +1,6 @@
 
 running 1 test
-test $DIR/rustflags-multiple-args.rs - Bar (line 10) ... ok
+test $DIR/rustflags-multiple-args.rs - Bar (line 9) ... ok
 
 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
 
diff --git a/tests/rustdoc-ui/doctest/rustflags.rs b/tests/rustdoc-ui/doctest/rustflags.rs
index 9f1e601..f030158 100644
--- a/tests/rustdoc-ui/doctest/rustflags.rs
+++ b/tests/rustdoc-ui/doctest/rustflags.rs
@@ -1,5 +1,5 @@
 //@ check-pass
-//@ compile-flags: --test -Zunstable-options --doctest-compilation-args=--cfg=testcase_must_be_present
+//@ compile-flags: --test -Zunstable-options --doctest-build-arg=--cfg=testcase_must_be_present
 //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR"
 //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
 
diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.rs b/tests/ui/inference/detect-old-time-version-format_description-parse.rs
deleted file mode 100644
index 386b2a3..0000000
--- a/tests/ui/inference/detect-old-time-version-format_description-parse.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#![crate_name = "time"]
-#![crate_type = "lib"]
-
-// This code compiled without error in Rust 1.79, but started failing in 1.80
-// after the addition of several `impl FromIterator<_> for Box<str>`.
-
-pub fn parse() -> Option<Vec<()>> {
-    let iter = std::iter::once(Some(())).map(|o| o.map(Into::into));
-    let items = iter.collect::<Option<Box<_>>>()?; //~ ERROR E0282
-    //~^ NOTE this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35`
-    Some(items.into())
-    //~^ NOTE type must be known at this point
-}
diff --git a/tests/ui/inference/detect-old-time-version-format_description-parse.stderr b/tests/ui/inference/detect-old-time-version-format_description-parse.stderr
deleted file mode 100644
index a70ce9d..0000000
--- a/tests/ui/inference/detect-old-time-version-format_description-parse.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0282]: type annotations needed for `Box<_>`
-  --> $DIR/detect-old-time-version-format_description-parse.rs:9:9
-   |
-LL |     let items = iter.collect::<Option<Box<_>>>()?;
-   |         ^^^^^
-LL |
-LL |     Some(items.into())
-   |                ---- type must be known at this point
-   |
-   = note: this is an inference error on crate `time` caused by an API change in Rust 1.80.0; update `time` to version `>=0.3.35` by calling `cargo update`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs
new file mode 100644
index 0000000..f90ff91
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.rs
@@ -0,0 +1,32 @@
+// This test demonstrates an ICE that may occur when we try to resolve the instance
+// of a impl that has different generics than the trait it's implementing. This ensures
+// we first check that the args are compatible before resolving the body, just like
+// we do in projection before substituting a GAT.
+//
+// Regression test for issue #125877.
+
+//@ compile-flags: -Znext-solver
+
+#![feature(const_trait_impl, effects)]
+//~^ ERROR feature has been removed
+
+#[const_trait]
+trait Main {
+    fn compute<T: ~const Aux>() -> u32;
+}
+
+impl const Main for () {
+    fn compute<'x>() -> u32 {
+        //~^ ERROR associated function `compute` has 0 type parameters but its trait declaration has 1 type parameter
+        0
+    }
+}
+
+#[const_trait]
+trait Aux {}
+
+impl const Aux for () {}
+
+fn main() {
+    const _: u32 = <()>::compute::<()>();
+}
diff --git a/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr
new file mode 100644
index 0000000..d45c4cb
--- /dev/null
+++ b/tests/ui/traits/const-traits/const-trait-impl-parameter-mismatch.stderr
@@ -0,0 +1,21 @@
+error[E0557]: feature has been removed
+  --> $DIR/const-trait-impl-parameter-mismatch.rs:10:30
+   |
+LL | #![feature(const_trait_impl, effects)]
+   |                              ^^^^^^^ feature has been removed
+   |
+   = note: removed, redundant with `#![feature(const_trait_impl)]`
+
+error[E0049]: associated function `compute` has 0 type parameters but its trait declaration has 1 type parameter
+  --> $DIR/const-trait-impl-parameter-mismatch.rs:19:16
+   |
+LL |     fn compute<T: ~const Aux>() -> u32;
+   |                - expected 1 type parameter
+...
+LL |     fn compute<'x>() -> u32 {
+   |                ^^ found 0 type parameters
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0049, E0557.
+For more information about an error, try `rustc --explain E0049`.