1
Fork 0

Suggest collecting into Vec<_>

This commit is contained in:
Esteban Küber 2022-12-09 22:31:16 -08:00
parent ed620cf969
commit 9d5e7d3c04
20 changed files with 49 additions and 31 deletions

View file

@ -20,7 +20,7 @@ use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
use rustc_middle::ty::{self, DefIdTree, InferConst}; use rustc_middle::ty::{self, DefIdTree, InferConst};
use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults}; 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 rustc_span::{BytePos, Span};
use std::borrow::Cow; use std::borrow::Cow;
use std::iter; use std::iter;
@ -78,12 +78,12 @@ impl InferenceDiagnosticsData {
} }
fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str { fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
if in_type.is_ty_infer() { if self.name == "_" {
"empty"
} else if self.name == "_" {
// FIXME: Consider specializing this message if there is a single `_` // FIXME: Consider specializing this message if there is a single `_`
// in the type. // in the type.
"underscore" "underscore"
} else if in_type.is_ty_infer() {
"empty"
} else { } else {
"has_name" "has_name"
} }
@ -368,6 +368,7 @@ impl<'tcx> InferCtxt<'tcx> {
} }
impl<'tcx> TypeErrCtxt<'_, 'tcx> { impl<'tcx> TypeErrCtxt<'_, 'tcx> {
#[instrument(level = "debug", skip(self, error_code))]
pub fn emit_inference_failure_err( pub fn emit_inference_failure_err(
&self, &self,
body_id: Option<hir::BodyId>, body_id: Option<hir::BodyId>,
@ -406,16 +407,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let mut infer_subdiags = Vec::new(); let mut infer_subdiags = Vec::new();
let mut multi_suggestions = Vec::new(); let mut multi_suggestions = Vec::new();
match kind { match kind {
InferSourceKind::LetBinding { insert_span, pattern_name, ty } => { InferSourceKind::LetBinding { insert_span, pattern_name, ty, is_collect } => {
infer_subdiags.push(SourceKindSubdiag::LetLike { infer_subdiags.push(SourceKindSubdiag::LetLike {
span: insert_span, span: insert_span,
name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new), 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_kind: arg_data.kind.clone(),
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(), prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
arg_name: arg_data.name, arg_name: arg_data.name,
kind: if pattern_name.is_some() { "with_pattern" } else { "other" }, 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 } => { InferSourceKind::ClosureArg { insert_span, ty } => {
@ -608,6 +613,7 @@ enum InferSourceKind<'tcx> {
insert_span: Span, insert_span: Span,
pattern_name: Option<Ident>, pattern_name: Option<Ident>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
is_collect: bool,
}, },
ClosureArg { ClosureArg {
insert_span: Span, 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 /// Uses `fn source_cost` to determine whether this inference source is preferable to
/// previous sources. We generally prefer earlier sources. /// previous sources. We generally prefer earlier sources.
#[instrument(level = "debug", skip(self))] #[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; let cost = self.source_cost(&new_source) + self.attempt;
debug!(?cost); debug!(?cost);
self.attempt += 1; 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 { if cost < self.infer_source_cost {
self.infer_source_cost = cost; self.infer_source_cost = cost;
self.infer_source = Some(new_source); 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(), insert_span: local.pat.span.shrink_to_hi(),
pattern_name: local.pat.simple_ident(), pattern_name: local.pat.simple_ident(),
ty, ty,
is_collect: false,
}, },
}) })
} }

View file

@ -827,6 +827,7 @@ symbols! {
item_like_imports, item_like_imports,
iter, iter,
iter_repeat, iter_repeat,
iterator_collect_fn,
kcfi, kcfi,
keyword, keyword,
kind, kind,

View file

@ -1829,6 +1829,7 @@ pub trait Iterator {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] #[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 fn collect<B: FromIterator<Self::Item>>(self) -> B
where where
Self: Sized, Self: Sized,

View file

@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | let [_, _] = a.into(); 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(); LL | let [_, _]: _ = a.into();
| +++ | +++

View file

@ -10,7 +10,7 @@ error[E0282]: type annotations needed
LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] 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] LL | [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize]
| +++ | +++

View file

@ -6,8 +6,8 @@ LL | let x = "hello".chars().rev().collect();
| |
help: consider giving `x` an explicit type 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 error: aborting due to previous error

View file

@ -18,7 +18,7 @@ error[E0282]: type annotations needed
LL | |_| true 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 LL | |_: _| true
| +++ | +++

View file

@ -30,7 +30,7 @@ error[E0282]: type annotations needed
LL | |x| String::from("x".as_ref()); 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()); LL | |x: _| String::from("x".as_ref());
| +++ | +++

View file

@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | let x; 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: _; LL | let x: _;
| +++ | +++

View file

@ -6,7 +6,7 @@ LL | let x = panic!();
LL | x.clone(); LL | x.clone();
| - type must be known at this point | - 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!(); LL | let x: _ = panic!();
| +++ | +++

View file

@ -17,7 +17,7 @@ error[E0282]: type annotations needed
LL | 1 => |c| c + 1, 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, LL | 1 => |c: _| c + 1,
| +++ | +++

View file

@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | |s| s.len() LL | |s| s.len()
| ^ - type must be known at this point | ^ - 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() LL | |s: _| s.len()
| +++ | +++
@ -15,7 +15,7 @@ error[E0282]: type annotations needed
LL | |s| s.len() LL | |s| s.len()
| ^ - type must be known at this point | ^ - 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() LL | |s: _| s.len()
| +++ | +++
@ -26,7 +26,7 @@ error[E0282]: type annotations needed
LL | |s| s.len() LL | |s| s.len()
| ^ - type must be known at this point | ^ - 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() LL | |s: _| s.len()
| +++ | +++
@ -37,7 +37,7 @@ error[E0282]: type annotations needed
LL | |s| s.len() LL | |s| s.len()
| ^ - type must be known at this point | ^ - 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() LL | |s: _| s.len()
| +++ | +++

View file

@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | let x = match () { 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 () { LL | let x: _ = match () {
| +++ | +++

View file

@ -7,7 +7,7 @@ LL | let x;
LL | (..) => {} LL | (..) => {}
| ---- type must be known at this point | ---- 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: _; LL | let x: _;
| +++ | +++

View file

@ -191,7 +191,7 @@ error[E0282]: type annotations needed
LL | let x @ ..; 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 @ ..: _; LL | let x @ ..: _;
| +++ | +++

View file

@ -19,7 +19,7 @@ error[E0282]: type annotations needed
LL | let mut N; 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: _; LL | let mut N: _;
| +++ | +++

View file

@ -7,7 +7,7 @@ LL |
LL | x.0; LL | x.0;
| - type must be known at this point | - 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(); LL | let mut x: _ = Default::default();
| +++ | +++
@ -21,7 +21,7 @@ LL |
LL | x[0]; LL | x[0];
| - type must be known at this point | - 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(); LL | let mut x: _ = Default::default();
| +++ | +++

View file

@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | |x| x.len() LL | |x| x.len()
| ^ - type must be known at this point | ^ - 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() LL | |x: _| x.len()
| +++ | +++
@ -15,7 +15,7 @@ error[E0282]: type annotations needed
LL | |x| x.len() LL | |x| x.len()
| ^ - type must be known at this point | ^ - 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() LL | |x: _| x.len()
| +++ | +++

View file

@ -10,7 +10,7 @@ error[E0282]: type annotations needed
LL | let x = |_| {}; 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 = |_: _| {}; LL | let x = |_: _| {};
| +++ | +++

View file

@ -28,7 +28,7 @@ error[E0282]: type annotations needed
LL | let _ = |a, b: _| -> _ { 0 }; 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 }; LL | let _ = |a: _, b: _| -> _ { 0 };
| +++ | +++