about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-04-10 00:11:52 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-04-10 00:41:27 +0000
commit796be88062721f93df01e07c5dad8cd0783bea65 (patch)
tree4238c2175a76a6a672da57b3c636db2733791524
parente78913baef70895c966f0456ad16086a6a9aa37b (diff)
downloadrust-796be88062721f93df01e07c5dad8cd0783bea65.tar.gz
rust-796be88062721f93df01e07c5dad8cd0783bea65.zip
Use `fn` ptr signature instead of `{closure@..}` in infer error
When suggesting a type on inference error, do not use `{closure@..}`.
Instead, replace with an appropriate `fn` ptr.

On the error message, use `short_ty_string` and write long types to
disk.

```
error[E0284]: type annotations needed for `Select<{closure@lib.rs:2782:13}, _, Expression<'_>, _>`
  --> crates/lang/src/parser.rs:41:13
   |
41 |         let lit = select! {
   |             ^^^
42 |             Token::Int(i) = e => Expression::new(Expr::Lit(ast::Lit::Int(i.parse().unwrap())), e.span()),
   |                                                                                                  ---- type must be known at this point
   |
   = note: the full type name has been written to '/home/gh-estebank/iowo/target/debug/deps/lang-e2d6e25819442273.long-type-4587393693885174369.txt'
   = note: cannot satisfy `<_ as chumsky::input::Input<'_>>::Span == SimpleSpan`
help: consider giving `lit` an explicit type, where the type for type parameter `I` is specified
   |
41 |         let lit: Select<for<'a, 'b> fn(tokens::Token<'_>, &'a mut MapExtra<'_, 'b, _, _>) -> Option<Expression<'_>>, _, Expression<'_>, _> = select! {
   |                +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
```

instead of

```
error[E0284]: type annotations needed for `Select<{closure@/home/gh-estebank/.cargo/registry/src/index.crates.io-6f17d22bba15001f/chumsky-1.0.0-alpha.6/src/lib.rs:2782:13: 2782:28}, _, Expression<'_>, _>`
  --> crates/lang/src/parser.rs:41:13
   |
41 |         let lit = select! {
   |             ^^^
42 |             Token::Int(i) = e => Expression::new(Expr::Lit(ast::Lit::Int(i.parse().unwrap())), e.span()),
   |                                                                                                  ---- type must be known at this point
   |
   = note: cannot satisfy `<_ as chumsky::input::Input<'_>>::Span == SimpleSpan`
help: consider giving `lit` an explicit type, where the type for type parameter `I` is specified
   |
41 |         let lit: Select<{closure@/home/gh-estebank/.cargo/registry/src/index.crates.io-6f17d22bba15001f/chumsky-1.0.0-alpha.6/src/lib.rs:2782:13: 2782:28}, _, Expression<'_>, _> = select! {
   |                ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
```

Fix #123630.
-rw-r--r--compiler/rustc_infer/messages.ftl3
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs11
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs75
-rw-r--r--tests/ui/array-slice-vec/vector-no-ann.stderr2
-rw-r--r--tests/ui/const-generics/defaults/doesnt_infer.rs2
-rw-r--r--tests/ui/const-generics/defaults/doesnt_infer.stderr2
-rw-r--r--tests/ui/const-generics/generic_arg_infer/issue-91614.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr2
-rw-r--r--tests/ui/generic-const-items/inference-failure.stderr2
-rw-r--r--tests/ui/generic-const-items/parameter-defaults.stderr2
-rw-r--r--tests/ui/inference/cannot-infer-closure-circular.rs2
-rw-r--r--tests/ui/inference/cannot-infer-closure-circular.stderr2
-rw-r--r--tests/ui/inference/erase-type-params-in-label.stderr4
-rw-r--r--tests/ui/inference/issue-104649.stderr2
-rw-r--r--tests/ui/inference/issue-72690.stderr2
-rw-r--r--tests/ui/inference/issue-83606.rs2
-rw-r--r--tests/ui/inference/issue-83606.stderr2
-rw-r--r--tests/ui/issues/issue-12187-1.stderr2
-rw-r--r--tests/ui/issues/issue-12187-2.stderr2
-rw-r--r--tests/ui/issues/issue-17551.stderr2
-rw-r--r--tests/ui/issues/issue-23046.stderr2
-rw-r--r--tests/ui/issues/issue-98299.stderr2
-rw-r--r--tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr2
-rw-r--r--tests/ui/traits/copy-guessing.rs2
-rw-r--r--tests/ui/traits/copy-guessing.stderr2
-rw-r--r--tests/ui/traits/issue-77982.stderr4
-rw-r--r--tests/ui/type-inference/or_else-multiple-type-params.stderr2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr2
29 files changed, 98 insertions, 47 deletions
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index fdb6ab8f59b..64f52ea7ac1 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -144,6 +144,9 @@ infer_fps_items_are_distinct = fn items are distinct from fn pointers
 infer_fps_remove_ref = consider removing the reference
 infer_fps_use_ref = consider using a reference
 infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
+
+infer_full_type_written = the full type name has been written to '{$path}'
+
 infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
 infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
 infer_label_bad = {$bad_kind ->
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 6192eaf3c3a..4593108edac 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -18,6 +18,8 @@ use crate::infer::error_reporting::{
     ObligationCauseAsDiagArg,
 };
 
+use std::path::PathBuf;
+
 pub mod note_and_explain;
 
 #[derive(Diagnostic)]
@@ -47,6 +49,9 @@ pub struct AnnotationRequired<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
+    #[note(infer_full_type_written)]
+    pub was_written: Option<()>,
+    pub path: PathBuf,
 }
 
 // Copy of `AnnotationRequired` for E0283
@@ -65,6 +70,9 @@ pub struct AmbiguousImpl<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
+    #[note(infer_full_type_written)]
+    pub was_written: Option<()>,
+    pub path: PathBuf,
 }
 
 // Copy of `AnnotationRequired` for E0284
@@ -83,6 +91,9 @@ pub struct AmbiguousReturn<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
+    #[note(infer_full_type_written)]
+    pub was_written: Option<()>,
+    pub path: PathBuf,
 }
 
 // Used when a better one isn't available
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index f89ed256a08..3b5658ed0ee 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -18,13 +18,15 @@ use rustc_middle::infer::unify_key::{
 };
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
-use rustc_middle::ty::{self, InferConst};
-use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
-use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
+use rustc_middle::ty::{
+    self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Ty, TyCtxt,
+    TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
+};
 use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{BytePos, Span};
+use rustc_span::{BytePos, Span, DUMMY_SP};
 use std::borrow::Cow;
 use std::iter;
+use std::path::PathBuf;
 
 pub enum TypeAnnotationNeeded {
     /// ```compile_fail,E0282
@@ -153,6 +155,29 @@ impl UnderspecifiedArgKind {
     }
 }
 
+struct ClosureEraser<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'tcx> {
+    fn interner(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        match ty.kind() {
+            ty::Closure(_, args) => {
+                let closure_sig = args.as_closure().sig();
+                Ty::new_fn_ptr(
+                    self.tcx,
+                    self.tcx.signature_unclosure(closure_sig, hir::Unsafety::Normal),
+                )
+            }
+            _ => ty.super_fold_with(self),
+        }
+    }
+}
+
 fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
     let mut printer = FmtPrinter::new(infcx.tcx, ns);
     let ty_getter = move |ty_vid| {
@@ -209,6 +234,10 @@ fn ty_to_string<'tcx>(
 ) -> String {
     let mut printer = fmt_printer(infcx, Namespace::TypeNS);
     let ty = infcx.resolve_vars_if_possible(ty);
+    // We use `fn` ptr syntax for closures, but this only works when the closure
+    // does not capture anything.
+    let ty = ty.fold_with(&mut ClosureEraser { tcx: infcx.tcx });
+
     match (ty.kind(), called_method_def_id) {
         // We don't want the regular output for `fn`s because it includes its path in
         // invalid pseudo-syntax, we want the `fn`-pointer output instead.
@@ -223,11 +252,6 @@ fn ty_to_string<'tcx>(
             "Vec<_>".to_string()
         }
         _ if ty.is_ty_or_numeric_infer() => "/* Type */".to_string(),
-        // FIXME: The same thing for closures, but this only works when the closure
-        // does not capture anything.
-        //
-        // We do have to hide the `extern "rust-call"` ABI in that case though,
-        // which is too much of a bother for now.
         _ => {
             ty.print(&mut printer).unwrap();
             printer.into_buffer()
@@ -387,6 +411,8 @@ impl<'tcx> InferCtxt<'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
+                was_written: None,
+                path: Default::default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -396,6 +422,8 @@ impl<'tcx> InferCtxt<'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
+                was_written: None,
+                path: Default::default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
                 span,
@@ -405,6 +433,8 @@ impl<'tcx> InferCtxt<'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
+                was_written: None,
+                path: Default::default(),
             }),
         }
     }
@@ -442,7 +472,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             return self.bad_inference_failure_err(failure_span, arg_data, error_code);
         };
 
-        let (source_kind, name) = kind.ty_localized_msg(self);
+        let (source_kind, name, path) = kind.ty_localized_msg(self);
         let failure_span = if should_label_span && !failure_span.overlaps(span) {
             Some(failure_span)
         } else {
@@ -518,7 +548,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
                                 GenericArgKind::Type(_) => self
                                     .next_ty_var(TypeVariableOrigin {
-                                        span: rustc_span::DUMMY_SP,
+                                        span: DUMMY_SP,
                                         kind: TypeVariableOriginKind::MiscVariable,
                                     })
                                     .into(),
@@ -526,7 +556,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                     .next_const_var(
                                         arg.ty(),
                                         ConstVariableOrigin {
-                                            span: rustc_span::DUMMY_SP,
+                                            span: DUMMY_SP,
                                             kind: ConstVariableOriginKind::MiscVariable,
                                         },
                                     )
@@ -547,7 +577,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
             InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
                 let placeholder = Some(self.next_ty_var(TypeVariableOrigin {
-                    span: rustc_span::DUMMY_SP,
+                    span: DUMMY_SP,
                     kind: TypeVariableOriginKind::MiscVariable,
                 }));
                 if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) {
@@ -584,7 +614,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
             InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
                 let placeholder = Some(self.next_ty_var(TypeVariableOrigin {
-                    span: rustc_span::DUMMY_SP,
+                    span: DUMMY_SP,
                     kind: TypeVariableOriginKind::MiscVariable,
                 }));
                 if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) {
@@ -606,6 +636,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
+                was_written: path.as_ref().map(|_| ()),
+                path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -615,6 +647,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
+                was_written: path.as_ref().map(|_| ()),
+                path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
                 span,
@@ -624,6 +658,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
+                was_written: path.as_ref().map(|_| ()),
+                path: path.unwrap_or_default(),
             }),
         }
     }
@@ -688,22 +724,23 @@ impl<'tcx> InferSource<'tcx> {
 }
 
 impl<'tcx> InferSourceKind<'tcx> {
-    fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String) {
+    fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Option<PathBuf>) {
+        let mut path = None;
         match *self {
             InferSourceKind::LetBinding { ty, .. }
             | InferSourceKind::ClosureArg { ty, .. }
             | InferSourceKind::ClosureReturn { ty, .. } => {
                 if ty.is_closure() {
-                    ("closure", closure_as_fn_str(infcx, ty))
+                    ("closure", closure_as_fn_str(infcx, ty), path)
                 } else if !ty.is_ty_or_numeric_infer() {
-                    ("normal", ty_to_string(infcx, ty, None))
+                    ("normal", infcx.tcx.short_ty_string(ty, &mut path), path)
                 } else {
-                    ("other", String::new())
+                    ("other", String::new(), path)
                 }
             }
             // FIXME: We should be able to add some additional info here.
             InferSourceKind::GenericArg { .. }
-            | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new()),
+            | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new(), path),
         }
     }
 }
diff --git a/tests/ui/array-slice-vec/vector-no-ann.stderr b/tests/ui/array-slice-vec/vector-no-ann.stderr
index 24b6abfb342..716971eb120 100644
--- a/tests/ui/array-slice-vec/vector-no-ann.stderr
+++ b/tests/ui/array-slice-vec/vector-no-ann.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Vec<T>`
+error[E0282]: type annotations needed for `Vec<_>`
   --> $DIR/vector-no-ann.rs:2:9
    |
 LL |     let _foo = Vec::new();
diff --git a/tests/ui/const-generics/defaults/doesnt_infer.rs b/tests/ui/const-generics/defaults/doesnt_infer.rs
index 9c59e672d8e..e14c08fc148 100644
--- a/tests/ui/const-generics/defaults/doesnt_infer.rs
+++ b/tests/ui/const-generics/defaults/doesnt_infer.rs
@@ -9,5 +9,5 @@ impl<const N: u32> Foo<N> {
 fn main() {
     let foo = Foo::<1>::foo();
     let foo = Foo::foo();
-    //~^ error: type annotations needed for `Foo<N>`
+    //~^ ERROR type annotations needed for `Foo<_>`
 }
diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr
index 65ee0ecfdc5..93d58603397 100644
--- a/tests/ui/const-generics/defaults/doesnt_infer.stderr
+++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Foo<N>`
+error[E0282]: type annotations needed for `Foo<_>`
   --> $DIR/doesnt_infer.rs:11:9
    |
 LL |     let foo = Foo::foo();
diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
index 5b296a14869..5ee42c19dd3 100644
--- a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
+++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr
@@ -1,4 +1,4 @@
-error[E0283]: type annotations needed for `Mask<_, N>`
+error[E0283]: type annotations needed for `Mask<_, _>`
   --> $DIR/issue-91614.rs:6:9
    |
 LL |     let y = Mask::<_, _>::splat(false);
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr
index f27d52a1437..5cda4681b5c 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr
@@ -18,7 +18,7 @@ help: try adding a `where` bound
 LL |     pub const fn new() -> Self where [(); Self::SIZE]: {
    |                                +++++++++++++++++++++++
 
-error[E0282]: type annotations needed for `ArrayHolder<X>`
+error[E0282]: type annotations needed for `ArrayHolder<_>`
   --> $DIR/issue-62504.rs:26:9
    |
 LL |     let mut array = ArrayHolder::new();
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr
index 1664669eee0..beb159779ff 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr
@@ -22,7 +22,7 @@ note: tuple struct defined here
 LL | struct ArrayHolder<const X: usize>([u32; X]);
    |        ^^^^^^^^^^^
 
-error[E0282]: type annotations needed for `ArrayHolder<X>`
+error[E0282]: type annotations needed for `ArrayHolder<_>`
   --> $DIR/issue-62504.rs:26:9
    |
 LL |     let mut array = ArrayHolder::new();
diff --git a/tests/ui/generic-const-items/inference-failure.stderr b/tests/ui/generic-const-items/inference-failure.stderr
index 10ecd83ec53..594743a47f4 100644
--- a/tests/ui/generic-const-items/inference-failure.stderr
+++ b/tests/ui/generic-const-items/inference-failure.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Option<T>`
+error[E0282]: type annotations needed for `Option<_>`
   --> $DIR/inference-failure.rs:8:9
    |
 LL |     let _ = NONE;
diff --git a/tests/ui/generic-const-items/parameter-defaults.stderr b/tests/ui/generic-const-items/parameter-defaults.stderr
index b8220af5d0e..13562c98f6d 100644
--- a/tests/ui/generic-const-items/parameter-defaults.stderr
+++ b/tests/ui/generic-const-items/parameter-defaults.stderr
@@ -4,7 +4,7 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`
 LL | const NONE<T = ()>: Option<T> = None::<T>;
    |            ^^^^^^
 
-error[E0282]: type annotations needed for `Option<T>`
+error[E0282]: type annotations needed for `Option<_>`
   --> $DIR/parameter-defaults.rs:13:9
    |
 LL |     let _ = NONE;
diff --git a/tests/ui/inference/cannot-infer-closure-circular.rs b/tests/ui/inference/cannot-infer-closure-circular.rs
index affb481496d..1b41171e74a 100644
--- a/tests/ui/inference/cannot-infer-closure-circular.rs
+++ b/tests/ui/inference/cannot-infer-closure-circular.rs
@@ -4,7 +4,7 @@ fn main() {
     // error handles this gracefully, and in particular doesn't generate an extra
     // note about the `?` operator in the closure body, which isn't relevant to
     // the inference.
-    let x = |r| { //~ ERROR type annotations needed for `Result<(), E>`
+    let x = |r| { //~ ERROR type annotations needed for `Result<(), _>`
         let v = r?;
         Ok(v)
     };
diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr
index e3cf0cca837..a16e832f8ef 100644
--- a/tests/ui/inference/cannot-infer-closure-circular.stderr
+++ b/tests/ui/inference/cannot-infer-closure-circular.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Result<(), E>`
+error[E0282]: type annotations needed for `Result<(), _>`
   --> $DIR/cannot-infer-closure-circular.rs:7:14
    |
 LL |     let x = |r| {
diff --git a/tests/ui/inference/erase-type-params-in-label.stderr b/tests/ui/inference/erase-type-params-in-label.stderr
index 546e679f2d0..4e9a74c1e40 100644
--- a/tests/ui/inference/erase-type-params-in-label.stderr
+++ b/tests/ui/inference/erase-type-params-in-label.stderr
@@ -1,4 +1,4 @@
-error[E0283]: type annotations needed for `Foo<i32, &str, W, Z>`
+error[E0283]: type annotations needed for `Foo<i32, &str, _, _>`
   --> $DIR/erase-type-params-in-label.rs:2:9
    |
 LL |     let foo = foo(1, "");
@@ -15,7 +15,7 @@ help: consider giving `foo` an explicit type, where the type for type parameter
 LL |     let foo: Foo<i32, &str, W, Z> = foo(1, "");
    |            ++++++++++++++++++++++
 
-error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
+error[E0283]: type annotations needed for `Bar<i32, &str, _>`
   --> $DIR/erase-type-params-in-label.rs:5:9
    |
 LL |     let bar = bar(1, "");
diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr
index afece960914..391ed16f349 100644
--- a/tests/ui/inference/issue-104649.stderr
+++ b/tests/ui/inference/issue-104649.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `A<std::result::Result<std::result::Result<(), E>, Error>>`
+error[E0282]: type annotations needed for `A<std::result::Result<std::result::Result<(), _>, Error>>`
   --> $DIR/issue-104649.rs:24:9
    |
 LL |     let a = A(Result::Ok(Result::Ok(())));
diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr
index 6c93241ea07..6391672f861 100644
--- a/tests/ui/inference/issue-72690.stderr
+++ b/tests/ui/inference/issue-72690.stderr
@@ -50,7 +50,7 @@ help: try using a fully qualified path to specify the expected types
 LL |     |x| String::from(<str as AsRef<T>>::as_ref("x"));
    |                      ++++++++++++++++++++++++++   ~
 
-error[E0283]: type annotations needed for `&T`
+error[E0283]: type annotations needed for `&_`
   --> $DIR/issue-72690.rs:17:9
    |
 LL |     let _ = "x".as_ref();
diff --git a/tests/ui/inference/issue-83606.rs b/tests/ui/inference/issue-83606.rs
index c387046e910..4454b5e60f0 100644
--- a/tests/ui/inference/issue-83606.rs
+++ b/tests/ui/inference/issue-83606.rs
@@ -6,5 +6,5 @@ fn foo<const N: usize>(_: impl std::fmt::Display) -> [usize; N] {
 
 fn main() {
     let _ = foo("foo");
-    //~^ ERROR: type annotations needed for `[usize; N]`
+    //~^ ERROR type annotations needed for `[usize; _]`
 }
diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr
index 00de4029e42..8e6ff6d568d 100644
--- a/tests/ui/inference/issue-83606.stderr
+++ b/tests/ui/inference/issue-83606.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `[usize; N]`
+error[E0282]: type annotations needed for `[usize; _]`
   --> $DIR/issue-83606.rs:8:9
    |
 LL |     let _ = foo("foo");
diff --git a/tests/ui/issues/issue-12187-1.stderr b/tests/ui/issues/issue-12187-1.stderr
index 93dc1df8f63..704854fe585 100644
--- a/tests/ui/issues/issue-12187-1.stderr
+++ b/tests/ui/issues/issue-12187-1.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `&T`
+error[E0282]: type annotations needed for `&_`
   --> $DIR/issue-12187-1.rs:6:9
    |
 LL |     let &v = new();
diff --git a/tests/ui/issues/issue-12187-2.stderr b/tests/ui/issues/issue-12187-2.stderr
index e9ba52ff4fd..eeef63a1d0b 100644
--- a/tests/ui/issues/issue-12187-2.stderr
+++ b/tests/ui/issues/issue-12187-2.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `&T`
+error[E0282]: type annotations needed for `&_`
   --> $DIR/issue-12187-2.rs:6:9
    |
 LL |     let &v = new();
diff --git a/tests/ui/issues/issue-17551.stderr b/tests/ui/issues/issue-17551.stderr
index 68f54a31084..b9cb76fc298 100644
--- a/tests/ui/issues/issue-17551.stderr
+++ b/tests/ui/issues/issue-17551.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `B<T>`
+error[E0282]: type annotations needed for `B<_>`
   --> $DIR/issue-17551.rs:6:9
    |
 LL |     let foo = B(marker::PhantomData);
diff --git a/tests/ui/issues/issue-23046.stderr b/tests/ui/issues/issue-23046.stderr
index b6e23814543..f70ac0c9f38 100644
--- a/tests/ui/issues/issue-23046.stderr
+++ b/tests/ui/issues/issue-23046.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Expr<'_, VAR>`
+error[E0282]: type annotations needed for `Expr<'_, _>`
   --> $DIR/issue-23046.rs:17:15
    |
 LL |     let ex = |x| {
diff --git a/tests/ui/issues/issue-98299.stderr b/tests/ui/issues/issue-98299.stderr
index e99d8e5cc80..becf16d1db9 100644
--- a/tests/ui/issues/issue-98299.stderr
+++ b/tests/ui/issues/issue-98299.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `SmallCString<N>`
+error[E0282]: type annotations needed for `SmallCString<_>`
   --> $DIR/issue-98299.rs:4:36
    |
 LL |     SmallCString::try_from(p).map(|cstr| cstr);
diff --git a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
index 0a022dc3984..b2d2d039ff6 100644
--- a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
+++ b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Vec<T>`
+error[E0282]: type annotations needed for `Vec<_>`
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:9
    |
 LL |     let mut x = Vec::new();
diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs
index af25010e3bd..0ffa8249789 100644
--- a/tests/ui/traits/copy-guessing.rs
+++ b/tests/ui/traits/copy-guessing.rs
@@ -18,7 +18,7 @@ fn assert_impls_fn<R,T: Fn()->R>(_: &T){}
 
 fn main() {
     let n = None;
-    //~^ ERROR type annotations needed for `Option<T>`
+    //~^ ERROR type annotations needed for `Option<_>`
     let e = S(&n);
     let f = || {
         // S being copy is critical for this to work
diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr
index 750140c017c..cae91579ee0 100644
--- a/tests/ui/traits/copy-guessing.stderr
+++ b/tests/ui/traits/copy-guessing.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Option<T>`
+error[E0282]: type annotations needed for `Option<_>`
   --> $DIR/copy-guessing.rs:20:9
    |
 LL |     let n = None;
diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr
index 5be8d2f4b32..0f4b3c3c877 100644
--- a/tests/ui/traits/issue-77982.stderr
+++ b/tests/ui/traits/issue-77982.stderr
@@ -55,7 +55,7 @@ help: try using a fully qualified path to specify the expected types
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();
    |                                                      +++++++++++++++++++++++    ~
 
-error[E0283]: type annotations needed for `Box<T>`
+error[E0283]: type annotations needed for `Box<_>`
   --> $DIR/issue-77982.rs:37:9
    |
 LL |     let _ = ().foo();
@@ -73,7 +73,7 @@ help: consider giving this pattern a type, where the type for type parameter `T`
 LL |     let _: Box<T> = ().foo();
    |          ++++++++
 
-error[E0283]: type annotations needed for `Box<T>`
+error[E0283]: type annotations needed for `Box<_>`
   --> $DIR/issue-77982.rs:41:9
    |
 LL |     let _ = (&()).bar();
diff --git a/tests/ui/type-inference/or_else-multiple-type-params.stderr b/tests/ui/type-inference/or_else-multiple-type-params.stderr
index d1bbe308ed3..3176a2d490e 100644
--- a/tests/ui/type-inference/or_else-multiple-type-params.stderr
+++ b/tests/ui/type-inference/or_else-multiple-type-params.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Result<Child, F>`
+error[E0282]: type annotations needed for `Result<Child, _>`
   --> $DIR/or_else-multiple-type-params.rs:7:18
    |
 LL |         .or_else(|err| {
diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
index 5a76ef3e875..058dbb1e220 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed for `Option<T>`
+error[E0282]: type annotations needed for `Option<_>`
   --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:8:9
    |
 LL |     let mut closure0 = None;