about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2022-12-09 22:31:16 -0800
committerEsteban Küber <esteban@kuber.com.ar>2022-12-13 10:39:44 -0800
commit9d5e7d3c042f73153cf8f009400569ff9e8e12a8 (patch)
tree60cb2e64d7fed9fbd7ec72bfdd265579285cdd4c
parented620cf9690fdafed65845bf35c455db992fbba1 (diff)
downloadrust-9d5e7d3c042f73153cf8f009400569ff9e8e12a8.tar.gz
rust-9d5e7d3c042f73153cf8f009400569ff9e8e12a8.zip
Suggest `collect`ing into `Vec<_>`
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs32
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/core/src/iter/traits/iterator.rs1
-rw-r--r--src/test/ui/array-slice-vec/infer_array_len.stderr2
-rw-r--r--src/test/ui/closures/issue-52437.stderr2
-rw-r--r--src/test/ui/error-codes/E0282.stderr4
-rw-r--r--src/test/ui/impl-trait/issues/issue-86719.stderr2
-rw-r--r--src/test/ui/inference/issue-72690.stderr2
-rw-r--r--src/test/ui/issues/issue-18159.stderr2
-rw-r--r--src/test/ui/issues/issue-2151.stderr2
-rw-r--r--src/test/ui/issues/issue-24036.stderr2
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/branches3.stderr8
-rw-r--r--src/test/ui/match/match-unresolved-one-arm.stderr2
-rw-r--r--src/test/ui/pattern/pat-tuple-bad-type.stderr2
-rw-r--r--src/test/ui/pattern/rest-pat-semantic-disallowed.stderr2
-rw-r--r--src/test/ui/resolve/issue-85348.stderr2
-rw-r--r--src/test/ui/span/method-and-field-eager-resolution.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/closures_in_branches.stderr4
-rw-r--r--src/test/ui/type/type-check/unknown_type_for_closure.stderr2
-rw-r--r--src/test/ui/type/type-path-err-node-types.stderr2
20 files changed, 49 insertions, 31 deletions
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 8ff1639a3a2..b55cb091b1f 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
@@ -20,7 +20,7 @@ use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
 use rustc_middle::ty::{self, DefIdTree, InferConst};
 use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span};
 use std::borrow::Cow;
 use std::iter;
@@ -78,12 +78,12 @@ impl InferenceDiagnosticsData {
     }
 
     fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
-        if in_type.is_ty_infer() {
-            "empty"
-        } else if self.name == "_" {
+        if self.name == "_" {
             // FIXME: Consider specializing this message if there is a single `_`
             // in the type.
             "underscore"
+        } else if in_type.is_ty_infer() {
+            "empty"
         } else {
             "has_name"
         }
@@ -368,6 +368,7 @@ impl<'tcx> InferCtxt<'tcx> {
 }
 
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    #[instrument(level = "debug", skip(self, error_code))]
     pub fn emit_inference_failure_err(
         &self,
         body_id: Option<hir::BodyId>,
@@ -406,16 +407,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         let mut infer_subdiags = Vec::new();
         let mut multi_suggestions = Vec::new();
         match kind {
-            InferSourceKind::LetBinding { insert_span, pattern_name, ty } => {
+            InferSourceKind::LetBinding { insert_span, pattern_name, ty, is_collect } => {
                 infer_subdiags.push(SourceKindSubdiag::LetLike {
                     span: insert_span,
                     name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
-                    x_kind: arg_data.where_x_is_kind(ty),
+                    x_kind: if is_collect { "empty" } else { arg_data.where_x_is_kind(ty) },
                     prefix_kind: arg_data.kind.clone(),
                     prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                     arg_name: arg_data.name,
                     kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
-                    type_name: ty_to_string(self, ty),
+                    type_name: if is_collect {
+                        "Vec<_>".to_string()
+                    } else {
+                        ty_to_string(self, ty)
+                    },
                 });
             }
             InferSourceKind::ClosureArg { insert_span, ty } => {
@@ -608,6 +613,7 @@ enum InferSourceKind<'tcx> {
         insert_span: Span,
         pattern_name: Option<Ident>,
         ty: Ty<'tcx>,
+        is_collect: bool,
     },
     ClosureArg {
         insert_span: Span,
@@ -788,10 +794,19 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
     /// Uses `fn source_cost` to determine whether this inference source is preferable to
     /// previous sources. We generally prefer earlier sources.
     #[instrument(level = "debug", skip(self))]
-    fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
+    fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
         let cost = self.source_cost(&new_source) + self.attempt;
         debug!(?cost);
         self.attempt += 1;
+        if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id, ..}, .. }) = self.infer_source
+            && self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id)
+            && let InferSourceKind::LetBinding { ref ty, ref mut is_collect, ..} = new_source.kind
+            && ty.is_ty_infer()
+        {
+            // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
+            // `let x: _ = iter.collect();`, as this is a very common case.
+            *is_collect = true;
+        }
         if cost < self.infer_source_cost {
             self.infer_source_cost = cost;
             self.infer_source = Some(new_source);
@@ -1089,6 +1104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
                                 insert_span: local.pat.span.shrink_to_hi(),
                                 pattern_name: local.pat.simple_ident(),
                                 ty,
+                                is_collect: false,
                             },
                         })
                     }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 85d416c43f9..ace095736c9 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -827,6 +827,7 @@ symbols! {
         item_like_imports,
         iter,
         iter_repeat,
+        iterator_collect_fn,
         kcfi,
         keyword,
         kind,
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 83c7e8977e9..1cdee992137 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1829,6 +1829,7 @@ pub trait Iterator {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")]
     fn collect<B: FromIterator<Self::Item>>(self) -> B
     where
         Self: Sized,
diff --git a/src/test/ui/array-slice-vec/infer_array_len.stderr b/src/test/ui/array-slice-vec/infer_array_len.stderr
index 919550cac30..bd757be126c 100644
--- a/src/test/ui/array-slice-vec/infer_array_len.stderr
+++ b/src/test/ui/array-slice-vec/infer_array_len.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     let [_, _] = a.into();
    |         ^^^^^^
    |
-help: consider giving this pattern a type
+help: consider giving this pattern a type, where the placeholders `_` are specified
    |
 LL |     let [_, _]: _ = a.into();
    |               +++
diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr
index 4c24a54bbbe..f7d34890a79 100644
--- a/src/test/ui/closures/issue-52437.stderr
+++ b/src/test/ui/closures/issue-52437.stderr
@@ -10,7 +10,7 @@ error[E0282]: type annotations needed
 LL |     [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
    |                              ^
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |     [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
    |                               +++
diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr
index d01aa3617c7..892d3a81f27 100644
--- a/src/test/ui/error-codes/E0282.stderr
+++ b/src/test/ui/error-codes/E0282.stderr
@@ -6,8 +6,8 @@ LL |     let x = "hello".chars().rev().collect();
    |
 help: consider giving `x` an explicit type
    |
-LL |     let x: _ = "hello".chars().rev().collect();
-   |          +++
+LL |     let x: Vec<_> = "hello".chars().rev().collect();
+   |          ++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issues/issue-86719.stderr b/src/test/ui/impl-trait/issues/issue-86719.stderr
index 09047cdcbe1..da184c26bfe 100644
--- a/src/test/ui/impl-trait/issues/issue-86719.stderr
+++ b/src/test/ui/impl-trait/issues/issue-86719.stderr
@@ -18,7 +18,7 @@ error[E0282]: type annotations needed
 LL |         |_| true
    |          ^
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |         |_: _| true
    |           +++
diff --git a/src/test/ui/inference/issue-72690.stderr b/src/test/ui/inference/issue-72690.stderr
index d4eeda07366..e59bcea9512 100644
--- a/src/test/ui/inference/issue-72690.stderr
+++ b/src/test/ui/inference/issue-72690.stderr
@@ -30,7 +30,7 @@ error[E0282]: type annotations needed
 LL |     |x| String::from("x".as_ref());
    |      ^
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |     |x: _| String::from("x".as_ref());
    |       +++
diff --git a/src/test/ui/issues/issue-18159.stderr b/src/test/ui/issues/issue-18159.stderr
index 605ff3829d1..bedfeda2ea0 100644
--- a/src/test/ui/issues/issue-18159.stderr
+++ b/src/test/ui/issues/issue-18159.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     let x;
    |         ^
    |
-help: consider giving `x` an explicit type
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
    |
 LL |     let x: _;
    |          +++
diff --git a/src/test/ui/issues/issue-2151.stderr b/src/test/ui/issues/issue-2151.stderr
index 31a8ca5fbfa..411fdc48344 100644
--- a/src/test/ui/issues/issue-2151.stderr
+++ b/src/test/ui/issues/issue-2151.stderr
@@ -6,7 +6,7 @@ LL |     let x = panic!();
 LL |     x.clone();
    |     - type must be known at this point
    |
-help: consider giving `x` an explicit type
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
    |
 LL |     let x: _ = panic!();
    |          +++
diff --git a/src/test/ui/issues/issue-24036.stderr b/src/test/ui/issues/issue-24036.stderr
index a42e35c4cad..fcfce56bcb1 100644
--- a/src/test/ui/issues/issue-24036.stderr
+++ b/src/test/ui/issues/issue-24036.stderr
@@ -17,7 +17,7 @@ error[E0282]: type annotations needed
 LL |         1 => |c| c + 1,
    |               ^
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |         1 => |c: _| c + 1,
    |                +++
diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr
index 420104e526d..9d56d96c8c1 100644
--- a/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr
+++ b/src/test/ui/lazy-type-alias-impl-trait/branches3.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |         |s| s.len()
    |          ^  - type must be known at this point
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |         |s: _| s.len()
    |           +++
@@ -15,7 +15,7 @@ error[E0282]: type annotations needed
 LL |         |s| s.len()
    |          ^  - type must be known at this point
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |         |s: _| s.len()
    |           +++
@@ -26,7 +26,7 @@ error[E0282]: type annotations needed
 LL |         |s| s.len()
    |          ^  - type must be known at this point
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |         |s: _| s.len()
    |           +++
@@ -37,7 +37,7 @@ error[E0282]: type annotations needed
 LL |         |s| s.len()
    |          ^  - type must be known at this point
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |         |s: _| s.len()
    |           +++
diff --git a/src/test/ui/match/match-unresolved-one-arm.stderr b/src/test/ui/match/match-unresolved-one-arm.stderr
index 9eadb88a8ba..db5db38391e 100644
--- a/src/test/ui/match/match-unresolved-one-arm.stderr
+++ b/src/test/ui/match/match-unresolved-one-arm.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |     let x = match () {
    |         ^
    |
-help: consider giving `x` an explicit type
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
    |
 LL |     let x: _ = match () {
    |          +++
diff --git a/src/test/ui/pattern/pat-tuple-bad-type.stderr b/src/test/ui/pattern/pat-tuple-bad-type.stderr
index 3342b8e4002..86fd1e0c196 100644
--- a/src/test/ui/pattern/pat-tuple-bad-type.stderr
+++ b/src/test/ui/pattern/pat-tuple-bad-type.stderr
@@ -7,7 +7,7 @@ LL |     let x;
 LL |         (..) => {}
    |         ---- type must be known at this point
    |
-help: consider giving `x` an explicit type
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
    |
 LL |     let x: _;
    |          +++
diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
index e6a4e5f19b7..5bf168a5711 100644
--- a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
+++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr
@@ -191,7 +191,7 @@ error[E0282]: type annotations needed
 LL |     let x @ ..;
    |         ^^^^^^
    |
-help: consider giving this pattern a type
+help: consider giving this pattern a type, where the placeholders `_` are specified
    |
 LL |     let x @ ..: _;
    |               +++
diff --git a/src/test/ui/resolve/issue-85348.stderr b/src/test/ui/resolve/issue-85348.stderr
index f839dd927db..cc9cd3fe68b 100644
--- a/src/test/ui/resolve/issue-85348.stderr
+++ b/src/test/ui/resolve/issue-85348.stderr
@@ -19,7 +19,7 @@ error[E0282]: type annotations needed
 LL |         let mut N;
    |             ^^^^^
    |
-help: consider giving `N` an explicit type
+help: consider giving `N` an explicit type, where the placeholders `_` are specified
    |
 LL |         let mut N: _;
    |                  +++
diff --git a/src/test/ui/span/method-and-field-eager-resolution.stderr b/src/test/ui/span/method-and-field-eager-resolution.stderr
index 7d240589a3f..85205464626 100644
--- a/src/test/ui/span/method-and-field-eager-resolution.stderr
+++ b/src/test/ui/span/method-and-field-eager-resolution.stderr
@@ -7,7 +7,7 @@ LL |
 LL |     x.0;
    |     - type must be known at this point
    |
-help: consider giving `x` an explicit type
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
    |
 LL |     let mut x: _ = Default::default();
    |              +++
@@ -21,7 +21,7 @@ LL |
 LL |     x[0];
    |     - type must be known at this point
    |
-help: consider giving `x` an explicit type
+help: consider giving `x` an explicit type, where the placeholders `_` are specified
    |
 LL |     let mut x: _ = Default::default();
    |              +++
diff --git a/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
index 48b7946ea82..6f8b5cc4cc5 100644
--- a/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
+++ b/src/test/ui/type-alias-impl-trait/closures_in_branches.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
 LL |         |x| x.len()
    |          ^  - type must be known at this point
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |         |x: _| x.len()
    |           +++
@@ -15,7 +15,7 @@ error[E0282]: type annotations needed
 LL |         |x| x.len()
    |          ^  - type must be known at this point
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |         |x: _| x.len()
    |           +++
diff --git a/src/test/ui/type/type-check/unknown_type_for_closure.stderr b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
index 9ae97f390d3..2ba5f07a8f4 100644
--- a/src/test/ui/type/type-check/unknown_type_for_closure.stderr
+++ b/src/test/ui/type/type-check/unknown_type_for_closure.stderr
@@ -10,7 +10,7 @@ error[E0282]: type annotations needed
 LL |     let x = |_| {};
    |              ^
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |     let x = |_: _| {};
    |               +++
diff --git a/src/test/ui/type/type-path-err-node-types.stderr b/src/test/ui/type/type-path-err-node-types.stderr
index c1ae10efac4..24cc4a2a761 100644
--- a/src/test/ui/type/type-path-err-node-types.stderr
+++ b/src/test/ui/type/type-path-err-node-types.stderr
@@ -28,7 +28,7 @@ error[E0282]: type annotations needed
 LL |     let _ = |a, b: _| -> _ { 0 };
    |              ^
    |
-help: consider giving this closure parameter an explicit type
+help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
    |
 LL |     let _ = |a: _, b: _| -> _ { 0 };
    |               +++