1
Fork 0

Rollup merge of #105523 - estebank:suggest-collect-vec, r=compiler-errors

Suggest `collect`ing into `Vec<_>`

Fix #105510.
This commit is contained in:
Matthias Krüger 2022-12-14 10:31:07 +01:00 committed by GitHub
commit e5fde968db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 168 additions and 151 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;
@ -79,7 +79,7 @@ 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 in_type.is_ty_infer() {
"empty" ""
} else if self.name == "_" { } 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.
@ -183,13 +183,24 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
printer printer
} }
fn ty_to_string<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String { fn ty_to_string<'tcx>(
infcx: &InferCtxt<'tcx>,
ty: Ty<'tcx>,
called_method_def_id: Option<DefId>,
) -> String {
let printer = fmt_printer(infcx, Namespace::TypeNS); let printer = fmt_printer(infcx, Namespace::TypeNS);
let ty = infcx.resolve_vars_if_possible(ty); let ty = infcx.resolve_vars_if_possible(ty);
match ty.kind() { match (ty.kind(), called_method_def_id) {
// We don't want the regular output for `fn`s because it includes its path in // 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. // invalid pseudo-syntax, we want the `fn`-pointer output instead.
ty::FnDef(..) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(), (ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
(_, Some(def_id))
if ty.is_ty_infer()
&& infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
{
"Vec<_>".to_string()
}
_ if ty.is_ty_infer() => "/* Type */".to_string(),
// FIXME: The same thing for closures, but this only works when the closure // FIXME: The same thing for closures, but this only works when the closure
// does not capture anything. // does not capture anything.
// //
@ -213,7 +224,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
.map(|args| { .map(|args| {
args.tuple_fields() args.tuple_fields()
.iter() .iter()
.map(|arg| ty_to_string(infcx, arg)) .map(|arg| ty_to_string(infcx, arg, None))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", ") .join(", ")
}) })
@ -221,7 +232,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
let ret = if fn_sig.output().skip_binder().is_unit() { let ret = if fn_sig.output().skip_binder().is_unit() {
String::new() String::new()
} else { } else {
format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder())) format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
}; };
format!("fn({}){}", args, ret) format!("fn({}){}", args, ret)
} }
@ -368,6 +379,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,7 +418,7 @@ 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, def_id } => {
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),
@ -415,7 +427,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
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: ty_to_string(self, ty, def_id),
}); });
} }
InferSourceKind::ClosureArg { insert_span, ty } => { InferSourceKind::ClosureArg { insert_span, ty } => {
@ -427,7 +439,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
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: "closure", kind: "closure",
type_name: ty_to_string(self, ty), type_name: ty_to_string(self, ty, None),
}); });
} }
InferSourceKind::GenericArg { InferSourceKind::GenericArg {
@ -456,33 +468,39 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
parent_name, parent_name,
}); });
let args = fmt_printer(self, Namespace::TypeNS) let args = if self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn)
.comma_sep(generic_args.iter().copied().map(|arg| { == Some(generics_def_id)
if arg.is_suggestable(self.tcx, true) { {
return arg; "Vec<_>".to_string()
} } else {
fmt_printer(self, Namespace::TypeNS)
.comma_sep(generic_args.iter().copied().map(|arg| {
if arg.is_suggestable(self.tcx, true) {
return arg;
}
match arg.unpack() { match arg.unpack() {
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
GenericArgKind::Type(_) => self GenericArgKind::Type(_) => self
.next_ty_var(TypeVariableOrigin { .next_ty_var(TypeVariableOrigin {
span: rustc_span::DUMMY_SP,
kind: TypeVariableOriginKind::MiscVariable,
})
.into(),
GenericArgKind::Const(arg) => self
.next_const_var(
arg.ty(),
ConstVariableOrigin {
span: rustc_span::DUMMY_SP, span: rustc_span::DUMMY_SP,
kind: ConstVariableOriginKind::MiscVariable, kind: TypeVariableOriginKind::MiscVariable,
}, })
) .into(),
.into(), GenericArgKind::Const(arg) => self
} .next_const_var(
})) arg.ty(),
.unwrap() ConstVariableOrigin {
.into_buffer(); span: rustc_span::DUMMY_SP,
kind: ConstVariableOriginKind::MiscVariable,
},
)
.into(),
}
}))
.unwrap()
.into_buffer()
};
if !have_turbofish { if !have_turbofish {
infer_subdiags.push(SourceKindSubdiag::GenericSuggestion { infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
@ -520,7 +538,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
)); ));
} }
InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => { InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
let ty_info = ty_to_string(self, ty); let ty_info = ty_to_string(self, ty, None);
multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return( multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
ty_info, ty_info,
data, data,
@ -608,6 +626,7 @@ enum InferSourceKind<'tcx> {
insert_span: Span, insert_span: Span,
pattern_name: Option<Ident>, pattern_name: Option<Ident>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
def_id: Option<DefId>,
}, },
ClosureArg { ClosureArg {
insert_span: Span, insert_span: Span,
@ -662,7 +681,7 @@ impl<'tcx> InferSourceKind<'tcx> {
if ty.is_closure() { if ty.is_closure() {
("closure", closure_as_fn_str(infcx, ty)) ("closure", closure_as_fn_str(infcx, ty))
} else if !ty.is_ty_infer() { } else if !ty.is_ty_infer() {
("normal", ty_to_string(infcx, ty)) ("normal", ty_to_string(infcx, ty, None))
} else { } else {
("other", String::new()) ("other", String::new())
} }
@ -788,10 +807,18 @@ 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: did, ..}, .. }) = self.infer_source
&& let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..} = 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.
*def_id = Some(did);
}
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);
@ -1092,6 +1119,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,
def_id: None,
}, },
}) })
} }

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

@ -42,7 +42,7 @@ use rustc_middle::ty::{
}; };
use rustc_session::Limit; use rustc_session::Limit;
use rustc_span::def_id::LOCAL_CRATE; use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::symbol::{kw, sym}; use rustc_span::symbol::sym;
use rustc_span::{ExpnKind, Span, DUMMY_SP}; use rustc_span::{ExpnKind, Span, DUMMY_SP};
use std::fmt; use std::fmt;
use std::iter; use std::iter;
@ -980,6 +980,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_ref, trait_ref,
obligation.cause.body_id, obligation.cause.body_id,
&mut err, &mut err,
true,
) { ) {
// This is *almost* equivalent to // This is *almost* equivalent to
// `obligation.cause.code().peel_derives()`, but it gives us the // `obligation.cause.code().peel_derives()`, but it gives us the
@ -1015,6 +1016,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_ref, trait_ref,
obligation.cause.body_id, obligation.cause.body_id,
&mut err, &mut err,
true,
); );
} }
} }
@ -1434,6 +1436,7 @@ trait InferCtxtPrivExt<'tcx> {
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
body_id: hir::HirId, body_id: hir::HirId,
err: &mut Diagnostic, err: &mut Diagnostic,
other: bool,
) -> bool; ) -> bool;
/// Gets the parent trait chain start /// Gets the parent trait chain start
@ -1888,7 +1891,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
body_id: hir::HirId, body_id: hir::HirId,
err: &mut Diagnostic, err: &mut Diagnostic,
other: bool,
) -> bool { ) -> bool {
let other = if other { "other " } else { "" };
let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| { let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
candidates.sort(); candidates.sort();
candidates.dedup(); candidates.dedup();
@ -1939,7 +1944,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
candidates.dedup(); candidates.dedup();
let end = if candidates.len() <= 9 { candidates.len() } else { 8 }; let end = if candidates.len() <= 9 { candidates.len() } else { 8 };
err.help(&format!( err.help(&format!(
"the following other types implement trait `{}`:{}{}", "the following {other}types implement trait `{}`:{}{}",
trait_ref.print_only_trait_path(), trait_ref.print_only_trait_path(),
candidates[..end].join(""), candidates[..end].join(""),
if len > 9 { format!("\nand {} others", len - 8) } else { String::new() } if len > 9 { format!("\nand {} others", len - 8) } else { String::new() }
@ -2180,7 +2185,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer()); trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer());
// It doesn't make sense to talk about applicable impls if there are more // It doesn't make sense to talk about applicable impls if there are more
// than a handful of them. // than a handful of them.
if impls.len() > 1 && impls.len() < 5 && has_non_region_infer { if impls.len() > 1 && impls.len() < 10 && has_non_region_infer {
self.annotate_source_of_ambiguity(&mut err, &impls, predicate); self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
} else { } else {
if self.tainted_by_errors().is_some() { if self.tainted_by_errors().is_some() {
@ -2188,6 +2193,18 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
return; return;
} }
err.note(&format!("cannot satisfy `{}`", predicate)); err.note(&format!("cannot satisfy `{}`", predicate));
let impl_candidates = self.find_similar_impl_candidates(
predicate.to_opt_poly_trait_pred().unwrap(),
);
if impl_candidates.len() < 10 {
self.report_similar_impl_candidates(
impl_candidates,
trait_ref,
body_id.map(|id| id.hir_id).unwrap_or(obligation.cause.body_id),
&mut err,
false,
);
}
} }
} }
_ => { _ => {
@ -2199,60 +2216,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
} }
} }
if let ObligationCauseCode::ItemObligation(def_id) | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code() { if let ObligationCauseCode::ItemObligation(def_id)
self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code()
} else if let Ok(snippet) = &self.tcx.sess.source_map().span_to_snippet(span)
&& let ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ExprBindingObligation(def_id, ..)
= *obligation.cause.code()
{ {
let generics = self.tcx.generics_of(def_id); self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
if generics.params.iter().any(|p| p.name != kw::SelfUpper)
&& !snippet.ends_with('>')
&& !generics.has_impl_trait()
&& !self.tcx.is_fn_trait(def_id)
{
// FIXME: To avoid spurious suggestions in functions where type arguments
// where already supplied, we check the snippet to make sure it doesn't
// end with a turbofish. Ideally we would have access to a `PathSegment`
// instead. Otherwise we would produce the following output:
//
// error[E0283]: type annotations needed
// --> $DIR/issue-54954.rs:3:24
// |
// LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
// | ^^^^^^^^^^^^^^^^^^^^^^^^^^
// | |
// | cannot infer type
// | help: consider specifying the type argument
// | in the function call:
// | `Tt::const_val::<[i8; 123]>::<T>`
// ...
// LL | const fn const_val<T: Sized>() -> usize {
// | - required by this bound in `Tt::const_val`
// |
// = note: cannot satisfy `_: Tt`
// Clear any more general suggestions in favor of our specific one
err.clear_suggestions();
err.span_suggestion_verbose(
span.shrink_to_hi(),
&format!(
"consider specifying the type argument{} in the function call",
pluralize!(generics.params.len()),
),
format!(
"::<{}>",
generics
.params
.iter()
.map(|p| p.name.to_string())
.collect::<Vec<String>>()
.join(", ")
),
Applicability::HasPlaceholders,
);
}
} }
if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) = if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =

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

@ -6,8 +6,8 @@ LL | let [_, _] = a.into();
| |
help: consider giving this pattern a type help: consider giving this pattern a type
| |
LL | let [_, _]: _ = a.into(); LL | let [_, _]: /* Type */ = a.into();
| +++ | ++++++++++++
error: aborting due to previous error error: aborting due to previous error

View file

@ -6,8 +6,8 @@ LL | with_closure(|x: u32, y| {});
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | with_closure(|x: u32, y: _| {}); LL | with_closure(|x: u32, y: /* Type */| {});
| +++ | ++++++++++++
error: aborting due to previous error error: aborting due to previous error

View file

@ -12,8 +12,8 @@ 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
| |
LL | [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize] LL | [(); &(&'static: loop { |x: /* Type */| {}; }) as *const _ as usize]
| +++ | ++++++++++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -5,6 +5,12 @@ LL | let y = Mask::<_, _>::splat(false);
| ^ ------------------- type must be known at this point | ^ ------------------- type must be known at this point
| |
= note: cannot satisfy `_: MaskElement` = note: cannot satisfy `_: MaskElement`
= help: the following types implement trait `MaskElement`:
i16
i32
i64
i8
isize
note: required by a bound in `Mask::<T, LANES>::splat` note: required by a bound in `Mask::<T, LANES>::splat`
--> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
help: consider giving `y` an explicit type, where the type for type parameter `T` is specified help: consider giving `y` an explicit type, where the type for type parameter `T` is specified

View file

@ -41,6 +41,7 @@ LL | IsLessOrEqual<I, 8>: True,
| ^^^^ | ^^^^
| |
= note: cannot satisfy `IsLessOrEqual<I, 8>: True` = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
= help: the trait `True` is implemented for `IsLessOrEqual<LHS, RHS>`
error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True` error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8>: True`
--> $DIR/issue-72787.rs:21:26 --> $DIR/issue-72787.rs:21:26
@ -49,6 +50,7 @@ LL | IsLessOrEqual<I, 8>: True,
| ^^^^ | ^^^^
| |
= note: cannot satisfy `IsLessOrEqual<I, 8>: True` = note: cannot satisfy `IsLessOrEqual<I, 8>: True`
= help: the trait `True` is implemented for `IsLessOrEqual<LHS, RHS>`
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View file

@ -6,8 +6,8 @@ LL | let _ = foo([0; 1]);
| |
help: consider giving this pattern a type help: consider giving this pattern a type
| |
LL | let _: _ = foo([0; 1]); LL | let _: /* Type */ = foo([0; 1]);
| +++ | ++++++++++++
error: aborting due to previous error error: aborting due to previous error

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

@ -59,7 +59,7 @@ note: required by a bound in `bfnr`
| |
LL | fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) { LL | fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
| ^^^^ required by this bound in `bfnr` | ^^^^ required by this bound in `bfnr`
help: consider specifying the type arguments in the function call help: consider specifying the generic arguments
| |
LL | bfnr::<U, V, W>(x); LL | bfnr::<U, V, W>(x);
| +++++++++++ | +++++++++++

View file

@ -20,8 +20,8 @@ LL | |_| true
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | |_: _| true LL | |_: /* Type */| true
| +++ | ++++++++++++
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -10,10 +10,10 @@ note: required by a bound in `foo`
| |
LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> { LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
| ^^^^^^^ required by this bound in `foo` | ^^^^^^^ required by this bound in `foo`
help: consider specifying the type arguments in the function call help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified
| |
LL | let foo = foo::<T, K, W, Z>(1, ""); 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, Z>`
--> $DIR/erase-type-params-in-label.rs:5:9 --> $DIR/erase-type-params-in-label.rs:5:9
@ -27,10 +27,10 @@ note: required by a bound in `bar`
| |
LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> { LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
| ^^^^^^^ required by this bound in `bar` | ^^^^^^^ required by this bound in `bar`
help: consider specifying the type arguments in the function call help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified
| |
LL | let bar = bar::<T, K, Z>(1, ""); LL | let bar: Bar<i32, &str, Z> = bar(1, "");
| +++++++++++ | +++++++++++++++++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -32,8 +32,8 @@ 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
| |
LL | |x: _| String::from("x".as_ref()); LL | |x: /* Type */| String::from("x".as_ref());
| +++ | ++++++++++++
error[E0283]: type annotations needed error[E0283]: type annotations needed
--> $DIR/issue-72690.rs:12:26 --> $DIR/issue-72690.rs:12:26

View file

@ -6,8 +6,8 @@ LL | let x;
| |
help: consider giving `x` an explicit type help: consider giving `x` an explicit type
| |
LL | let x: _; LL | let x: /* Type */;
| +++ | ++++++++++++
error: aborting due to previous error error: aborting due to previous error

View file

@ -8,8 +8,8 @@ LL | x.clone();
| |
help: consider giving `x` an explicit type help: consider giving `x` an explicit type
| |
LL | let x: _ = panic!(); LL | let x: /* Type */ = panic!();
| +++ | ++++++++++++
error: aborting due to previous error error: aborting due to previous error

View file

@ -19,8 +19,8 @@ LL | 1 => |c| c + 1,
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | 1 => |c: _| c + 1, LL | 1 => |c: /* Type */| c + 1,
| +++ | ++++++++++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -6,8 +6,8 @@ LL | |s| s.len()
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | |s: _| s.len() LL | |s: /* Type */| s.len()
| +++ | ++++++++++++
error[E0282]: type annotations needed error[E0282]: type annotations needed
--> $DIR/branches3.rs:15:10 --> $DIR/branches3.rs:15:10
@ -17,8 +17,8 @@ LL | |s| s.len()
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | |s: _| s.len() LL | |s: /* Type */| s.len()
| +++ | ++++++++++++
error[E0282]: type annotations needed error[E0282]: type annotations needed
--> $DIR/branches3.rs:23:10 --> $DIR/branches3.rs:23:10
@ -28,8 +28,8 @@ LL | |s| s.len()
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | |s: _| s.len() LL | |s: /* Type */| s.len()
| +++ | ++++++++++++
error[E0282]: type annotations needed error[E0282]: type annotations needed
--> $DIR/branches3.rs:30:10 --> $DIR/branches3.rs:30:10
@ -39,8 +39,8 @@ LL | |s| s.len()
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | |s: _| s.len() LL | |s: /* Type */| s.len()
| +++ | ++++++++++++
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View file

@ -5,6 +5,7 @@ LL | &'a (): Foo,
| ^^^ | ^^^
| |
= note: cannot satisfy `&'a (): Foo` = note: cannot satisfy `&'a (): Foo`
= help: the trait `Foo` is implemented for `&'a T`
error: aborting due to previous error error: aborting due to previous error

View file

@ -6,8 +6,8 @@ LL | let x = match () {
| |
help: consider giving `x` an explicit type help: consider giving `x` an explicit type
| |
LL | let x: _ = match () { LL | let x: /* Type */ = match () {
| +++ | ++++++++++++
error: aborting due to previous error error: aborting due to previous error

View file

@ -9,8 +9,8 @@ LL | (..) => {}
| |
help: consider giving `x` an explicit type help: consider giving `x` an explicit type
| |
LL | let x: _; LL | let x: /* Type */;
| +++ | ++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/pat-tuple-bad-type.rs:10:9 --> $DIR/pat-tuple-bad-type.rs:10:9

View file

@ -193,8 +193,8 @@ LL | let x @ ..;
| |
help: consider giving this pattern a type help: consider giving this pattern a type
| |
LL | let x @ ..: _; LL | let x @ ..: /* Type */;
| +++ | ++++++++++++
error: aborting due to 23 previous errors error: aborting due to 23 previous errors

View file

@ -21,8 +21,8 @@ LL | let mut N;
| |
help: consider giving `N` an explicit type help: consider giving `N` an explicit type
| |
LL | let mut N: _; LL | let mut N: /* Type */;
| +++ | ++++++++++++
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -9,8 +9,8 @@ LL | x.0;
| |
help: consider giving `x` an explicit type help: consider giving `x` an explicit type
| |
LL | let mut x: _ = Default::default(); LL | let mut x: /* Type */ = Default::default();
| +++ | ++++++++++++
error[E0282]: type annotations needed error[E0282]: type annotations needed
--> $DIR/method-and-field-eager-resolution.rs:11:9 --> $DIR/method-and-field-eager-resolution.rs:11:9
@ -23,8 +23,8 @@ LL | x[0];
| |
help: consider giving `x` an explicit type help: consider giving `x` an explicit type
| |
LL | let mut x: _ = Default::default(); LL | let mut x: /* Type */ = Default::default();
| +++ | ++++++++++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -43,7 +43,15 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= note: cannot satisfy `u32: From<_>` = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
- impl From<Ipv4Addr> for u32;
- impl From<NonZeroU32> for u32;
- impl From<bool> for u32;
- impl From<char> for u32;
- impl From<u16> for u32;
- impl From<u8> for u32;
- impl<T> From<!> for T;
- impl<T> From<T> for T;
help: try using a fully qualified path to specify the expected types 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(); LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();

View file

@ -5,6 +5,9 @@ LL | T: FnMut(&'a ()),
| ^^^^^^^^^^^^^ | ^^^^^^^^^^^^^
| |
= note: cannot satisfy `T: FnMut<(&'a (),)>` = note: cannot satisfy `T: FnMut<(&'a (),)>`
= help: the following types implement trait `FnMut<Args>`:
&F
&mut F
error: aborting due to previous error error: aborting due to previous error

View file

@ -6,8 +6,8 @@ LL | |x| x.len()
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | |x: _| x.len() LL | |x: /* Type */| x.len()
| +++ | ++++++++++++
error[E0282]: type annotations needed error[E0282]: type annotations needed
--> $DIR/closures_in_branches.rs:21:10 --> $DIR/closures_in_branches.rs:21:10
@ -17,8 +17,8 @@ LL | |x| x.len()
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | |x: _| x.len() LL | |x: /* Type */| x.len()
| +++ | ++++++++++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -10,7 +10,7 @@ note: required by a bound in `foo`
| |
LL | fn foo<T: Into<String>>(x: i32) {} LL | fn foo<T: Into<String>>(x: i32) {}
| ^^^^^^^^^^^^ required by this bound in `foo` | ^^^^^^^^^^^^ required by this bound in `foo`
help: consider specifying the type argument in the function call help: consider specifying the generic argument
| |
LL | foo::<T>(42); LL | foo::<T>(42);
| +++++ | +++++

View file

@ -12,8 +12,8 @@ LL | let x = |_| {};
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | let x = |_: _| {}; LL | let x = |_: /* Type */| {};
| +++ | ++++++++++++
error[E0282]: type annotations needed error[E0282]: type annotations needed
--> $DIR/unknown_type_for_closure.rs:10:14 --> $DIR/unknown_type_for_closure.rs:10:14

View file

@ -30,8 +30,8 @@ LL | let _ = |a, b: _| -> _ { 0 };
| |
help: consider giving this closure parameter an explicit type help: consider giving this closure parameter an explicit type
| |
LL | let _ = |a: _, b: _| -> _ { 0 }; LL | let _ = |a: /* Type */, b: _| -> _ { 0 };
| +++ | ++++++++++++
error: aborting due to 5 previous errors error: aborting due to 5 previous errors