Skip to content

Commit 9d5e7d3

Browse files
committed
Suggest collecting into Vec<_>
1 parent ed620cf commit 9d5e7d3

File tree

20 files changed

+49
-31
lines changed

20 files changed

+49
-31
lines changed

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
2020
use rustc_middle::ty::{self, DefIdTree, InferConst};
2121
use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
2222
use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
23-
use rustc_span::symbol::{kw, Ident};
23+
use rustc_span::symbol::{kw, sym, Ident};
2424
use rustc_span::{BytePos, Span};
2525
use std::borrow::Cow;
2626
use std::iter;
@@ -78,12 +78,12 @@ impl InferenceDiagnosticsData {
7878
}
7979

8080
fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
81-
if in_type.is_ty_infer() {
82-
"empty"
83-
} else if self.name == "_" {
81+
if self.name == "_" {
8482
// FIXME: Consider specializing this message if there is a single `_`
8583
// in the type.
8684
"underscore"
85+
} else if in_type.is_ty_infer() {
86+
"empty"
8787
} else {
8888
"has_name"
8989
}
@@ -368,6 +368,7 @@ impl<'tcx> InferCtxt<'tcx> {
368368
}
369369

370370
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
371+
#[instrument(level = "debug", skip(self, error_code))]
371372
pub fn emit_inference_failure_err(
372373
&self,
373374
body_id: Option<hir::BodyId>,
@@ -406,16 +407,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
406407
let mut infer_subdiags = Vec::new();
407408
let mut multi_suggestions = Vec::new();
408409
match kind {
409-
InferSourceKind::LetBinding { insert_span, pattern_name, ty } => {
410+
InferSourceKind::LetBinding { insert_span, pattern_name, ty, is_collect } => {
410411
infer_subdiags.push(SourceKindSubdiag::LetLike {
411412
span: insert_span,
412413
name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
413-
x_kind: arg_data.where_x_is_kind(ty),
414+
x_kind: if is_collect { "empty" } else { arg_data.where_x_is_kind(ty) },
414415
prefix_kind: arg_data.kind.clone(),
415416
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
416417
arg_name: arg_data.name,
417418
kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
418-
type_name: ty_to_string(self, ty),
419+
type_name: if is_collect {
420+
"Vec<_>".to_string()
421+
} else {
422+
ty_to_string(self, ty)
423+
},
419424
});
420425
}
421426
InferSourceKind::ClosureArg { insert_span, ty } => {
@@ -608,6 +613,7 @@ enum InferSourceKind<'tcx> {
608613
insert_span: Span,
609614
pattern_name: Option<Ident>,
610615
ty: Ty<'tcx>,
616+
is_collect: bool,
611617
},
612618
ClosureArg {
613619
insert_span: Span,
@@ -788,10 +794,19 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
788794
/// Uses `fn source_cost` to determine whether this inference source is preferable to
789795
/// previous sources. We generally prefer earlier sources.
790796
#[instrument(level = "debug", skip(self))]
791-
fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
797+
fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
792798
let cost = self.source_cost(&new_source) + self.attempt;
793799
debug!(?cost);
794800
self.attempt += 1;
801+
if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id, ..}, .. }) = self.infer_source
802+
&& self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id)
803+
&& let InferSourceKind::LetBinding { ref ty, ref mut is_collect, ..} = new_source.kind
804+
&& ty.is_ty_infer()
805+
{
806+
// Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
807+
// `let x: _ = iter.collect();`, as this is a very common case.
808+
*is_collect = true;
809+
}
795810
if cost < self.infer_source_cost {
796811
self.infer_source_cost = cost;
797812
self.infer_source = Some(new_source);
@@ -1089,6 +1104,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
10891104
insert_span: local.pat.span.shrink_to_hi(),
10901105
pattern_name: local.pat.simple_ident(),
10911106
ty,
1107+
is_collect: false,
10921108
},
10931109
})
10941110
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,7 @@ symbols! {
827827
item_like_imports,
828828
iter,
829829
iter_repeat,
830+
iterator_collect_fn,
830831
kcfi,
831832
keyword,
832833
kind,

library/core/src/iter/traits/iterator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,6 +1829,7 @@ pub trait Iterator {
18291829
#[inline]
18301830
#[stable(feature = "rust1", since = "1.0.0")]
18311831
#[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"]
1832+
#[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")]
18321833
fn collect<B: FromIterator<Self::Item>>(self) -> B
18331834
where
18341835
Self: Sized,

src/test/ui/array-slice-vec/infer_array_len.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
44
LL | let [_, _] = a.into();
55
| ^^^^^^
66
|
7-
help: consider giving this pattern a type
7+
help: consider giving this pattern a type, where the placeholders `_` are specified
88
|
99
LL | let [_, _]: _ = a.into();
1010
| +++

src/test/ui/closures/issue-52437.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ error[E0282]: type annotations needed
1010
LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
1111
| ^
1212
|
13-
help: consider giving this closure parameter an explicit type
13+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
1414
|
1515
LL | [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
1616
| +++

src/test/ui/error-codes/E0282.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ LL | let x = "hello".chars().rev().collect();
66
|
77
help: consider giving `x` an explicit type
88
|
9-
LL | let x: _ = "hello".chars().rev().collect();
10-
| +++
9+
LL | let x: Vec<_> = "hello".chars().rev().collect();
10+
| ++++++++
1111

1212
error: aborting due to previous error
1313

src/test/ui/impl-trait/issues/issue-86719.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ error[E0282]: type annotations needed
1818
LL | |_| true
1919
| ^
2020
|
21-
help: consider giving this closure parameter an explicit type
21+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
2222
|
2323
LL | |_: _| true
2424
| +++

src/test/ui/inference/issue-72690.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ error[E0282]: type annotations needed
3030
LL | |x| String::from("x".as_ref());
3131
| ^
3232
|
33-
help: consider giving this closure parameter an explicit type
33+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
3434
|
3535
LL | |x: _| String::from("x".as_ref());
3636
| +++

src/test/ui/issues/issue-18159.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
44
LL | let x;
55
| ^
66
|
7-
help: consider giving `x` an explicit type
7+
help: consider giving `x` an explicit type, where the placeholders `_` are specified
88
|
99
LL | let x: _;
1010
| +++

src/test/ui/issues/issue-2151.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | let x = panic!();
66
LL | x.clone();
77
| - type must be known at this point
88
|
9-
help: consider giving `x` an explicit type
9+
help: consider giving `x` an explicit type, where the placeholders `_` are specified
1010
|
1111
LL | let x: _ = panic!();
1212
| +++

src/test/ui/issues/issue-24036.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ error[E0282]: type annotations needed
1717
LL | 1 => |c| c + 1,
1818
| ^
1919
|
20-
help: consider giving this closure parameter an explicit type
20+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
2121
|
2222
LL | 1 => |c: _| c + 1,
2323
| +++

src/test/ui/lazy-type-alias-impl-trait/branches3.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
44
LL | |s| s.len()
55
| ^ - type must be known at this point
66
|
7-
help: consider giving this closure parameter an explicit type
7+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
88
|
99
LL | |s: _| s.len()
1010
| +++
@@ -15,7 +15,7 @@ error[E0282]: type annotations needed
1515
LL | |s| s.len()
1616
| ^ - type must be known at this point
1717
|
18-
help: consider giving this closure parameter an explicit type
18+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
1919
|
2020
LL | |s: _| s.len()
2121
| +++
@@ -26,7 +26,7 @@ error[E0282]: type annotations needed
2626
LL | |s| s.len()
2727
| ^ - type must be known at this point
2828
|
29-
help: consider giving this closure parameter an explicit type
29+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
3030
|
3131
LL | |s: _| s.len()
3232
| +++
@@ -37,7 +37,7 @@ error[E0282]: type annotations needed
3737
LL | |s| s.len()
3838
| ^ - type must be known at this point
3939
|
40-
help: consider giving this closure parameter an explicit type
40+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
4141
|
4242
LL | |s: _| s.len()
4343
| +++

src/test/ui/match/match-unresolved-one-arm.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
44
LL | let x = match () {
55
| ^
66
|
7-
help: consider giving `x` an explicit type
7+
help: consider giving `x` an explicit type, where the placeholders `_` are specified
88
|
99
LL | let x: _ = match () {
1010
| +++

src/test/ui/pattern/pat-tuple-bad-type.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | let x;
77
LL | (..) => {}
88
| ---- type must be known at this point
99
|
10-
help: consider giving `x` an explicit type
10+
help: consider giving `x` an explicit type, where the placeholders `_` are specified
1111
|
1212
LL | let x: _;
1313
| +++

src/test/ui/pattern/rest-pat-semantic-disallowed.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ error[E0282]: type annotations needed
191191
LL | let x @ ..;
192192
| ^^^^^^
193193
|
194-
help: consider giving this pattern a type
194+
help: consider giving this pattern a type, where the placeholders `_` are specified
195195
|
196196
LL | let x @ ..: _;
197197
| +++

src/test/ui/resolve/issue-85348.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ error[E0282]: type annotations needed
1919
LL | let mut N;
2020
| ^^^^^
2121
|
22-
help: consider giving `N` an explicit type
22+
help: consider giving `N` an explicit type, where the placeholders `_` are specified
2323
|
2424
LL | let mut N: _;
2525
| +++

src/test/ui/span/method-and-field-eager-resolution.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL |
77
LL | x.0;
88
| - type must be known at this point
99
|
10-
help: consider giving `x` an explicit type
10+
help: consider giving `x` an explicit type, where the placeholders `_` are specified
1111
|
1212
LL | let mut x: _ = Default::default();
1313
| +++
@@ -21,7 +21,7 @@ LL |
2121
LL | x[0];
2222
| - type must be known at this point
2323
|
24-
help: consider giving `x` an explicit type
24+
help: consider giving `x` an explicit type, where the placeholders `_` are specified
2525
|
2626
LL | let mut x: _ = Default::default();
2727
| +++

src/test/ui/type-alias-impl-trait/closures_in_branches.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed
44
LL | |x| x.len()
55
| ^ - type must be known at this point
66
|
7-
help: consider giving this closure parameter an explicit type
7+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
88
|
99
LL | |x: _| x.len()
1010
| +++
@@ -15,7 +15,7 @@ error[E0282]: type annotations needed
1515
LL | |x| x.len()
1616
| ^ - type must be known at this point
1717
|
18-
help: consider giving this closure parameter an explicit type
18+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
1919
|
2020
LL | |x: _| x.len()
2121
| +++

src/test/ui/type/type-check/unknown_type_for_closure.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ error[E0282]: type annotations needed
1010
LL | let x = |_| {};
1111
| ^
1212
|
13-
help: consider giving this closure parameter an explicit type
13+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
1414
|
1515
LL | let x = |_: _| {};
1616
| +++

src/test/ui/type/type-path-err-node-types.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ error[E0282]: type annotations needed
2828
LL | let _ = |a, b: _| -> _ { 0 };
2929
| ^
3030
|
31-
help: consider giving this closure parameter an explicit type
31+
help: consider giving this closure parameter an explicit type, where the placeholders `_` are specified
3232
|
3333
LL | let _ = |a: _, b: _| -> _ { 0 };
3434
| +++

0 commit comments

Comments
 (0)