From 721fc7320850596a20ad417397f5fc8820cd87da Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 14 Feb 2022 12:48:27 +0100 Subject: [PATCH 1/7] remove the old `emit_inference_failure_err` --- .../infer/error_reporting/need_type_info.rs | 956 +----------------- 1 file changed, 43 insertions(+), 913 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 e1a2a237c2324..19b2ea08e5f8a 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 @@ -17,248 +17,6 @@ use rustc_span::symbol::kw; use rustc_span::{sym, Span}; use std::borrow::Cow; -struct FindHirNodeVisitor<'a, 'tcx> { - infcx: &'a InferCtxt<'a, 'tcx>, - target: GenericArg<'tcx>, - target_span: Span, - found_node_ty: Option>, - found_local_pattern: Option<&'tcx Pat<'tcx>>, - found_arg_pattern: Option<&'tcx Pat<'tcx>>, - found_closure: Option<&'tcx Expr<'tcx>>, - found_method_call: Option<&'tcx Expr<'tcx>>, - found_exact_method_call: Option<&'tcx Expr<'tcx>>, - found_for_loop_iter: Option<&'tcx Expr<'tcx>>, - found_use_diagnostic: Option>, -} - -impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> { - fn new(infcx: &'a InferCtxt<'a, 'tcx>, target: GenericArg<'tcx>, target_span: Span) -> Self { - Self { - infcx, - target, - target_span, - found_node_ty: None, - found_local_pattern: None, - found_arg_pattern: None, - found_closure: None, - found_method_call: None, - found_exact_method_call: None, - found_for_loop_iter: None, - found_use_diagnostic: None, - } - } - - fn node_type_opt(&self, hir_id: HirId) -> Option> { - self.infcx.in_progress_typeck_results?.borrow().node_type_opt(hir_id) - } - - fn node_ty_contains_target(&self, hir_id: HirId) -> Option> { - self.node_type_opt(hir_id).map(|ty| self.infcx.resolve_vars_if_possible(ty)).filter(|ty| { - ty.walk().any(|inner| { - inner == self.target - || match (inner.unpack(), self.target.unpack()) { - (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => { - use ty::{Infer, TyVar}; - match (inner_ty.kind(), target_ty.kind()) { - (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => self - .infcx - .inner - .borrow_mut() - .type_variables() - .sub_unified(a_vid, b_vid), - _ => false, - } - } - _ => false, - } - }) - }) - } - - /// Determine whether the expression, assumed to be the callee within a `Call`, - /// corresponds to the `From::from` emitted in desugaring of the `?` operator. - fn is_try_conversion(&self, callee: &Expr<'tcx>) -> bool { - self.infcx - .trait_def_from_hir_fn(callee.hir_id) - .map_or(false, |def_id| self.infcx.is_try_conversion(callee.span, def_id)) - } -} - -impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - - fn nested_visit_map(&mut self) -> Self::Map { - self.infcx.tcx.hir() - } - - fn visit_local(&mut self, local: &'tcx Local<'tcx>) { - if let (None, Some(ty)) = - (self.found_local_pattern, self.node_ty_contains_target(local.hir_id)) - { - self.found_local_pattern = Some(&*local.pat); - self.found_node_ty = Some(ty); - } - intravisit::walk_local(self, local); - } - - fn visit_body(&mut self, body: &'tcx Body<'tcx>) { - for param in body.params { - if let (None, Some(ty)) = - (self.found_arg_pattern, self.node_ty_contains_target(param.hir_id)) - { - self.found_arg_pattern = Some(&*param.pat); - self.found_node_ty = Some(ty); - } - } - intravisit::walk_body(self, body); - } - - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind - && let Some(pat) = arm.pat.for_loop_some() - && let Some(ty) = self.node_ty_contains_target(pat.hir_id) - { - self.found_for_loop_iter = Some(scrutinee); - self.found_node_ty = Some(ty); - return; - } - if let ExprKind::MethodCall(segment, exprs, _) = expr.kind - && segment.ident.span == self.target_span - && Some(self.target) == self.infcx.in_progress_typeck_results.and_then(|typeck_results| { - typeck_results - .borrow() - .node_type_opt(exprs.first().unwrap().hir_id) - .map(Into::into) - }) - { - self.found_exact_method_call = Some(&expr); - return; - } - - // FIXME(const_generics): Currently, any uninferred `const` generics arguments - // are handled specially, but instead they should be handled in `annotate_method_call`, - // which currently doesn't work because this evaluates to `false` for const arguments. - // See https://github.com/rust-lang/rust/pull/77758 for more details. - if let Some(ty) = self.node_ty_contains_target(expr.hir_id) { - match expr.kind { - ExprKind::Closure(..) => self.found_closure = Some(&expr), - ExprKind::MethodCall(..) => self.found_method_call = Some(&expr), - - // If the given expression falls within the target span and is a - // `From::from(e)` call emitted during desugaring of the `?` operator, - // extract the types inferred before and after the call - ExprKind::Call(callee, [arg]) - if self.target_span.contains(expr.span) - && self.found_use_diagnostic.is_none() - && self.is_try_conversion(callee) => - { - self.found_use_diagnostic = self.node_type_opt(arg.hir_id).map(|pre_ty| { - UseDiagnostic::TryConversion { pre_ty, post_ty: ty, span: callee.span } - }); - } - _ => {} - } - } - intravisit::walk_expr(self, expr); - } -} - -/// An observation about the use site of a type to be emitted as an additional -/// note in an inference failure error. -enum UseDiagnostic<'tcx> { - /// Records the types inferred before and after `From::from` is called on the - /// error value within the desugaring of the `?` operator. - TryConversion { pre_ty: Ty<'tcx>, post_ty: Ty<'tcx>, span: Span }, -} - -impl UseDiagnostic<'_> { - /// Return a descriptor of the value at the use site - fn descr(&self) -> &'static str { - match self { - Self::TryConversion { .. } => "error for `?` operator", - } - } - - /// Return a descriptor of the type at the use site - fn type_descr(&self) -> &'static str { - match self { - Self::TryConversion { .. } => "error type for `?` operator", - } - } - - fn applies_to(&self, span: Span) -> bool { - match *self { - // In some cases the span for an inference failure due to try - // conversion contains the antecedent expression as well as the `?` - Self::TryConversion { span: s, .. } => span.contains(s) && span.hi() == s.hi(), - } - } - - fn attach_note(&self, err: &mut Diagnostic) { - match *self { - Self::TryConversion { pre_ty, post_ty, .. } => { - let intro = "`?` implicitly converts the error value"; - - let msg = match (pre_ty.is_ty_infer(), post_ty.is_ty_infer()) { - (true, true) => format!("{} using the `From` trait", intro), - (false, true) => { - format!("{} into a type implementing `From<{}>`", intro, pre_ty) - } - (true, false) => { - format!("{} into `{}` using the `From` trait", intro, post_ty) - } - (false, false) => { - format!( - "{} into `{}` using its implementation of `From<{}>`", - intro, post_ty, pre_ty - ) - } - }; - - err.note(&msg); - } - } - } -} - -/// Suggest giving an appropriate return type to a closure expression. -fn closure_return_type_suggestion( - err: &mut Diagnostic, - output: &FnRetTy<'_>, - body: &Body<'_>, - ret: &str, -) { - let (arrow, post) = match output { - FnRetTy::DefaultReturn(_) => ("-> ", " "), - _ => ("", ""), - }; - let suggestion = match body.value.kind { - ExprKind::Block(..) => vec![(output.span(), format!("{}{}{}", arrow, ret, post))], - _ => vec![ - (output.span(), format!("{}{}{}{{ ", arrow, ret, post)), - (body.value.span.shrink_to_hi(), " }".to_string()), - ], - }; - err.multipart_suggestion( - "give this closure an explicit return type without `_` placeholders", - suggestion, - Applicability::HasPlaceholders, - ); -} - -/// Given a closure signature, return a `String` containing a list of all its argument types. -fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String { - fn_sig - .inputs() - .skip_binder() - .iter() - .next() - .map(|args| { - args.tuple_fields().iter().map(|arg| arg.to_string()).collect::>().join(", ") - }) - .unwrap_or_default() -} - pub enum TypeAnnotationNeeded { /// ```compile_fail,E0282 /// let x = "hello".chars().rev().collect(); @@ -306,32 +64,18 @@ pub enum UnderspecifiedArgKind { Const { is_parameter: bool }, } -impl UnderspecifiedArgKind { - fn descr(&self) -> &'static str { - match self { - Self::Type { .. } => "type", - Self::Const { .. } => "const", - } - } -} - impl InferenceDiagnosticsData { /// Generate a label for a generic argument which can't be inferred. When not /// much is known about the argument, `use_diag` may be used to describe the /// labeled value. - fn cannot_infer_msg(&self, use_diag: Option<&UseDiagnostic<'_>>) -> String { + fn cannot_infer_msg(&self) -> String { if self.name == "_" && matches!(self.kind, UnderspecifiedArgKind::Type { .. }) { - if let Some(use_diag) = use_diag { - return format!("cannot infer type of {}", use_diag.descr()); - } - return "cannot infer type".to_string(); } - let suffix = match (&self.parent, use_diag) { - (Some(parent), _) => format!(" declared on the {} `{}`", parent.prefix, parent.name), - (None, Some(use_diag)) => format!(" in {}", use_diag.type_descr()), - (None, None) => String::new(), + let suffix = match &self.parent { + Some(parent) => parent.suffix_string(), + None => String::new(), }; // For example: "cannot infer type for type parameter `T`" @@ -340,9 +84,10 @@ impl InferenceDiagnosticsData { } impl InferenceDiagnosticsParentData { - fn for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - let parent_def_id = tcx.parent(def_id); - + fn for_parent_def_id( + tcx: TyCtxt<'_>, + parent_def_id: DefId, + ) -> Option { let parent_name = tcx.def_key(parent_def_id).disambiguated_data.data.get_opt_name()?.to_string(); @@ -352,6 +97,14 @@ impl InferenceDiagnosticsParentData { def_id: parent_def_id, }) } + + fn for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + Self::for_parent_def_id(tcx, tcx.parent(def_id)) + } + + fn suffix_string(&self) -> String { + format!(" declared on the {} `{}`", self.prefix, self.name) + } } impl UnderspecifiedArgKind { @@ -409,71 +162,34 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } GenericArgKind::Const(ct) => { - match ct.val() { - ty::ConstKind::Infer(InferConst::Var(vid)) => { - let origin = self - .inner - .borrow_mut() - .const_unification_table() - .probe_value(vid) - .origin; - if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = - origin.kind - { - return InferenceDiagnosticsData { - name: name.to_string(), - span: Some(origin.span), - kind: UnderspecifiedArgKind::Const { is_parameter: true }, - parent: InferenceDiagnosticsParentData::for_def_id( - self.tcx, def_id, - ), - }; - } - - debug_assert!(!origin.span.is_dummy()); - let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::ValueNS); - if let Some(highlight) = highlight { - printer.region_highlight_mode = highlight; - } - let name = ct.print(printer).unwrap().into_buffer(); - InferenceDiagnosticsData { - name, + if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val() { + let origin = + self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; + if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = + origin.kind + { + return InferenceDiagnosticsData { + name: name.to_string(), span: Some(origin.span), - kind: UnderspecifiedArgKind::Const { is_parameter: false }, - parent: None, - } + kind: UnderspecifiedArgKind::Const { is_parameter: true }, + parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id), + }; } - ty::ConstKind::Unevaluated(ty::Unevaluated { substs, .. }) => { - assert!(substs.has_infer_types_or_consts()); - // FIXME: We only use the first inference variable we encounter in - // `substs` here, this gives insufficiently informative diagnostics - // in case there are multiple inference variables - for s in substs.iter() { - match s.unpack() { - GenericArgKind::Type(t) => match t.kind() { - ty::Infer(_) => { - return self.extract_inference_diagnostics_data(s, None); - } - _ => {} - }, - GenericArgKind::Const(c) => match c.val() { - ty::ConstKind::Infer(InferConst::Var(_)) => { - return self.extract_inference_diagnostics_data(s, None); - } - _ => {} - }, - _ => {} - } - } - bug!( - "expected an inference variable in substs of unevaluated const {:?}", - ct - ); + debug_assert!(!origin.span.is_dummy()); + let mut printer = + ty::print::FmtPrinter::new(self.tcx, Namespace::ValueNS); + if let Some(highlight) = highlight { + printer.region_highlight_mode = highlight; } - _ => { - bug!("unexpect const: {:?}", ct); + InferenceDiagnosticsData { + name: ct.print(printer).unwrap().into_buffer(), + span: Some(origin.span), + kind: UnderspecifiedArgKind::Const { is_parameter: false }, + parent: None, } + } else { + bug!("unexpect const: {:?}", ct); } } GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), @@ -489,473 +205,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { error_code: TypeAnnotationNeeded, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let arg = self.resolve_vars_if_possible(arg); - let arg_data = self.extract_inference_diagnostics_data(arg, None); - let mut local_visitor = FindHirNodeVisitor::new(&self, arg, span); - let ty_to_string = |ty: Ty<'tcx>| -> String { - let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS); - let ty_getter = move |ty_vid| { - if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = - self.inner.borrow_mut().type_variables().var_origin(ty_vid).kind - { - Some(name.to_string()) - } else { - None - } - }; - printer.ty_infer_name_resolver = Some(Box::new(ty_getter)); - let const_getter = move |ct_vid| { - if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = self - .inner - .borrow_mut() - .const_unification_table() - .probe_value(ct_vid) - .origin - .kind - { - return Some(name.to_string()); - } else { - None - } - }; - printer.const_infer_name_resolver = Some(Box::new(const_getter)); - - if let ty::FnDef(..) = ty.kind() { - // 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. - ty.fn_sig(self.tcx).print(printer).unwrap().into_buffer() - } else { - ty.print(printer).unwrap().into_buffer() - } - }; - - if let Some(body_id) = body_id { - let expr = self.tcx.hir().expect_expr(body_id.hir_id); - local_visitor.visit_expr(expr); - } - let err_span = if let Some(pattern) = local_visitor.found_arg_pattern { - pattern.span - } else if let Some(span) = arg_data.span { - // `span` here lets us point at `sum` instead of the entire right hand side expr: - // error[E0282]: type annotations needed - // --> file2.rs:3:15 - // | - // 3 | let _ = x.sum() as f64; - // | ^^^ cannot infer type for `S` - span - } else if let Some(ExprKind::MethodCall(segment, ..)) = - local_visitor.found_method_call.map(|e| &e.kind) - { - // Point at the call instead of the whole expression: - // error[E0284]: type annotations needed - // --> file.rs:2:5 - // | - // 2 | [Ok(2)].into_iter().collect()?; - // | ^^^^^^^ cannot infer type - // | - // = note: cannot resolve `<_ as std::ops::Try>::Ok == _` - if span.contains(segment.ident.span) { segment.ident.span } else { span } - } else { - span - }; - - let is_named_and_not_impl_trait = - |ty: Ty<'_>| &ty.to_string() != "_" && !ty.is_impl_trait(); - - let ty_msg = match (local_visitor.found_node_ty, local_visitor.found_exact_method_call) { - (_, Some(_)) => String::new(), - (Some(ty), _) if ty.is_closure() => { - let ty::Closure(_, substs) = *ty.kind() else { unreachable!() }; - let fn_sig = substs.as_closure().sig(); - let args = closure_args(&fn_sig); - let ret = fn_sig.output().skip_binder().to_string(); - format!(" for the closure `fn({}) -> {}`", args, ret) - } - (Some(ty), _) if is_named_and_not_impl_trait(ty) => { - let ty = ty_to_string(ty); - format!(" for `{}`", ty) - } - _ => String::new(), - }; - - // When `arg_data.name` corresponds to a type argument, show the path of the full type we're - // trying to infer. In the following example, `ty_msg` contains - // " for `std::result::Result`": - // ``` - // error[E0282]: type annotations needed for `std::result::Result` - // --> file.rs:L:CC - // | - // L | let b = Ok(4); - // | - ^^ cannot infer type for `E` in `std::result::Result` - // | | - // | consider giving `b` the explicit type `std::result::Result`, where - // | the type parameter `E` is specified - // ``` let error_code = error_code.into(); - let mut err = self.tcx.sess.struct_span_err_with_code( - err_span, - &format!("type annotations needed{}", ty_msg), + let err = self.tcx.sess.struct_span_err_with_code( + span, + &format!("type annotations needed"), error_code, ); - - let use_diag = local_visitor.found_use_diagnostic.as_ref(); - if let Some(use_diag) = use_diag && use_diag.applies_to(err_span) { - use_diag.attach_note(&mut err); - } - - let param_type = arg_data.kind.descr(); - let suffix = match local_visitor.found_node_ty { - Some(ty) if ty.is_closure() => { - let ty::Closure(_, substs) = *ty.kind() else { unreachable!() }; - let fn_sig = substs.as_closure().sig(); - let ret = fn_sig.output().skip_binder().to_string(); - - let closure_decl_and_body_id = - local_visitor.found_closure.and_then(|closure| match &closure.kind { - ExprKind::Closure(_, decl, body_id, ..) => Some((decl, *body_id)), - _ => None, - }); - - if let Some((decl, body_id)) = closure_decl_and_body_id { - closure_return_type_suggestion( - &mut err, - &decl.output, - self.tcx.hir().body(body_id), - &ret, - ); - // We don't want to give the other suggestions when the problem is the - // closure return type. - err.span_label( - span, - arg_data.cannot_infer_msg(use_diag.filter(|d| d.applies_to(span))), - ); - return err; - } - - // This shouldn't be reachable, but just in case we leave a reasonable fallback. - let args = closure_args(&fn_sig); - // This suggestion is incomplete, as the user will get further type inference - // errors due to the `_` placeholders and the introduction of `Box`, but it does - // nudge them in the right direction. - format!("a boxed closure type like `Box {}>`", args, ret) - } - Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => { - let ty = ty_to_string(ty); - format!("the explicit type `{}`, with the {} parameters specified", ty, param_type) - } - Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => { - let ty = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty); - let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty); - let ty = ty_to_string(ty); - format!( - "the explicit type `{}`, where the {} parameter `{}` is specified", - ty, param_type, arg_data.name, - ) - } - _ => "a type".to_string(), - }; - - if let Some(e) = local_visitor.found_exact_method_call { - if let ExprKind::MethodCall(segment, ..) = &e.kind { - // Suggest specifying type params or point out the return type of the call: - // - // error[E0282]: type annotations needed - // --> $DIR/type-annotations-needed-expr.rs:2:39 - // | - // LL | let _ = x.into_iter().sum() as f64; - // | ^^^ - // | | - // | cannot infer type for `S` - // | help: consider specifying the type argument in - // | the method call: `sum::` - // | - // = note: type must be known at this point - // - // or - // - // error[E0282]: type annotations needed - // --> $DIR/issue-65611.rs:59:20 - // | - // LL | let x = buffer.last().unwrap().0.clone(); - // | -------^^^^-- - // | | | - // | | cannot infer type for `T` - // | this method call resolves to `std::option::Option<&T>` - // | - // = note: type must be known at this point - self.annotate_method_call(segment, e, &mut err); - } - } else if let Some(pattern) = local_visitor.found_arg_pattern { - // We don't want to show the default label for closures. - // - // So, before clearing, the output would look something like this: - // ``` - // let x = |_| { }; - // - ^^^^ cannot infer type for `[_; 0]` - // | - // consider giving this closure parameter a type - // ``` - // - // After clearing, it looks something like this: - // ``` - // let x = |_| { }; - // ^ consider giving this closure parameter the type `[_; 0]` - // with the type parameter `_` specified - // ``` - err.span_label( - pattern.span, - format!("consider giving this closure parameter {}", suffix), - ); - } else if let Some(pattern) = local_visitor.found_local_pattern { - let msg = if let Some(simple_ident) = pattern.simple_ident() { - match pattern.span.desugaring_kind() { - None => format!("consider giving `{}` {}", simple_ident, suffix), - Some(_) => format!("this needs {}", suffix), - } - } else { - format!("consider giving this pattern {}", suffix) - }; - err.span_label(pattern.span, msg); - } else if let Some(e) = local_visitor.found_method_call { - if let ExprKind::MethodCall(segment, exprs, _) = &e.kind { - // Suggest impl candidates: - // - // error[E0283]: type annotations needed - // --> $DIR/E0283.rs:35:24 - // | - // LL | let bar = foo_impl.into() * 1u32; - // | ---------^^^^-- - // | | | - // | | cannot infer type for type parameter `T` declared on the trait `Into` - // | this method call resolves to `T` - // | help: specify type like: `>::into(foo_impl)` - // | - // = note: cannot satisfy `Impl: Into<_>` - debug!(?segment); - if !impl_candidates.is_empty() && e.span.contains(span) - && let Some(expr) = exprs.first() - && let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind - && let [_] = path.segments - { - let mut eraser = TypeParamEraser(self.tcx); - let candidate_len = impl_candidates.len(); - let mut suggestions: Vec<_> = impl_candidates.iter().filter_map(|candidate| { - let trait_item = self.tcx - .associated_items(candidate.def_id) - .find_by_name_and_kind( - self.tcx, - segment.ident, - ty::AssocKind::Fn, - candidate.def_id - ); - if trait_item.is_none() { - return None; - } - let prefix = if let Some(trait_item) = trait_item - && let Some(trait_m) = trait_item.def_id.as_local() - && let hir::TraitItemKind::Fn(fn_, _) = &self.tcx.hir().trait_item(hir::TraitItemId { def_id: trait_m }).kind - { - match fn_.decl.implicit_self { - hir::ImplicitSelfKind::ImmRef => "&", - hir::ImplicitSelfKind::MutRef => "&mut ", - _ => "", - } - } else { - "" - }; - let candidate = candidate.super_fold_with(&mut eraser); - Some(vec![ - (expr.span.shrink_to_lo(), format!("{}::{}({}", candidate, segment.ident, prefix)), - if exprs.len() == 1 { - (expr.span.shrink_to_hi().with_hi(e.span.hi()), ")".to_string()) - } else { - (expr.span.shrink_to_hi().with_hi(exprs[1].span.lo()), ", ".to_string()) - }, - ]) - }).collect(); - suggestions.sort_by(|a, b| a[0].1.cmp(&b[0].1)); - if !suggestions.is_empty() { - err.multipart_suggestions( - &format!( - "use the fully qualified path for the potential candidate{}", - pluralize!(candidate_len), - ), - suggestions.into_iter(), - Applicability::MaybeIncorrect, - ); - } - } - // Suggest specifying type params or point out the return type of the call: - // - // error[E0282]: type annotations needed - // --> $DIR/type-annotations-needed-expr.rs:2:39 - // | - // LL | let _ = x.into_iter().sum() as f64; - // | ^^^ - // | | - // | cannot infer type for `S` - // | help: consider specifying the type argument in - // | the method call: `sum::` - // | - // = note: type must be known at this point - // - // or - // - // error[E0282]: type annotations needed - // --> $DIR/issue-65611.rs:59:20 - // | - // LL | let x = buffer.last().unwrap().0.clone(); - // | -------^^^^-- - // | | | - // | | cannot infer type for `T` - // | this method call resolves to `std::option::Option<&T>` - // | - // = note: type must be known at this point - self.annotate_method_call(segment, e, &mut err); - } - } else if let Some(scrutinee) = local_visitor.found_for_loop_iter { - err.span_label( - scrutinee.span, - "the element type for this iterator is not specified".to_string(), - ); - } - // Instead of the following: - // error[E0282]: type annotations needed - // --> file2.rs:3:15 - // | - // 3 | let _ = x.sum() as f64; - // | --^^^--------- cannot infer type for `S` - // | - // = note: type must be known at this point - // We want: - // error[E0282]: type annotations needed - // --> file2.rs:3:15 - // | - // 3 | let _ = x.sum() as f64; - // | ^^^ cannot infer type for `S` - // | - // = note: type must be known at this point - let span = arg_data.span.unwrap_or(err_span); - - // Avoid multiple labels pointing at `span`. - if !err - .span - .span_labels() - .iter() - .any(|span_label| span_label.label.is_some() && span_label.span == span) - && local_visitor.found_arg_pattern.is_none() - { - // FIXME(const_generics): we would like to handle const arguments - // as part of the normal diagnostics flow below, but there appear to - // be subtleties in doing so, so for now we special-case const args - // here. - if let (UnderspecifiedArgKind::Const { .. }, Some(parent_data)) = - (&arg_data.kind, &arg_data.parent) - { - // (#83606): Do not emit a suggestion if the parent has an `impl Trait` - // as an argument otherwise it will cause the E0282 error. - if !self.tcx.generics_of(parent_data.def_id).has_impl_trait() - || self.tcx.features().explicit_generic_args_with_impl_trait - { - err.span_suggestion_verbose( - span, - "consider specifying the const argument", - format!("{}::<{}>", parent_data.name, arg_data.name), - Applicability::MaybeIncorrect, - ); - } - } - - self.report_ambiguous_type_parameter(&mut err, arg); - err.span_label( - span, - arg_data.cannot_infer_msg(use_diag.filter(|d| d.applies_to(span))), - ); - } - err } - fn trait_def_from_hir_fn(&self, hir_id: hir::HirId) -> Option { - // The DefId will be the method's trait item ID unless this is an inherent impl - if let Some((DefKind::AssocFn, def_id)) = - self.in_progress_typeck_results?.borrow().type_dependent_def(hir_id) - { - let parent_def_id = self.tcx.parent(def_id); - return self.tcx.is_trait(parent_def_id).then_some(parent_def_id); - } - - None - } - - /// If the `FnSig` for the method call can be found and type arguments are identified as - /// needed, suggest annotating the call, otherwise point out the resulting type of the call. - fn annotate_method_call( - &self, - segment: &hir::PathSegment<'_>, - e: &Expr<'_>, - err: &mut Diagnostic, - ) { - if let (Some(typeck_results), None) = (self.in_progress_typeck_results, &segment.args) { - let borrow = typeck_results.borrow(); - if let Some((DefKind::AssocFn, did)) = borrow.type_dependent_def(e.hir_id) { - let generics = self.tcx.generics_of(did); - if !generics.params.is_empty() && !generics.has_impl_trait() { - err.span_suggestion_verbose( - segment.ident.span.shrink_to_hi(), - &format!( - "consider specifying the type argument{} in the method call", - pluralize!(generics.params.len()), - ), - format!( - "::<{}>", - generics - .params - .iter() - .map(|p| p.name.to_string()) - .collect::>() - .join(", ") - ), - Applicability::HasPlaceholders, - ); - } else { - let sig = self.tcx.fn_sig(did); - let bound_output = sig.output(); - let output = bound_output.skip_binder(); - err.span_label(e.span, &format!("this method call resolves to `{}`", output)); - let kind = output.kind(); - if let ty::Projection(proj) = kind { - if let Some(span) = self.tcx.hir().span_if_local(proj.item_def_id) { - err.span_label(span, &format!("`{}` defined here", output)); - } - } - } - } - } - } - - fn report_ambiguous_type_parameter(&self, err: &mut Diagnostic, arg: GenericArg<'tcx>) { - if let GenericArgKind::Type(ty) = arg.unpack() - && let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() - { - let mut inner = self.inner.borrow_mut(); - let ty_vars = &inner.type_variables(); - let var_origin = ty_vars.var_origin(ty_vid); - if let TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) = - var_origin.kind - && let Some(parent_def_id) = self.tcx.parent(def_id).as_local() - && let Some(node) = self.tcx.hir().find_by_def_id(parent_def_id) - { - match node { - hir::Node::Item(item) if matches!(item.kind, hir::ItemKind::Impl(_) | hir::ItemKind::Fn(..)) => (), - hir::Node::ImplItem(impl_item) if matches!(impl_item.kind, hir::ImplItemKind::Fn(..)) => (), - _ => return, - } - err.span_help(self.tcx.def_span(def_id), "type parameter declared here"); - } - } - } - pub fn need_type_info_err_in_generator( &self, kind: hir::GeneratorKind, @@ -972,136 +231,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "type inside {} must be known in this context", kind, ); - err.span_label(span, data.cannot_infer_msg(None)); + err.span_label(span, data.cannot_infer_msg()); err } } - -/// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After -/// performing that replacement, we'll turn all remaining infer type params to use their name from -/// their definition, and replace all the `[type error]`s back to being infer so they display in -/// the output as `_`. If we didn't go through `[type error]`, we would either show all type params -/// by their name *or* `_`, neither of which is desirable: we want to show all types that we could -/// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations. -struct ResolvedTypeParamEraser<'tcx> { - tcx: TyCtxt<'tcx>, - level: usize, -} - -impl<'tcx> ResolvedTypeParamEraser<'tcx> { - fn new(tcx: TyCtxt<'tcx>) -> Self { - ResolvedTypeParamEraser { tcx, level: 0 } - } - - /// Replace not yet inferred const params with their def name. - fn replace_infers(&self, c: Const<'tcx>, index: u32, name: Symbol) -> Const<'tcx> { - match c.val() { - ty::ConstKind::Infer(..) => self.tcx().mk_const_param(index, name, c.ty()), - _ => c, - } - } -} - -impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx - } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - self.level += 1; - let t = match t.kind() { - // We'll hide this type only if all its type params are hidden as well. - ty::Adt(def, substs) => { - let generics = self.tcx().generics_of(def.did()); - // Account for params with default values, like `Vec`, where we - // want to show `Vec`, not `Vec`. If we replaced that - // subst, then we'd get the incorrect output, so we passthrough. - let substs: Vec<_> = substs - .iter() - .zip(generics.params.iter()) - .map(|(subst, param)| match &(subst.unpack(), ¶m.kind) { - (_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst, - (crate::infer::GenericArgKind::Const(c), _) => { - self.replace_infers(*c, param.index, param.name).into() - } - _ => subst.super_fold_with(self), - }) - .collect(); - let should_keep = |subst: &GenericArg<'_>| match subst.unpack() { - ty::subst::GenericArgKind::Type(t) => match t.kind() { - ty::Error(_) => false, - _ => true, - }, - // Account for `const` params here, otherwise `doesnt_infer.rs` - // shows `_` instead of `Foo<{ _: u32 }>` - ty::subst::GenericArgKind::Const(_) => true, - _ => false, - }; - if self.level == 1 || substs.iter().any(should_keep) { - let substs = self.tcx().intern_substs(&substs[..]); - self.tcx().mk_ty(ty::Adt(*def, substs)) - } else { - self.tcx().ty_error() - } - } - ty::Ref(_, ty, _) => { - let ty = self.fold_ty(*ty); - match ty.kind() { - // Avoid `&_`, these can be safely presented as `_`. - ty::Error(_) => self.tcx().ty_error(), - _ => t.super_fold_with(self), - } - } - // We could account for `()` if we wanted to replace it, but it's assured to be short. - ty::Tuple(_) - | ty::Slice(_) - | ty::RawPtr(_) - | ty::FnDef(..) - | ty::FnPtr(_) - | ty::Opaque(..) - | ty::Projection(_) - | ty::Never => t.super_fold_with(self), - ty::Array(ty, c) => { - self.tcx().mk_ty(ty::Array(self.fold_ty(*ty), self.replace_infers(*c, 0, sym::N))) - } - // We don't want to hide type params that haven't been resolved yet. - // This would be the type that will be written out with the type param - // name in the output. - ty::Infer(_) => t, - // We don't want to hide the outermost type, only its type params. - _ if self.level == 1 => t.super_fold_with(self), - // Hide this type - _ => self.tcx().ty_error(), - }; - self.level -= 1; - t - } -} - -/// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`. -struct ErrTypeParamEraser<'tcx>(TyCtxt<'tcx>); -impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.0 - } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.kind() { - ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)), - _ => t.super_fold_with(self), - } - } -} - -/// Replace type parameters with `ty::Infer(ty::Var)` to display `_`. -struct TypeParamEraser<'tcx>(TyCtxt<'tcx>); - -impl<'tcx> TypeFolder<'tcx> for TypeParamEraser<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.0 - } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.kind() { - ty::Param(_) | ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)), - _ => t.super_fold_with(self), - } - } -} From 3fe346e7a3776d01541fc973c4a7bb686ef3b1a8 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 14 Feb 2022 13:25:26 +0100 Subject: [PATCH 2/7] add new `emit_inference_failure_err` --- .../infer/error_reporting/need_type_info.rs | 829 +++++++++++++++++- compiler/rustc_infer/src/lib.rs | 1 + compiler/rustc_middle/src/hir/map/mod.rs | 6 +- compiler/rustc_middle/src/ty/generics.rs | 29 + .../ui/array-slice-vec/infer_array_len.stderr | 6 +- .../ui/array-slice-vec/vector-no-ann.stderr | 11 +- ...er-vars-supply-ty-with-bound-region.stderr | 7 +- src/test/ui/closures/issue-52437.stderr | 7 +- .../defaults/doesnt_infer.stderr | 11 +- .../generic_arg_infer/issue-91614.stderr | 10 +- .../const_eval_resolve_canonical.stderr | 9 +- .../infer/cannot-infer-const-args.stderr | 6 +- .../const-generics/infer/issue-77092.stderr | 8 +- .../const-generics/infer/method-chain.stderr | 6 +- .../infer/one-param-uninferred.stderr | 8 +- .../infer/uninferred-consts.stderr | 8 +- .../const-generics/issues/issue-83249.stderr | 13 +- src/test/ui/consts/issue-64662.stderr | 18 +- src/test/ui/error-codes/E0282.stderr | 7 +- src/test/ui/error-codes/E0283.stderr | 11 +- src/test/ui/error-codes/E0401.stderr | 9 +- ...for-loop-unconstrained-element-type.stderr | 11 +- .../issue-91762.stderr | 7 +- .../impl-trait/cross-return-site-inference.rs | 8 +- .../cross-return-site-inference.stderr | 33 +- .../fully-qualified-path-impl-trait.rs | 15 + .../fully-qualified-path-impl-trait.stderr | 9 + src/test/ui/impl-trait/fallback_inference.rs | 2 +- .../ui/impl-trait/fallback_inference.stderr | 11 +- .../ui/impl-trait/hidden-type-is-opaque-2.rs | 8 +- .../impl-trait/hidden-type-is-opaque-2.stderr | 12 +- .../ui/impl-trait/issues/issue-84073.stderr | 7 +- .../ui/impl-trait/issues/issue-86719.stderr | 7 +- .../ui/impl-trait/issues/issue-92305.stderr | 7 +- .../inference/ambiguous_type_parameter.stderr | 6 - .../ui/inference/cannot-infer-async.stderr | 10 +- .../cannot-infer-closure-circular.rs | 3 +- .../cannot-infer-closure-circular.stderr | 7 +- src/test/ui/inference/cannot-infer-closure.rs | 2 +- .../ui/inference/cannot-infer-closure.stderr | 10 +- .../cannot-infer-partial-try-return.rs | 3 +- .../cannot-infer-partial-try-return.stderr | 15 +- .../erase-type-params-in-label.stderr | 30 +- src/test/ui/inference/issue-71732.stderr | 8 +- src/test/ui/inference/issue-72616.stderr | 10 +- src/test/ui/inference/issue-83606.stderr | 11 +- src/test/ui/inference/issue-86162-1.stderr | 13 +- src/test/ui/inference/issue-86162-2.stderr | 13 +- src/test/ui/issues/issue-12187-1.stderr | 12 +- src/test/ui/issues/issue-12187-2.stderr | 12 +- src/test/ui/issues/issue-16966.stderr | 6 +- src/test/ui/issues/issue-17551.stderr | 11 +- src/test/ui/issues/issue-18159.stderr | 7 +- src/test/ui/issues/issue-20261.stderr | 4 +- src/test/ui/issues/issue-2151.rs | 4 +- src/test/ui/issues/issue-2151.stderr | 10 +- src/test/ui/issues/issue-23046.stderr | 7 +- src/test/ui/issues/issue-24036.stderr | 7 +- src/test/ui/issues/issue-25368.rs | 7 +- src/test/ui/issues/issue-25368.stderr | 14 +- src/test/ui/issues/issue-47486.stderr | 9 +- src/test/ui/issues/issue-5062.stderr | 7 +- src/test/ui/issues/issue-51116.rs | 1 - src/test/ui/issues/issue-51116.stderr | 5 +- src/test/ui/issues/issue-6458-2.stderr | 7 +- src/test/ui/issues/issue-6458-3.stderr | 7 +- src/test/ui/issues/issue-6458.stderr | 11 +- src/test/ui/issues/issue-66706.stderr | 2 +- src/test/ui/issues/issue-69455.stderr | 18 +- src/test/ui/issues/issue-69683.stderr | 6 +- src/test/ui/issues/issue-72690.stderr | 89 +- src/test/ui/issues/issue-7813.stderr | 11 +- .../ui/match/match-unresolved-one-arm.stderr | 7 +- ...od-ambig-one-trait-unknown-int-type.stderr | 11 +- .../missing-type-parameter.stderr | 9 +- ...invalid-syntax-in-enum-discriminant.stderr | 7 +- ...closing-angle-bracket-eq-constraint.stderr | 22 +- src/test/ui/pattern/pat-tuple-bad-type.rs | 4 +- src/test/ui/pattern/pat-tuple-bad-type.stderr | 11 +- .../rest-pat-semantic-disallowed.stderr | 7 +- src/test/ui/resolve/issue-85348.stderr | 7 +- ...ue-42234-unknown-receiver-type.full.stderr | 22 +- ...4-unknown-receiver-type.generic_arg.stderr | 22 +- .../span/issue-42234-unknown-receiver-type.rs | 3 +- .../span/method-and-field-eager-resolution.rs | 4 +- .../method-and-field-eager-resolution.stderr | 20 +- .../span/type-annotations-needed-expr.stderr | 4 +- .../fn-needing-specified-return-type-param.rs | 4 +- ...needing-specified-return-type-param.stderr | 13 +- .../suggest-closure-return-type-1.rs | 6 +- .../suggest-closure-return-type-1.stderr | 15 +- .../suggest-closure-return-type-2.rs | 6 +- .../suggest-closure-return-type-2.stderr | 13 +- .../suggest-closure-return-type-3.rs | 6 +- .../suggest-closure-return-type-3.stderr | 14 +- ...s-by-name-in-suggestion-issue-96292.stderr | 23 +- src/test/ui/traits/issue-77982.stderr | 60 +- .../multidispatch-convert-ambig-dest.stderr | 20 +- ...t-non-existing-fully-qualified-path.stderr | 24 +- ...st-fully-qualified-path-with-adjustment.rs | 60 ++ ...ully-qualified-path-with-adjustment.stderr | 186 ++++ ...-qualified-path-with-appropriate-params.rs | 24 - ...lified-path-with-appropriate-params.stderr | 61 -- ...fully-qualified-path-without-adjustment.rs | 64 ++ ...y-qualified-path-without-adjustment.stderr | 224 +++++ .../closures_in_branches.stderr | 6 +- .../incomplete-inference.stderr | 7 +- .../or_else-multiple-type-params.stderr | 11 +- src/test/ui/type-inference/sort_by_key.stderr | 6 +- .../unbounded-associated-type.stderr | 15 +- ...ed-type-param-in-fn-with-assoc-type.stderr | 9 +- .../unbounded-type-param-in-fn.stderr | 9 +- .../ui/type/type-annotation-needed.stderr | 11 +- .../cannot_infer_local_or_array.stderr | 11 +- .../cannot_infer_local_or_vec.stderr | 11 +- ...cannot_infer_local_or_vec_in_tuples.stderr | 11 +- .../type-check/unknown_type_for_closure.rs | 2 +- .../unknown_type_for_closure.stderr | 39 +- .../ui/type/type-path-err-node-types.stderr | 7 +- src/test/ui/typeck/issue-65611.stderr | 7 +- .../unboxed-closures-failed-recursive-fn-2.rs | 2 +- ...oxed-closures-failed-recursive-fn-2.stderr | 11 +- src/test/ui/unconstrained-none.stderr | 7 +- src/test/ui/unconstrained-ref.stderr | 7 +- 124 files changed, 2114 insertions(+), 630 deletions(-) create mode 100644 src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs create mode 100644 src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr create mode 100644 src/test/ui/traits/suggest-fully-qualified-path-with-adjustment.rs create mode 100644 src/test/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr delete mode 100644 src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs delete mode 100644 src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.stderr create mode 100644 src/test/ui/traits/suggest-fully-qualified-path-without-adjustment.rs create mode 100644 src/test/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr 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 19b2ea08e5f8a..779735ed444af 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 @@ -1,21 +1,22 @@ use crate::infer::type_variable::TypeVariableOriginKind; -use crate::infer::{InferCtxt, Symbol}; -use rustc_errors::{ - pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, -}; +use crate::infer::InferCtxt; +use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Namespace}; +use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, MatchSource, Pat}; +use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, LocalSource}; use rustc_middle::hir::nested_filter; use rustc_middle::infer::unify_key::ConstVariableOriginKind; -use rustc_middle::ty::print::Print; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, Const, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder}; -use rustc_span::symbol::kw; -use rustc_span::{sym, Span}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; +use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, InferConst}; +use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_span::symbol::{kw, Ident}; +use rustc_span::{BytePos, Span}; use std::borrow::Cow; +use std::iter; pub enum TypeAnnotationNeeded { /// ```compile_fail,E0282 @@ -54,9 +55,8 @@ pub struct InferenceDiagnosticsData { /// Data on the parent definition where a generic argument was declared. pub struct InferenceDiagnosticsParentData { - pub prefix: &'static str, - pub name: String, - pub def_id: DefId, + prefix: &'static str, + name: String, } pub enum UnderspecifiedArgKind { @@ -81,6 +81,18 @@ impl InferenceDiagnosticsData { // For example: "cannot infer type for type parameter `T`" format!("cannot infer {} `{}`{}", self.kind.prefix_string(), self.name, suffix) } + + fn where_x_is_specified(&self, in_type: Ty<'_>) -> String { + if in_type.is_ty_infer() { + String::new() + } else if self.name == "_" { + // FIXME: Consider specializing this message if there is a single `_` + // in the type. + ", where the placeholders `_` are specified".to_string() + } else { + format!(", where the {} `{}` is specified", self.kind.prefix_string(), self.name) + } + } } impl InferenceDiagnosticsParentData { @@ -94,7 +106,6 @@ impl InferenceDiagnosticsParentData { Some(InferenceDiagnosticsParentData { prefix: tcx.def_kind(parent_def_id).descr(parent_def_id), name: parent_name, - def_id: parent_def_id, }) } @@ -117,6 +128,80 @@ impl UnderspecifiedArgKind { } } +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| { + if infcx.probe_ty_var(ty_vid).is_ok() { + warn!("resolved ty var in error message"); + } + if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = + infcx.inner.borrow_mut().type_variables().var_origin(ty_vid).kind + { + Some(name.to_string()) + } else { + None + } + }; + printer.ty_infer_name_resolver = Some(Box::new(ty_getter)); + let const_getter = move |ct_vid| { + if infcx.probe_const_var(ct_vid).is_ok() { + warn!("resolved const var in error message"); + } + if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = + infcx.inner.borrow_mut().const_unification_table().probe_value(ct_vid).origin.kind + { + return Some(name.to_string()); + } else { + None + } + }; + printer.const_infer_name_resolver = Some(Box::new(const_getter)); + printer +} + +fn ty_to_string<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String { + let printer = fmt_printer(infcx, Namespace::TypeNS); + let ty = infcx.resolve_vars_if_possible(ty); + match ty.kind() { + // 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. + ty::FnDef(..) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(), + // 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(printer).unwrap().into_buffer(), + } +} + +/// We don't want to directly use `ty_to_string` for closures as their type isn't really +/// something users are familar with. Directly printing the `fn_sig` of closures also +/// doesn't work as they actually use the "rust-call" API. +fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String { + let ty::Closure(_, substs) = ty.kind() else { unreachable!() }; + let fn_sig = substs.as_closure().sig(); + let args = fn_sig + .inputs() + .skip_binder() + .iter() + .next() + .map(|args| { + args.tuple_fields() + .iter() + .map(|arg| ty_to_string(infcx, arg)) + .collect::>() + .join(", ") + }) + .unwrap_or_default(); + let ret = if fn_sig.output().skip_binder().is_unit() { + String::new() + } else { + format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder())) + }; + format!("fn({}){}", args, ret) +} + impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Extracts data used by diagnostic for either types or constants /// which were stuck during inference. @@ -153,9 +238,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Some(highlight) = highlight { printer.region_highlight_mode = highlight; } - let name = ty.print(printer).unwrap().into_buffer(); InferenceDiagnosticsData { - name, + name: ty.print(printer).unwrap().into_buffer(), span: None, kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) }, parent: None, @@ -177,8 +261,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } debug_assert!(!origin.span.is_dummy()); - let mut printer = - ty::print::FmtPrinter::new(self.tcx, Namespace::ValueNS); + let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::ValueNS); if let Some(highlight) = highlight { printer.region_highlight_mode = highlight; } @@ -189,7 +272,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { parent: None, } } else { - bug!("unexpect const: {:?}", ct); + // FIXME: This code seems a bit wrong, idk. + let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::ValueNS); + if let Some(highlight) = highlight { + printer.region_highlight_mode = highlight; + } + InferenceDiagnosticsData { + name: ct.print(printer).unwrap().into_buffer(), + span: None, + kind: UnderspecifiedArgKind::Const { is_parameter: false }, + parent: None, + } } } GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), @@ -201,17 +294,160 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { body_id: Option, span: Span, arg: GenericArg<'tcx>, - impl_candidates: Vec>, + // FIXME(#94483): Either use this or remove it. + _impl_candidates: Vec>, error_code: TypeAnnotationNeeded, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let arg = self.resolve_vars_if_possible(arg); + let arg_data = self.extract_inference_diagnostics_data(arg, None); + + let mut local_visitor = FindInferSourceVisitor::new(&self, arg); + if let Some(body_id) = body_id { + let expr = self.tcx.hir().expect_expr(body_id.hir_id); + debug!(?expr); + local_visitor.visit_expr(expr); + } + + let Some(InferSource { span, kind }) = local_visitor.infer_source else { + let error_code = error_code.into(); + let mut err = self.tcx.sess.struct_span_err_with_code( + span, + &format!("type annotations needed"), + error_code, + ); + err.span_label( + span, + arg_data.cannot_infer_msg(), + ); + return err; + }; let error_code = error_code.into(); - let err = self.tcx.sess.struct_span_err_with_code( + let mut err = self.tcx.sess.struct_span_err_with_code( span, - &format!("type annotations needed"), + &format!("type annotations needed{}", kind.ty_msg(self)), error_code, ); + match kind { + InferSourceKind::LetBinding { insert_span, pattern_name, ty } => { + let suggestion_msg = if let Some(name) = pattern_name { + format!( + "consider giving `{}` an explicit type{}", + name, + arg_data.where_x_is_specified(ty) + ) + } else { + format!( + "consider giving this pattern a type{}", + arg_data.where_x_is_specified(ty) + ) + }; + err.span_suggestion_verbose( + insert_span, + &suggestion_msg, + format!(": {}", ty_to_string(self, ty)), + Applicability::HasPlaceholders, + ); + } + InferSourceKind::ClosureArg { insert_span, ty } => { + err.span_suggestion_verbose( + insert_span, + &format!( + "consider giving this closure parameter an explicit type{}", + arg_data.where_x_is_specified(ty) + ), + format!(": {}", ty_to_string(self, ty)), + Applicability::HasPlaceholders, + ); + } + InferSourceKind::GenericArg { + insert_span, + argument_index, + generics_def_id, + def_id: _, + generic_args, + } => { + let generics = self.tcx.generics_of(generics_def_id); + let is_type = matches!(arg.unpack(), GenericArgKind::Type(_)); + + let cannot_infer_msg = format!( + "cannot infer {} of the {} parameter `{}`{}", + if is_type { "type" } else { "the value" }, + if is_type { "type" } else { "const" }, + generics.params[argument_index].name, + // We use the `generics_def_id` here, as even when suggesting `None::`, + // the type parameter `T` was still declared on the enum, not on the + // variant. + InferenceDiagnosticsParentData::for_parent_def_id(self.tcx, generics_def_id) + .map_or(String::new(), |parent| parent.suffix_string()), + ); + + err.span_label(span, cannot_infer_msg); + + let printer = fmt_printer(self, Namespace::TypeNS); + let args = printer.comma_sep(generic_args.iter().copied()).unwrap().into_buffer(); + err.span_suggestion_verbose( + insert_span, + &format!("consider specifying the generic argument{}", pluralize!(args.len()),), + format!("::<{}>", args), + Applicability::HasPlaceholders, + ); + } + InferSourceKind::FullyQualifiedMethodCall { receiver, successor, substs, def_id } => { + let typeck_results = self.in_progress_typeck_results.unwrap(); + let typeck_results = typeck_results.borrow(); + let printer = fmt_printer(self, Namespace::ValueNS); + let def_path = printer.print_def_path(def_id, substs).unwrap().into_buffer(); + + // We only care about whether we have to add `&` or `&mut ` for now. + // This is the case if the last adjustment is a borrow and the + // first adjustment was not a builtin deref. + let adjustment = match typeck_results.expr_adjustments(receiver) { + [ + Adjustment { kind: Adjust::Deref(None), target: _ }, + .., + Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ }, + ] => "", + [ + .., + Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mut_)), target: _ }, + ] => match mut_ { + AutoBorrowMutability::Mut { .. } => "&mut ", + AutoBorrowMutability::Not => "&", + }, + _ => "", + }; + + let suggestion = vec![ + (receiver.span.shrink_to_lo(), format!("{def_path}({adjustment}")), + (receiver.span.shrink_to_hi().with_hi(successor.1), successor.0.to_string()), + ]; + err.multipart_suggestion( + "try using a fully qualified path to specify the expected types", + suggestion, + Applicability::HasPlaceholders, + ); + } + InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => { + let ret = ty_to_string(self, ty); + let (arrow, post) = match data { + FnRetTy::DefaultReturn(_) => ("-> ", " "), + _ => ("", ""), + }; + let suggestion = match should_wrap_expr { + Some(end_span) => vec![ + (data.span(), format!("{}{}{}{{ ", arrow, ret, post)), + (end_span, " }".to_string()), + ], + None => vec![(data.span(), format!("{}{}{}", arrow, ret, post))], + }; + err.multipart_suggestion( + "try giving this closure an explicit return type", + suggestion, + Applicability::HasPlaceholders, + ); + } + } err } @@ -235,3 +471,550 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } } + +#[derive(Debug)] +struct InferSource<'tcx> { + span: Span, + kind: InferSourceKind<'tcx>, +} + +#[derive(Debug)] +enum InferSourceKind<'tcx> { + LetBinding { + insert_span: Span, + pattern_name: Option, + ty: Ty<'tcx>, + }, + ClosureArg { + insert_span: Span, + ty: Ty<'tcx>, + }, + GenericArg { + insert_span: Span, + argument_index: usize, + generics_def_id: DefId, + def_id: DefId, + generic_args: &'tcx [GenericArg<'tcx>], + }, + FullyQualifiedMethodCall { + receiver: &'tcx Expr<'tcx>, + /// If the method has other arguments, this is ", " and the start of the first argument, + /// while for methods without arguments this is ")" and the end of the method call. + successor: (&'static str, BytePos), + substs: SubstsRef<'tcx>, + def_id: DefId, + }, + ClosureReturn { + ty: Ty<'tcx>, + data: &'tcx FnRetTy<'tcx>, + should_wrap_expr: Option, + }, +} + +impl<'tcx> InferSourceKind<'tcx> { + fn ty_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> String { + match *self { + InferSourceKind::LetBinding { ty, .. } + | InferSourceKind::ClosureArg { ty, .. } + | InferSourceKind::ClosureReturn { ty, .. } => { + if ty.is_closure() { + format!(" for the closure `{}`", closure_as_fn_str(infcx, ty)) + } else if !ty.is_ty_infer() { + format!(" for `{}`", ty_to_string(infcx, ty)) + } else { + String::new() + } + } + // FIXME: We should be able to add some additional info here. + InferSourceKind::GenericArg { .. } + | InferSourceKind::FullyQualifiedMethodCall { .. } => String::new(), + } + } +} + +struct InsertableGenericArgs<'tcx> { + insert_span: Span, + substs: SubstsRef<'tcx>, + generics_def_id: DefId, + def_id: DefId, +} + +/// A visitor which searches for the "best" spot to use in the inference error. +/// +/// For this it walks over the hir body and tries to check all places where +/// inference variables could be bound. +/// +/// While doing so, the currently best spot is stored in `infer_source`. +/// For details on how we rank spots, see [Self::source_cost] +struct FindInferSourceVisitor<'a, 'tcx> { + infcx: &'a InferCtxt<'a, 'tcx>, + target: GenericArg<'tcx>, + + attempt: usize, + infer_source_cost: usize, + infer_source: Option>, +} + +impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { + fn new(infcx: &'a InferCtxt<'a, 'tcx>, target: GenericArg<'tcx>) -> Self { + FindInferSourceVisitor { + infcx, + target, + + attempt: 0, + infer_source_cost: usize::MAX, + infer_source: None, + } + } + + /// Computes cost for the given source. + /// + /// Sources with a small cost are prefer and should result + /// in a clearer and idiomatic suggestion. + fn source_cost(&self, source: &InferSource<'tcx>) -> usize { + let tcx = self.infcx.tcx; + + fn arg_cost<'tcx>(arg: GenericArg<'tcx>) -> usize { + match arg.unpack() { + GenericArgKind::Lifetime(_) => 0, // erased + GenericArgKind::Type(ty) => ty_cost(ty), + GenericArgKind::Const(_) => 3, // some non-zero value + } + } + fn ty_cost<'tcx>(ty: Ty<'tcx>) -> usize { + match ty.kind() { + ty::Closure(..) => 100, + ty::FnDef(..) => 20, + ty::FnPtr(..) => 10, + ty::Infer(..) => 0, + _ => 1, + } + } + + // The sources are listed in order of preference here. + match source.kind { + InferSourceKind::LetBinding { ty, .. } => ty_cost(ty), + InferSourceKind::ClosureArg { ty, .. } => 5 + ty_cost(ty), + InferSourceKind::GenericArg { def_id, generic_args, .. } => { + let variant_cost = match tcx.def_kind(def_id) { + DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15, // `None::` and friends are ugly. + _ => 12, + }; + variant_cost + generic_args.iter().map(|&arg| arg_cost(arg)).sum::() + } + InferSourceKind::FullyQualifiedMethodCall { substs, .. } => { + // FIXME: We should also consider the cost of lifetimes and constants here. + 20 + substs.iter().map(|arg| arg_cost(arg)).sum::() + } + InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => { + 30 + ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 } + } + } + } + + /// 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>) { + let cost = self.source_cost(&new_source) + self.attempt; + self.attempt += 1; + if cost < self.infer_source_cost { + self.infer_source_cost = cost; + self.infer_source = Some(new_source); + } + } + + fn opt_node_type(&self, hir_id: HirId) -> Option> { + let ty = self.infcx.in_progress_typeck_results?.borrow().node_type_opt(hir_id); + self.infcx.resolve_vars_if_possible(ty) + } + + // Check whether this generic argument is the inference variable we + // are looking for. + fn generic_arg_is_target(&self, arg: GenericArg<'tcx>) -> bool { + if arg == self.target { + return true; + } + + match (arg.unpack(), self.target.unpack()) { + (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => { + use ty::{Infer, TyVar}; + match (inner_ty.kind(), target_ty.kind()) { + (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => { + self.infcx.inner.borrow_mut().type_variables().sub_unified(a_vid, b_vid) + } + _ => false, + } + } + (GenericArgKind::Const(inner_ct), GenericArgKind::Const(target_ct)) => { + use ty::InferConst::*; + match (inner_ct.val(), target_ct.val()) { + (ty::ConstKind::Infer(Var(a_vid)), ty::ConstKind::Infer(Var(b_vid))) => self + .infcx + .inner + .borrow_mut() + .const_unification_table() + .unioned(a_vid, b_vid), + _ => false, + } + } + _ => false, + } + } + + /// Does this generic argument contain our target inference variable + /// in a way which can be written by the user. + fn generic_arg_contains_target(&self, arg: GenericArg<'tcx>) -> bool { + let mut walker = arg.walk(); + while let Some(inner) = walker.next() { + if self.generic_arg_is_target(inner) { + return true; + } + match inner.unpack() { + GenericArgKind::Lifetime(_) => {} + GenericArgKind::Type(ty) => { + if matches!(ty.kind(), ty::Opaque(..)) { + // Opaque types can't be named by the user right now + // FIXME(type_alias_impl_trait): These opaque types + // can actually be named, so it would make sense to + // adjust this case and add a test for it. + walker.skip_current_subtree(); + } + } + GenericArgKind::Const(ct) => { + if matches!(ct.val(), ty::ConstKind::Unevaluated(..)) { + // You can't write the generic arguments for + // unevaluated constants. + walker.skip_current_subtree(); + } + } + } + } + false + } + + fn expr_inferred_subst_iter( + &self, + expr: &'tcx hir::Expr<'tcx>, + ) -> Box> + 'a> { + let tcx = self.infcx.tcx; + let typeck_results = self.infcx.in_progress_typeck_results.unwrap().borrow(); + match expr.kind { + hir::ExprKind::Path(ref path) => { + if let Some(substs) = typeck_results.node_substs_opt(expr.hir_id) { + return self.path_inferred_subst_iter(expr.hir_id, substs, path); + } + } + hir::ExprKind::Struct(path, _, _) => { + if let Some(ty) = self.opt_node_type(expr.hir_id) { + if let ty::Adt(_, substs) = ty.kind() { + return self.path_inferred_subst_iter(expr.hir_id, substs, path); + } + } + } + hir::ExprKind::MethodCall(segment, _, _) => { + if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) { + let generics = tcx.generics_of(def_id); + let insertable: Option<_> = try { + if generics.has_impl_trait() { + None? + } + let substs = typeck_results.node_substs_opt(expr.hir_id)?; + let span = tcx.hir().span(segment.hir_id?); + let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); + InsertableGenericArgs { + insert_span, + substs, + generics_def_id: def_id, + def_id, + } + }; + return Box::new(insertable.into_iter()); + } + } + _ => {} + } + + Box::new(iter::empty()) + } + + fn resolved_path_inferred_subst_iter( + &self, + path: &'tcx hir::Path<'tcx>, + substs: SubstsRef<'tcx>, + ) -> impl Iterator> + 'a { + let tcx = self.infcx.tcx; + // The last segment of a path often has `Res::Err` and the + // correct `Res` is the one of the whole path. + // + // FIXME: We deal with that one separately for now, + // would be good to remove this special case. + let last_segment_using_path_data: Option<_> = try { + let generics_def_id = tcx.res_generics_def_id(path.res)?; + let generics = tcx.generics_of(generics_def_id); + if generics.has_impl_trait() { + None? + } + let insert_span = + path.segments.last().unwrap().ident.span.shrink_to_hi().with_hi(path.span.hi()); + InsertableGenericArgs { + insert_span, + substs, + generics_def_id, + def_id: path.res.def_id(), + } + }; + + path.segments + .iter() + .filter_map(move |segment| { + let res = segment.res?; + let generics_def_id = tcx.res_generics_def_id(res)?; + let generics = tcx.generics_of(generics_def_id); + if generics.has_impl_trait() { + return None; + } + let span = tcx.hir().span(segment.hir_id?); + let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); + Some(InsertableGenericArgs { + insert_span, + substs, + generics_def_id, + def_id: res.def_id(), + }) + }) + .chain(last_segment_using_path_data) + } + + fn path_inferred_subst_iter( + &self, + hir_id: HirId, + substs: SubstsRef<'tcx>, + qpath: &'tcx hir::QPath<'tcx>, + ) -> Box> + 'a> { + let tcx = self.infcx.tcx; + let typeck_results = self.infcx.in_progress_typeck_results.unwrap().borrow(); + match qpath { + hir::QPath::Resolved(_self_ty, path) => { + Box::new(self.resolved_path_inferred_subst_iter(path, substs)) + } + hir::QPath::TypeRelative(ty, segment) => { + let Some(def_id) = typeck_results.type_dependent_def_id(hir_id) else { + return Box::new(iter::empty()); + }; + + let generics = tcx.generics_of(def_id); + let segment: Option<_> = try { + if !segment.infer_args || generics.has_impl_trait() { + None?; + } + let span = tcx.hir().span(segment.hir_id?); + let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); + InsertableGenericArgs { insert_span, substs, generics_def_id: def_id, def_id } + }; + + let parent_def_id = generics.parent.unwrap(); + if tcx.def_kind(parent_def_id) == DefKind::Impl { + let parent_ty = tcx.bound_type_of(parent_def_id).subst(tcx, substs); + match (parent_ty.kind(), &ty.kind) { + ( + ty::Adt(def, substs), + hir::TyKind::Path(hir::QPath::Resolved(_self_ty, path)), + ) => { + if tcx.res_generics_def_id(path.res) != Some(def.did()) { + bug!( + "unexpected path: def={:?} substs={:?} path={:?}", + def, + substs, + path, + ); + } else { + return Box::new( + self.resolved_path_inferred_subst_iter(path, substs) + .chain(segment), + ); + } + } + _ => (), + } + } + + Box::new(segment.into_iter()) + } + hir::QPath::LangItem(_, _, _) => Box::new(iter::empty()), + } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { + type NestedFilter = nested_filter::OnlyBodies; + + fn nested_visit_map(&mut self) -> Self::Map { + self.infcx.tcx.hir() + } + + fn visit_local(&mut self, local: &'tcx Local<'tcx>) { + intravisit::walk_local(self, local); + + if let Some(ty) = self.opt_node_type(local.hir_id) { + if self.generic_arg_contains_target(ty.into()) { + match local.source { + LocalSource::Normal if local.ty.is_none() => { + self.update_infer_source(InferSource { + span: local.pat.span, + kind: InferSourceKind::LetBinding { + insert_span: local.pat.span.shrink_to_hi(), + pattern_name: local.pat.simple_ident(), + ty, + }, + }) + } + _ => {} + } + } + } + } + + /// For closures, we first visit the parameters and then the content, + /// as we prefer those. + fn visit_body(&mut self, body: &'tcx Body<'tcx>) { + for param in body.params { + debug!( + "param: span {:?}, ty_span {:?}, pat.span {:?}", + param.span, param.ty_span, param.pat.span + ); + if param.ty_span != param.pat.span { + debug!("skipping param: has explicit type"); + continue; + } + + let Some(param_ty) = self.opt_node_type(param.hir_id) else { + continue + }; + + if self.generic_arg_contains_target(param_ty.into()) { + self.update_infer_source(InferSource { + span: param.pat.span, + kind: InferSourceKind::ClosureArg { + insert_span: param.pat.span.shrink_to_hi(), + ty: param_ty, + }, + }) + } + } + intravisit::walk_body(self, body); + } + + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { + let tcx = self.infcx.tcx; + match expr.kind { + // When encountering `func(arg)` first look into `arg` and then `func`, + // as `arg` is "more specific". + ExprKind::Call(func, args) => { + for arg in args { + self.visit_expr(arg); + } + self.visit_expr(func); + } + _ => intravisit::walk_expr(self, expr), + } + + for InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } in + self.expr_inferred_subst_iter(expr) + { + let generics = tcx.generics_of(generics_def_id); + if let Some(argument_index) = + generics.own_substs(substs).iter().position(|&arg| self.generic_arg_is_target(arg)) + { + let substs = self.infcx.resolve_vars_if_possible(substs); + let num_args = generics + .params + .iter() + .rev() + .filter(|&p| !matches!(p.kind, GenericParamDefKind::Lifetime)) + .skip_while(|¶m| { + if let Some(default) = param.default_value(tcx) { + // FIXME: Using structural comparisions has a bunch of false negatives. + // + // We should instead try to replace inference variables with placeholders and + // then use `infcx.can_eq`. That probably should be a separate method + // generally used during error reporting. + default.subst(tcx, substs) == substs[param.index as usize] + } else { + false + } + }) + .count(); + let generic_args = + &generics.own_substs(substs)[generics.own_counts().lifetimes..][..num_args]; + let span = match expr.kind { + ExprKind::MethodCall(path, _, _) => path.ident.span, + _ => expr.span, + }; + + self.update_infer_source(InferSource { + span, + kind: InferSourceKind::GenericArg { + insert_span, + argument_index, + generics_def_id, + def_id, + generic_args, + }, + }); + } + } + + if let Some(node_ty) = self.opt_node_type(expr.hir_id) { + if let (&ExprKind::Closure(_, decl, body_id, span, _), ty::Closure(_, substs)) = + (&expr.kind, node_ty.kind()) + { + let output = substs.as_closure().sig().output().skip_binder(); + if self.generic_arg_contains_target(output.into()) { + let body = self.infcx.tcx.hir().body(body_id); + let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) { + None + } else { + Some(body.value.span.shrink_to_hi()) + }; + self.update_infer_source(InferSource { + span, + kind: InferSourceKind::ClosureReturn { + ty: output, + data: &decl.output, + should_wrap_expr, + }, + }) + } + } + } + + let has_impl_trait = |def_id| { + iter::successors(Some(tcx.generics_of(def_id)), |generics| { + generics.parent.map(|def_id| tcx.generics_of(def_id)) + }) + .any(|generics| generics.has_impl_trait()) + }; + if let ExprKind::MethodCall(path, args, span) = expr.kind + && let Some(typeck_results) = self.infcx.in_progress_typeck_results + && let Some(substs) = typeck_results.borrow().node_substs_opt(expr.hir_id) + && substs.iter().any(|arg| self.generic_arg_contains_target(arg)) + && let Some(def_id) = typeck_results.borrow().type_dependent_def_id(expr.hir_id) + && self.infcx.tcx.trait_of_item(def_id).is_some() + && !has_impl_trait(def_id) + { + let successor = + args.get(1).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo())); + let substs = self.infcx.resolve_vars_if_possible(substs); + self.update_infer_source(InferSource { + span: path.ident.span, + kind: InferSourceKind::FullyQualifiedMethodCall { + receiver: args.first().unwrap(), + successor, + substs, + def_id, + } + }) + } + } +} diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 0f13a9b138800..7769a68ba2a66 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -22,6 +22,7 @@ #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(try_blocks)] #![recursion_limit = "512"] // For rustdoc #[macro_use] diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 97f429cfd3fa6..7a1bdd6beca18 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -983,7 +983,11 @@ impl<'hir> Map<'hir> { Node::AnonConst(constant) => self.body(constant.body).value.span, Node::Expr(expr) => expr.span, Node::Stmt(stmt) => stmt.span, - Node::PathSegment(seg) => seg.ident.span, + Node::PathSegment(seg) => { + let ident_span = seg.ident.span; + ident_span + .with_hi(seg.args.map_or_else(|| ident_span.hi(), |args| args.span_ext.hi())) + } Node::Ty(ty) => ty.span, Node::TraitRef(tr) => tr.path.span, Node::Binding(pat) => pat.span, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index d9b82ee0a7680..1feabb2d6b122 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -63,6 +63,29 @@ impl GenericParamDef { bug!("cannot convert a non-lifetime parameter def to an early bound region") } } + + pub fn has_default(&self) -> bool { + match self.kind { + GenericParamDefKind::Type { has_default, .. } + | GenericParamDefKind::Const { has_default } => has_default, + GenericParamDefKind::Lifetime => false, + } + } + + pub fn default_value<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + ) -> Option>> { + match self.kind { + GenericParamDefKind::Type { has_default, .. } if has_default => { + Some(EarlyBinder(tcx.type_of(self.def_id).into())) + } + GenericParamDefKind::Const { has_default } if has_default => { + Some(EarlyBinder(tcx.const_param_default(self.def_id).into())) + } + _ => None, + } + } } #[derive(Default)] @@ -204,6 +227,12 @@ impl<'tcx> Generics { matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }) }) } + + /// Returns the substs corresponding to the generic parameters of this item, excluding `Self`. + pub fn own_substs(&'tcx self, substs: SubstsRef<'tcx>) -> &'tcx [ty::GenericArg<'tcx>] { + let own = &substs[self.parent_count..][..self.params.len()]; + if self.has_self && self.parent.is_none() { &own[1..] } else { &own } + } } /// Bounds on generics. 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 6eed4ce4f0c01..8da6d97251ba1 100644 --- a/src/test/ui/array-slice-vec/infer_array_len.stderr +++ b/src/test/ui/array-slice-vec/infer_array_len.stderr @@ -2,9 +2,13 @@ error[E0282]: type annotations needed --> $DIR/infer_array_len.rs:19:9 | LL | let [_, _] = a.into(); - | ^^^^^^ consider giving this pattern a type + | ^^^^^^ | = note: type must be known at this point +help: consider giving this pattern a type + | +LL | let [_, _]: _ = a.into(); + | +++ error: aborting due to previous error diff --git a/src/test/ui/array-slice-vec/vector-no-ann.stderr b/src/test/ui/array-slice-vec/vector-no-ann.stderr index 8a7b8d22760a2..d2ea08aa47430 100644 --- a/src/test/ui/array-slice-vec/vector-no-ann.stderr +++ b/src/test/ui/array-slice-vec/vector-no-ann.stderr @@ -1,10 +1,13 @@ error[E0282]: type annotations needed for `Vec` - --> $DIR/vector-no-ann.rs:2:16 + --> $DIR/vector-no-ann.rs:2:9 | LL | let _foo = Vec::new(); - | ---- ^^^^^^^^ cannot infer type for type parameter `T` - | | - | consider giving `_foo` the explicit type `Vec`, where the type parameter `T` is specified + | ^^^^ + | +help: consider giving `_foo` an explicit type, where the type for type parameter `T` is specified + | +LL | let _foo: Vec = Vec::new(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr index 2005bd4dd5ca7..db7586bee4953 100644 --- a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr +++ b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27 | LL | with_closure(|x: u32, y| {}); - | ^ consider giving this closure parameter a type + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | with_closure(|x: u32, y: B| {}); + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr index 54825cb746d42..38d9d08ce36ab 100644 --- a/src/test/ui/closures/issue-52437.stderr +++ b/src/test/ui/closures/issue-52437.stderr @@ -8,7 +8,12 @@ error[E0282]: type annotations needed --> $DIR/issue-52437.rs:2:30 | LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] - | ^ consider giving this closure parameter a type + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | [(); &(&'static: loop { |x: _| {}; }) as *const _ as usize] + | +++ error[E0308]: mismatched types --> $DIR/issue-52437.rs:2:5 diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index cccf433e32864..227b2f4022365 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -1,10 +1,13 @@ error[E0282]: type annotations needed for `Foo` - --> $DIR/doesnt_infer.rs:11:15 + --> $DIR/doesnt_infer.rs:11:9 | LL | let foo = Foo::foo(); - | --- ^^^^^^^^ cannot infer the value of const parameter `N` - | | - | consider giving `foo` the explicit type `Foo`, where the const parameter `N` is specified + | ^^^ + | +help: consider giving `foo` an explicit type, where the the value of const parameter `N` is specified + | +LL | let foo: Foo = Foo::foo(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr index 347cd2364b266..463605e2431d6 100644 --- a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -1,10 +1,8 @@ error[E0283]: type annotations needed for `Mask<_, LANES>` - --> $DIR/issue-91614.rs:6:13 + --> $DIR/issue-91614.rs:6:9 | LL | let y = Mask::<_, _>::splat(false); - | - ^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` - | | - | consider giving `y` the explicit type `Mask<_, LANES>`, where the type parameter `T` is specified + | ^ | = note: cannot satisfy `_: MaskElement` note: required by a bound in `Mask::::splat` @@ -12,6 +10,10 @@ note: required by a bound in `Mask::::splat` | LL | T: MaskElement, | ^^^^^^^^^^^ required by this bound in `Mask::::splat` +help: consider giving `y` an explicit type, where the type for type parameter `T` is specified + | +LL | let y: Mask<_, LANES> = Mask::<_, _>::splat(false); + | ++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr index e59f1ac8027de..9e8328d37017e 100644 --- a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.stderr @@ -2,13 +2,18 @@ error[E0282]: type annotations needed --> $DIR/const_eval_resolve_canonical.rs:26:9 | LL | let mut _q = Default::default(); - | ^^^^^^ consider giving `_q` a type + | ^^^^^^ + | +help: consider giving `_q` an explicit type + | +LL | let mut _q: _ = Default::default(); + | +++ error[E0283]: type annotations needed --> $DIR/const_eval_resolve_canonical.rs:29:10 | LL | _q = foo::<_, 2>(_q); - | ^^^^^^^^^^^ cannot infer type + | ^^^^^^^^^^^ cannot infer the value of the constant `{ N + 1 }` | note: multiple `impl`s satisfying `(): Foo<{ N + 1 }>` found --> $DIR/const_eval_resolve_canonical.rs:8:1 diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.stderr index 828f497240395..93e45a88a6c20 100644 --- a/src/test/ui/const-generics/infer/cannot-infer-const-args.stderr +++ b/src/test/ui/const-generics/infer/cannot-infer-const-args.stderr @@ -2,12 +2,12 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:6:5 | LL | foo(); - | ^^^ cannot infer the value of const parameter `X` declared on the function `foo` + | ^^^ cannot infer the value of the const parameter `X` declared on the function `foo` | -help: consider specifying the const argument +help: consider specifying the generic argument | LL | foo::(); - | ~~~~~~~~ + | +++++ error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/issue-77092.stderr b/src/test/ui/const-generics/infer/issue-77092.stderr index a625ed2bdc3b2..1682b26ac8777 100644 --- a/src/test/ui/const-generics/infer/issue-77092.stderr +++ b/src/test/ui/const-generics/infer/issue-77092.stderr @@ -2,12 +2,12 @@ error[E0282]: type annotations needed --> $DIR/issue-77092.rs:11:26 | LL | println!("{:?}", take_array_from_mut(&mut arr, i)); - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `take_array_from_mut` + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `take_array_from_mut` | -help: consider specifying the const argument +help: consider specifying the generic arguments | -LL | println!("{:?}", take_array_from_mut::(&mut arr, i)); - | ~~~~~~~~~~~~~~~~~~~~~~~~ +LL | println!("{:?}", take_array_from_mut::(&mut arr, i)); + | ++++++++++ error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/method-chain.stderr b/src/test/ui/const-generics/infer/method-chain.stderr index 53d92e5ae725d..ff6da535bd264 100644 --- a/src/test/ui/const-generics/infer/method-chain.stderr +++ b/src/test/ui/const-generics/infer/method-chain.stderr @@ -2,12 +2,12 @@ error[E0282]: type annotations needed --> $DIR/method-chain.rs:15:33 | LL | Foo.bar().bar().bar().bar().baz(); - | ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz` + | ^^^ cannot infer the value of the const parameter `N` declared on the associated function `baz` | -help: consider specifying the const argument +help: consider specifying the generic argument | LL | Foo.bar().bar().bar().bar().baz::(); - | ~~~~~~~~ + | +++++ error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/one-param-uninferred.stderr b/src/test/ui/const-generics/infer/one-param-uninferred.stderr index acf59170c369e..98ea8df825265 100644 --- a/src/test/ui/const-generics/infer/one-param-uninferred.stderr +++ b/src/test/ui/const-generics/infer/one-param-uninferred.stderr @@ -2,12 +2,12 @@ error[E0282]: type annotations needed --> $DIR/one-param-uninferred.rs:9:23 | LL | let _: [u8; 17] = foo(); - | ^^^ cannot infer the value of const parameter `M` declared on the function `foo` + | ^^^ cannot infer the value of the const parameter `M` declared on the function `foo` | -help: consider specifying the const argument +help: consider specifying the generic arguments | -LL | let _: [u8; 17] = foo::(); - | ~~~~~~~~ +LL | let _: [u8; 17] = foo::<17_usize, M>(); + | +++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/const-generics/infer/uninferred-consts.stderr b/src/test/ui/const-generics/infer/uninferred-consts.stderr index a6c79fc058a43..3980ecea86362 100644 --- a/src/test/ui/const-generics/infer/uninferred-consts.stderr +++ b/src/test/ui/const-generics/infer/uninferred-consts.stderr @@ -2,12 +2,12 @@ error[E0282]: type annotations needed --> $DIR/uninferred-consts.rs:9:9 | LL | Foo.foo(); - | ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo` + | ^^^ cannot infer the value of the const parameter `A` declared on the associated function `foo` | -help: consider specifying the const argument +help: consider specifying the generic arguments | -LL | Foo.foo::(); - | ~~~~~~~~ +LL | Foo.foo::(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/const-generics/issues/issue-83249.stderr b/src/test/ui/const-generics/issues/issue-83249.stderr index 3f44a54e80adc..362b8554b2fcb 100644 --- a/src/test/ui/const-generics/issues/issue-83249.stderr +++ b/src/test/ui/const-generics/issues/issue-83249.stderr @@ -1,16 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/issue-83249.rs:19:13 + --> $DIR/issue-83249.rs:19:9 | LL | let _ = foo([0; 1]); - | - ^^^ cannot infer type for type parameter `T` declared on the function `foo` - | | - | consider giving this pattern a type + | ^ | -help: type parameter declared here - --> $DIR/issue-83249.rs:12:8 +help: consider giving this pattern a type | -LL | fn foo(_: [u8; T::N]) -> T { - | ^ +LL | let _: _ = foo([0; 1]); + | +++ error: aborting due to previous error diff --git a/src/test/ui/consts/issue-64662.stderr b/src/test/ui/consts/issue-64662.stderr index caa582d87f527..21a419711a989 100644 --- a/src/test/ui/consts/issue-64662.stderr +++ b/src/test/ui/consts/issue-64662.stderr @@ -2,25 +2,23 @@ error[E0282]: type annotations needed --> $DIR/issue-64662.rs:2:9 | LL | A = foo(), - | ^^^ cannot infer type for type parameter `T` declared on the function `foo` + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` | -help: type parameter declared here - --> $DIR/issue-64662.rs:6:14 +help: consider specifying the generic argument | -LL | const fn foo() -> isize { - | ^ +LL | A = foo::(), + | +++++ error[E0282]: type annotations needed --> $DIR/issue-64662.rs:3:9 | LL | B = foo(), - | ^^^ cannot infer type for type parameter `T` declared on the function `foo` + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` | -help: type parameter declared here - --> $DIR/issue-64662.rs:6:14 +help: consider specifying the generic argument | -LL | const fn foo() -> isize { - | ^ +LL | B = foo::(), + | +++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr index 0f610a5e42f65..d01aa3617c764 100644 --- a/src/test/ui/error-codes/E0282.stderr +++ b/src/test/ui/error-codes/E0282.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/E0282.rs:2:9 | LL | let x = "hello".chars().rev().collect(); - | ^ consider giving `x` a type + | ^ + | +help: consider giving `x` an explicit type + | +LL | let x: _ = "hello".chars().rev().collect(); + | +++ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index e2bab486064f0..a107160d11a35 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -10,10 +10,7 @@ error[E0283]: type annotations needed --> $DIR/E0283.rs:35:24 | LL | let bar = foo_impl.into() * 1u32; - | ---------^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `Into` - | this method call resolves to `T` + | ^^^^ | note: multiple `impl`s satisfying `Impl: Into<_>` found --> $DIR/E0283.rs:17:1 @@ -23,10 +20,10 @@ LL | impl Into for Impl { = note: and another `impl` found in the `core` crate: - impl Into for T where U: From; -help: use the fully qualified path for the potential candidate +help: try using a fully qualified path to specify the expected types | -LL | let bar = >::into(foo_impl) * 1u32; - | ++++++++++++++++++++++++++ ~ +LL | let bar = >::into(foo_impl) * 1u32; + | ++++++++++++++++++++++++ ~ error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr index e58c9d3116a1c..81715621dd921 100644 --- a/src/test/ui/error-codes/E0401.stderr +++ b/src/test/ui/error-codes/E0401.stderr @@ -36,13 +36,12 @@ error[E0282]: type annotations needed --> $DIR/E0401.rs:11:5 | LL | bfnr(x); - | ^^^^ cannot infer type for type parameter `U` declared on the function `bfnr` + | ^^^^ cannot infer type of the type parameter `U` declared on the function `bfnr` | -help: type parameter declared here - --> $DIR/E0401.rs:4:13 +help: consider specifying the generic arguments | -LL | fn bfnr, W: Fn()>(y: T) { - | ^ +LL | bfnr::(x); + | +++++++++++ error: aborting due to 4 previous errors diff --git a/src/test/ui/for/for-loop-unconstrained-element-type.stderr b/src/test/ui/for/for-loop-unconstrained-element-type.stderr index 580b135ac2d71..b1b38f6b9194b 100644 --- a/src/test/ui/for/for-loop-unconstrained-element-type.stderr +++ b/src/test/ui/for/for-loop-unconstrained-element-type.stderr @@ -1,10 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/for-loop-unconstrained-element-type.rs:8:9 + --> $DIR/for-loop-unconstrained-element-type.rs:8:14 | LL | for i in Vec::new() { } - | ^ ---------- the element type for this iterator is not specified - | | - | cannot infer type + | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec` + | +help: consider specifying the generic argument + | +LL | for i in Vec::::new() { } + | +++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-91762.stderr b/src/test/ui/generic-associated-types/issue-91762.stderr index a9c465cdd7ea2..c2785fee387fa 100644 --- a/src/test/ui/generic-associated-types/issue-91762.stderr +++ b/src/test/ui/generic-associated-types/issue-91762.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/issue-91762.rs:25:15 | LL | ret = ::fmap(arg); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the associated function `fmap` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `fmap` + | +help: consider specifying the generic arguments + | +LL | ret = ::fmap::(arg); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/cross-return-site-inference.rs b/src/test/ui/impl-trait/cross-return-site-inference.rs index a7428f9bf129f..d881af9ed8fe1 100644 --- a/src/test/ui/impl-trait/cross-return-site-inference.rs +++ b/src/test/ui/impl-trait/cross-return-site-inference.rs @@ -29,17 +29,17 @@ fn baa(b: bool) -> impl std::fmt::Debug { } fn muh() -> Result<(), impl std::fmt::Debug> { - Err("whoops")?; //~^ ERROR type annotations needed - Ok(()) + Err("whoops")?; + Ok(()) //~ ERROR type annotations needed } fn muh2() -> Result<(), impl std::fmt::Debug> { - return Err(From::from("foo")); //~^ ERROR type annotations needed + return Err(From::from("foo")); //~ ERROR type annotations needed Ok(()) } fn muh3() -> Result<(), impl std::fmt::Debug> { - Err(From::from("foo")) //~^ ERROR type annotations needed + Err(From::from("foo")) //~ ERROR type annotations needed } fn main() {} diff --git a/src/test/ui/impl-trait/cross-return-site-inference.stderr b/src/test/ui/impl-trait/cross-return-site-inference.stderr index 5209d7a574349..1ff777e65037c 100644 --- a/src/test/ui/impl-trait/cross-return-site-inference.stderr +++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr @@ -1,20 +1,35 @@ error[E0282]: type annotations needed - --> $DIR/cross-return-site-inference.rs:31:24 + --> $DIR/cross-return-site-inference.rs:33:5 | -LL | fn muh() -> Result<(), impl std::fmt::Debug> { - | ^^^^^^^^^^^^^^^^^^^^ cannot infer type +LL | Ok(()) + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | +help: consider specifying the generic arguments + | +LL | Ok::<(), E>(()) + | +++++++++ error[E0282]: type annotations needed - --> $DIR/cross-return-site-inference.rs:36:25 + --> $DIR/cross-return-site-inference.rs:37:12 + | +LL | return Err(From::from("foo")); + | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` | -LL | fn muh2() -> Result<(), impl std::fmt::Debug> { - | ^^^^^^^^^^^^^^^^^^^^ cannot infer type +help: consider specifying the generic arguments + | +LL | return Err::<(), E>(From::from("foo")); + | +++++++++ error[E0282]: type annotations needed - --> $DIR/cross-return-site-inference.rs:41:25 + --> $DIR/cross-return-site-inference.rs:42:5 + | +LL | Err(From::from("foo")) + | ^^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | +help: consider specifying the generic arguments | -LL | fn muh3() -> Result<(), impl std::fmt::Debug> { - | ^^^^^^^^^^^^^^^^^^^^ cannot infer type +LL | Err::<(), E>(From::from("foo")) + | +++++++++ error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs b/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs new file mode 100644 index 0000000000000..3a47710d508b5 --- /dev/null +++ b/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.rs @@ -0,0 +1,15 @@ +trait Foo { + fn foo(self, f: impl FnOnce()); +} + +impl Foo for () { + fn foo(self, f: impl FnOnce()) { + f() + } +} + +fn main() { + // FIXME: This should ideally use a fully qualified path + // without mentioning the generic arguments of `foo`. + ().foo(|| ()) //~ ERROR type annotations needed +} diff --git a/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr b/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr new file mode 100644 index 0000000000000..a1a629bddbdea --- /dev/null +++ b/src/test/ui/impl-trait/diagnostics/fully-qualified-path-impl-trait.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/fully-qualified-path-impl-trait.rs:14:8 + | +LL | ().foo(|| ()) + | ^^^ cannot infer type for type parameter `T` declared on the trait `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/impl-trait/fallback_inference.rs b/src/test/ui/impl-trait/fallback_inference.rs index 001f9ee487758..98f0bd1af2813 100644 --- a/src/test/ui/impl-trait/fallback_inference.rs +++ b/src/test/ui/impl-trait/fallback_inference.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; fn weird() -> PhantomData { - PhantomData //~^ ERROR type annotations needed + PhantomData //~ ERROR type annotations needed } fn main() {} diff --git a/src/test/ui/impl-trait/fallback_inference.stderr b/src/test/ui/impl-trait/fallback_inference.stderr index b637ca694c203..4ac3c238fe958 100644 --- a/src/test/ui/impl-trait/fallback_inference.stderr +++ b/src/test/ui/impl-trait/fallback_inference.stderr @@ -1,8 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/fallback_inference.rs:3:27 + --> $DIR/fallback_inference.rs:4:5 | -LL | fn weird() -> PhantomData { - | ^^^^^^^^^^ cannot infer type +LL | PhantomData + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` + | +help: consider specifying the generic argument + | +LL | PhantomData:: + | +++++ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs index 7876add5aa6cb..970d84120e07e 100644 --- a/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs +++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.rs @@ -5,8 +5,8 @@ #![feature(type_alias_impl_trait)] fn reify_as() -> Thunk Continuation> { - Thunk::new(|mut cont| { //~ ERROR type annotations needed - cont.reify_as(); + Thunk::new(|mut cont| { + cont.reify_as(); //~ ERROR type annotations needed cont }) } @@ -14,8 +14,8 @@ fn reify_as() -> Thunk Continuation> { type Tait = impl FnOnce(Continuation) -> Continuation; fn reify_as_tait() -> Thunk { - Thunk::new(|mut cont| { //~ ERROR type annotations needed - cont.reify_as(); + Thunk::new(|mut cont| { + cont.reify_as(); //~ ERROR type annotations needed cont }) } diff --git a/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr index dcf1982312f29..11ba5aa7867fe 100644 --- a/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr +++ b/src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr @@ -1,16 +1,16 @@ error[E0282]: type annotations needed - --> $DIR/hidden-type-is-opaque-2.rs:8:17 + --> $DIR/hidden-type-is-opaque-2.rs:9:9 | -LL | Thunk::new(|mut cont| { - | ^^^^^^^^ consider giving this closure parameter a type +LL | cont.reify_as(); + | ^^^^ cannot infer type | = note: type must be known at this point error[E0282]: type annotations needed - --> $DIR/hidden-type-is-opaque-2.rs:17:17 + --> $DIR/hidden-type-is-opaque-2.rs:18:9 | -LL | Thunk::new(|mut cont| { - | ^^^^^^^^ consider giving this closure parameter a type +LL | cont.reify_as(); + | ^^^^ cannot infer type | = note: type must be known at this point diff --git a/src/test/ui/impl-trait/issues/issue-84073.stderr b/src/test/ui/impl-trait/issues/issue-84073.stderr index 36047d23fedda..3c39aa6ce5bb9 100644 --- a/src/test/ui/impl-trait/issues/issue-84073.stderr +++ b/src/test/ui/impl-trait/issues/issue-84073.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed for `RaceBuilder>` --> $DIR/issue-84073.rs:32:16 | LL | Race::new(|race| race.when()); - | ^^^^ consider giving this closure parameter the explicit type `RaceBuilder>`, where the type parameter `T` is specified + | ^^^^ + | +help: consider giving this closure parameter an explicit type, where the type for type parameter `T` is specified + | +LL | Race::new(|race: RaceBuilder>| race.when()); + | ++++++++++++++++++++++++++ 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 e2abf71c110b9..09047cdcbe15c 100644 --- a/src/test/ui/impl-trait/issues/issue-86719.stderr +++ b/src/test/ui/impl-trait/issues/issue-86719.stderr @@ -16,7 +16,12 @@ error[E0282]: type annotations needed --> $DIR/issue-86719.rs:9:10 | LL | |_| true - | ^ consider giving this closure parameter a type + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | |_: _| true + | +++ error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/issues/issue-92305.stderr b/src/test/ui/impl-trait/issues/issue-92305.stderr index c4fc49225e9a0..e8575b76b0930 100644 --- a/src/test/ui/impl-trait/issues/issue-92305.stderr +++ b/src/test/ui/impl-trait/issues/issue-92305.stderr @@ -18,7 +18,12 @@ error[E0282]: type annotations needed --> $DIR/issue-92305.rs:7:5 | LL | iter::empty() - | ^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the function `empty` + | ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty` + | +help: consider specifying the generic argument + | +LL | iter::empty::() + | +++++ error[E0282]: type annotations needed --> $DIR/issue-92305.rs:10:35 diff --git a/src/test/ui/inference/ambiguous_type_parameter.stderr b/src/test/ui/inference/ambiguous_type_parameter.stderr index 47ef1948aee9f..a08342371b3b5 100644 --- a/src/test/ui/inference/ambiguous_type_parameter.stderr +++ b/src/test/ui/inference/ambiguous_type_parameter.stderr @@ -3,12 +3,6 @@ error[E0282]: type annotations needed | LL | InMemoryStore.get_raw(&String::default()); | ^^^^^^^ cannot infer type for type parameter `K` - | -help: type parameter declared here - --> $DIR/ambiguous_type_parameter.rs:9:6 - | -LL | impl Store> for InMemoryStore { - | ^ error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr index 233604833612a..0579cf238a9da 100644 --- a/src/test/ui/inference/cannot-infer-async.stderr +++ b/src/test/ui/inference/cannot-infer-async.stderr @@ -1,11 +1,13 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-async.rs:13:9 | -LL | let fut = async { - | --- consider giving `fut` a type -... LL | Ok(()) - | ^^ cannot infer type for type parameter `E` declared on the enum `Result` + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` + | +help: consider specifying the generic arguments + | +LL | Ok::<(), E>(()) + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-closure-circular.rs b/src/test/ui/inference/cannot-infer-closure-circular.rs index a3b957179b1b1..affb481496d02 100644 --- a/src/test/ui/inference/cannot-infer-closure-circular.rs +++ b/src/test/ui/inference/cannot-infer-closure-circular.rs @@ -4,8 +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 + let x = |r| { //~ ERROR type annotations needed for `Result<(), E>` let v = r?; Ok(v) }; diff --git a/src/test/ui/inference/cannot-infer-closure-circular.stderr b/src/test/ui/inference/cannot-infer-closure-circular.stderr index a6ddb7ae908fc..b706cd2bc36e8 100644 --- a/src/test/ui/inference/cannot-infer-closure-circular.stderr +++ b/src/test/ui/inference/cannot-infer-closure-circular.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed for `Result<(), E>` --> $DIR/cannot-infer-closure-circular.rs:7:14 | LL | let x = |r| { - | ^ consider giving this closure parameter the explicit type `Result<(), E>`, where the type parameter `E` is specified + | ^ + | +help: consider giving this closure parameter an explicit type, where the type for type parameter `E` is specified + | +LL | let x = |r: Result<(), E>| { + | +++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs index 6e84b6d5ad0bd..1c350b18f5a6f 100644 --- a/src/test/ui/inference/cannot-infer-closure.rs +++ b/src/test/ui/inference/cannot-infer-closure.rs @@ -1,6 +1,6 @@ fn main() { let x = |a: (), b: ()| { Err(a)?; - Ok(b) //~ ERROR type annotations needed for the closure + Ok(b) //~ ERROR type annotations needed }; } diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr index f8026fafeb2c4..a4b818e6e2bb8 100644 --- a/src/test/ui/inference/cannot-infer-closure.stderr +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -1,13 +1,13 @@ -error[E0282]: type annotations needed for the closure `fn((), ()) -> Result<(), _>` +error[E0282]: type annotations needed --> $DIR/cannot-infer-closure.rs:4:9 | LL | Ok(b) - | ^^ cannot infer type for type parameter `E` declared on the enum `Result` + | ^^ cannot infer type of the type parameter `E` declared on the enum `Result` | -help: give this closure an explicit return type without `_` placeholders +help: consider specifying the generic arguments | -LL | let x = |a: (), b: ()| -> Result<(), _> { - | ++++++++++++++++ +LL | Ok::<(), E>(b) + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.rs b/src/test/ui/inference/cannot-infer-partial-try-return.rs index 6e897a3edfdc3..976827a447860 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.rs +++ b/src/test/ui/inference/cannot-infer-partial-try-return.rs @@ -16,7 +16,8 @@ fn infallible() -> Result<(), std::convert::Infallible> { fn main() { let x = || -> Result<_, QualifiedError<_>> { - infallible()?; //~ ERROR type annotations needed + //~^ ERROR type annotations needed for `Result<(), QualifiedError<_>>` + infallible()?; Ok(()) }; } diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.stderr b/src/test/ui/inference/cannot-infer-partial-try-return.stderr index 3542eb6848caf..3956b1a18de50 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.stderr +++ b/src/test/ui/inference/cannot-infer-partial-try-return.stderr @@ -1,13 +1,10 @@ -error[E0282]: type annotations needed for the closure `fn() -> Result<(), QualifiedError<_>>` - --> $DIR/cannot-infer-partial-try-return.rs:19:9 +error[E0282]: type annotations needed for `Result<(), QualifiedError<_>>` + --> $DIR/cannot-infer-partial-try-return.rs:18:13 | -LL | infallible()?; - | ^^^^^^^^^^^^^ cannot infer type - | -help: give this closure an explicit return type without `_` placeholders - | -LL | let x = || -> Result<(), QualifiedError<_>> { - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | let x = || -> Result<_, QualifiedError<_>> { + | ^^^^^^---------------------------- + | | + | help: try giving this closure an explicit return type: `Result<(), QualifiedError<_>>` error: aborting due to previous error diff --git a/src/test/ui/inference/erase-type-params-in-label.stderr b/src/test/ui/inference/erase-type-params-in-label.stderr index 51fac5f79df47..fd58844c2380a 100644 --- a/src/test/ui/inference/erase-type-params-in-label.stderr +++ b/src/test/ui/inference/erase-type-params-in-label.stderr @@ -1,46 +1,40 @@ error[E0283]: type annotations needed for `Foo` - --> $DIR/erase-type-params-in-label.rs:2:15 + --> $DIR/erase-type-params-in-label.rs:2:9 | LL | let foo = foo(1, ""); - | --- ^^^ cannot infer type for type parameter `W` declared on the function `foo` - | | - | consider giving `foo` the explicit type `Foo<_, _, W, Z>`, where the type parameter `W` is specified + | ^^^ | -help: type parameter declared here - --> $DIR/erase-type-params-in-label.rs:25:14 - | -LL | fn foo(t: T, k: K) -> Foo { - | ^ = note: cannot satisfy `_: Default` note: required by a bound in `foo` --> $DIR/erase-type-params-in-label.rs:25:17 | LL | fn foo(t: T, k: K) -> Foo { | ^^^^^^^ required by this bound in `foo` +help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified + | +LL | let foo: Foo = foo(1, ""); + | ++++++++++++++++++++++ help: consider specifying the type arguments in the function call | LL | let foo = foo::(1, ""); | ++++++++++++++ error[E0283]: type annotations needed for `Bar` - --> $DIR/erase-type-params-in-label.rs:5:15 + --> $DIR/erase-type-params-in-label.rs:5:9 | LL | let bar = bar(1, ""); - | --- ^^^ cannot infer type for type parameter `Z` declared on the function `bar` - | | - | consider giving `bar` the explicit type `Bar<_, _, Z>`, where the type parameter `Z` is specified + | ^^^ | -help: type parameter declared here - --> $DIR/erase-type-params-in-label.rs:14:14 - | -LL | fn bar(t: T, k: K) -> Bar { - | ^ = note: cannot satisfy `_: Default` note: required by a bound in `bar` --> $DIR/erase-type-params-in-label.rs:14:17 | LL | fn bar(t: T, k: K) -> Bar { | ^^^^^^^ required by this bound in `bar` +help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified + | +LL | let bar: Bar = bar(1, ""); + | +++++++++++++++++++ help: consider specifying the type arguments in the function call | LL | let bar = bar::(1, ""); diff --git a/src/test/ui/inference/issue-71732.stderr b/src/test/ui/inference/issue-71732.stderr index 0369196c9108e..db153d38aaa9f 100644 --- a/src/test/ui/inference/issue-71732.stderr +++ b/src/test/ui/inference/issue-71732.stderr @@ -2,9 +2,7 @@ error[E0283]: type annotations needed --> $DIR/issue-71732.rs:18:10 | LL | .get(&"key".into()) - | ^^^ ------------ this method call resolves to `T` - | | - | cannot infer type for type parameter `Q` declared on the associated function `get` + | ^^^ cannot infer type of the type parameter `Q` declared on the associated function `get` | = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`: - impl Borrow for String; @@ -15,6 +13,10 @@ note: required by a bound in `HashMap::::get` | LL | K: Borrow, | ^^^^^^^^^ required by this bound in `HashMap::::get` +help: consider specifying the generic argument + | +LL | .get::(&"key".into()) + | +++++ help: consider specifying the type argument in the function call | LL | .get::(&"key".into()) diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr index 0077c73474818..3c53d8126e778 100644 --- a/src/test/ui/inference/issue-72616.stderr +++ b/src/test/ui/inference/issue-72616.stderr @@ -1,16 +1,18 @@ error[E0283]: type annotations needed - --> $DIR/issue-72616.rs:20:30 + --> $DIR/issue-72616.rs:20:37 | LL | if String::from("a") == "a".try_into().unwrap() {} - | ^^ -------------- this method call resolves to `Result>::Error>` - | | - | cannot infer type + | ^^^^^^^^ | = note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate: - impl PartialEq for String; - impl<'a, 'b> PartialEq<&'a str> for String; - impl<'a, 'b> PartialEq> for String; - impl<'a, 'b> PartialEq for String; +help: try using a fully qualified path to specify the expected types + | +LL | if String::from("a") == <&str as TryInto>::try_into("a").unwrap() {} + | +++++++++++++++++++++++++++++++ ~ error: aborting due to previous error diff --git a/src/test/ui/inference/issue-83606.stderr b/src/test/ui/inference/issue-83606.stderr index 9ca8f35fd545a..4ffaf820b8267 100644 --- a/src/test/ui/inference/issue-83606.stderr +++ b/src/test/ui/inference/issue-83606.stderr @@ -1,10 +1,13 @@ error[E0282]: type annotations needed for `[usize; _]` - --> $DIR/issue-83606.rs:8:13 + --> $DIR/issue-83606.rs:8:9 | LL | let _ = foo("foo"); //<- Do not suggest `foo::("foo");`! - | - ^^^ cannot infer the value of const parameter `N` declared on the function `foo` - | | - | consider giving this pattern the explicit type `[_; N]`, where the const parameter `N` is specified + | ^ + | +help: consider giving this pattern a type, where the the value of const parameter `N` is specified + | +LL | let _: [usize; _] = foo("foo"); //<- Do not suggest `foo::("foo");`! + | ++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/inference/issue-86162-1.stderr b/src/test/ui/inference/issue-86162-1.stderr index edf97c0aed47e..6641b29b30b0b 100644 --- a/src/test/ui/inference/issue-86162-1.stderr +++ b/src/test/ui/inference/issue-86162-1.stderr @@ -1,20 +1,19 @@ error[E0283]: type annotations needed - --> $DIR/issue-86162-1.rs:7:5 + --> $DIR/issue-86162-1.rs:7:9 | LL | foo(gen()); //<- Do not suggest `foo::()`! - | ^^^ cannot infer type for type parameter `impl Clone` declared on the function `foo` + | ^^^ cannot infer type of the type parameter `T` declared on the function `gen` | -help: type parameter declared here - --> $DIR/issue-86162-1.rs:3:11 - | -LL | fn foo(x: impl Clone) {} - | ^^^^^^^^^^ = note: cannot satisfy `_: Clone` note: required by a bound in `foo` --> $DIR/issue-86162-1.rs:3:16 | LL | fn foo(x: impl Clone) {} | ^^^^^ required by this bound in `foo` +help: consider specifying the generic argument + | +LL | foo(gen::()); //<- Do not suggest `foo::()`! + | +++++ error: aborting due to previous error diff --git a/src/test/ui/inference/issue-86162-2.stderr b/src/test/ui/inference/issue-86162-2.stderr index c642ebb057603..d2a026a9269c6 100644 --- a/src/test/ui/inference/issue-86162-2.stderr +++ b/src/test/ui/inference/issue-86162-2.stderr @@ -1,20 +1,19 @@ error[E0283]: type annotations needed - --> $DIR/issue-86162-2.rs:12:5 + --> $DIR/issue-86162-2.rs:12:14 | LL | Foo::bar(gen()); //<- Do not suggest `Foo::bar::()`! - | ^^^^^^^^ cannot infer type for type parameter `impl Clone` declared on the associated function `bar` + | ^^^ cannot infer type of the type parameter `T` declared on the function `gen` | -help: type parameter declared here - --> $DIR/issue-86162-2.rs:8:15 - | -LL | fn bar(x: impl Clone) {} - | ^^^^^^^^^^ = note: cannot satisfy `_: Clone` note: required by a bound in `Foo::bar` --> $DIR/issue-86162-2.rs:8:20 | LL | fn bar(x: impl Clone) {} | ^^^^^ required by this bound in `Foo::bar` +help: consider specifying the generic argument + | +LL | Foo::bar(gen::()); //<- Do not suggest `Foo::bar::()`! + | +++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-12187-1.stderr b/src/test/ui/issues/issue-12187-1.stderr index 3ea15439df25a..806b7f0ac05e9 100644 --- a/src/test/ui/issues/issue-12187-1.stderr +++ b/src/test/ui/issues/issue-12187-1.stderr @@ -1,11 +1,13 @@ error[E0282]: type annotations needed for `&T` - --> $DIR/issue-12187-1.rs:6:10 + --> $DIR/issue-12187-1.rs:6:9 | LL | let &v = new(); - | -^ - | || - | |cannot infer type - | consider giving this pattern the explicit type `&T`, with the type parameters specified + | ^^ + | +help: consider giving this pattern a type, where the placeholders `_` are specified + | +LL | let &v: &T = new(); + | ++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-12187-2.stderr b/src/test/ui/issues/issue-12187-2.stderr index a5e65c65beb2f..a1fa0a2b00245 100644 --- a/src/test/ui/issues/issue-12187-2.stderr +++ b/src/test/ui/issues/issue-12187-2.stderr @@ -1,11 +1,13 @@ error[E0282]: type annotations needed for `&T` - --> $DIR/issue-12187-2.rs:6:10 + --> $DIR/issue-12187-2.rs:6:9 | LL | let &v = new(); - | -^ - | || - | |cannot infer type - | consider giving this pattern the explicit type `&T`, with the type parameters specified + | ^^ + | +help: consider giving this pattern a type, where the placeholders `_` are specified + | +LL | let &v: &T = new(); + | ++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16966.stderr b/src/test/ui/issues/issue-16966.stderr index 09e20c0c77731..0b261b3201bee 100644 --- a/src/test/ui/issues/issue-16966.stderr +++ b/src/test/ui/issues/issue-16966.stderr @@ -2,9 +2,13 @@ error[E0282]: type annotations needed --> $DIR/issue-16966.rs:2:5 | LL | panic!(std::default::Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `M` declared on the function `begin_panic` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `M` declared on the function `begin_panic` | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider specifying the generic argument + | +LL | $crate::rt::begin_panic::($msg) + | +++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17551.stderr b/src/test/ui/issues/issue-17551.stderr index 48405a292f3aa..5f45a2f844321 100644 --- a/src/test/ui/issues/issue-17551.stderr +++ b/src/test/ui/issues/issue-17551.stderr @@ -1,10 +1,13 @@ error[E0282]: type annotations needed for `B` - --> $DIR/issue-17551.rs:6:15 + --> $DIR/issue-17551.rs:6:9 | LL | let foo = B(marker::PhantomData); - | --- ^ cannot infer type for type parameter `T` declared on the struct `B` - | | - | consider giving `foo` the explicit type `B`, where the type parameter `T` is specified + | ^^^ + | +help: consider giving `foo` an explicit type, where the type for type parameter `T` is specified + | +LL | let foo: B = B(marker::PhantomData); + | ++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18159.stderr b/src/test/ui/issues/issue-18159.stderr index 9b890be3c789b..605ff3829d19a 100644 --- a/src/test/ui/issues/issue-18159.stderr +++ b/src/test/ui/issues/issue-18159.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/issue-18159.rs:2:9 | LL | let x; - | ^ consider giving `x` a type + | ^ + | +help: consider giving `x` an explicit type + | +LL | let x: _; + | +++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20261.stderr b/src/test/ui/issues/issue-20261.stderr index 6330364c92b6a..73468c7ca1687 100644 --- a/src/test/ui/issues/issue-20261.stderr +++ b/src/test/ui/issues/issue-20261.stderr @@ -1,8 +1,6 @@ -error[E0282]: type annotations needed for `(_,)` +error[E0282]: type annotations needed --> $DIR/issue-20261.rs:4:11 | -LL | for (ref i,) in [].iter() { - | --------- this method call resolves to `std::slice::Iter<'_, T>` LL | i.clone(); | ^^^^^ cannot infer type | diff --git a/src/test/ui/issues/issue-2151.rs b/src/test/ui/issues/issue-2151.rs index 32fba4cb2177d..82cf49de8227e 100644 --- a/src/test/ui/issues/issue-2151.rs +++ b/src/test/ui/issues/issue-2151.rs @@ -1,4 +1,4 @@ fn main() { - let x = panic!(); - x.clone(); //~ ERROR type annotations needed + let x = panic!(); //~ ERROR type annotations needed + x.clone(); } diff --git a/src/test/ui/issues/issue-2151.stderr b/src/test/ui/issues/issue-2151.stderr index a2bcc8a8ceaf0..e0d946205ad0a 100644 --- a/src/test/ui/issues/issue-2151.stderr +++ b/src/test/ui/issues/issue-2151.stderr @@ -1,12 +1,14 @@ error[E0282]: type annotations needed - --> $DIR/issue-2151.rs:3:5 + --> $DIR/issue-2151.rs:2:9 | LL | let x = panic!(); - | - consider giving `x` a type -LL | x.clone(); - | ^ cannot infer type + | ^ | = note: type must be known at this point +help: consider giving `x` an explicit type + | +LL | let x: _ = panic!(); + | +++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23046.stderr b/src/test/ui/issues/issue-23046.stderr index 12b2eb48e7eaa..1403ecbd92d49 100644 --- a/src/test/ui/issues/issue-23046.stderr +++ b/src/test/ui/issues/issue-23046.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed for `Expr<'_, VAR>` --> $DIR/issue-23046.rs:17:15 | LL | let ex = |x| { - | ^ consider giving this closure parameter the explicit type `Expr<'_, VAR>`, where the type parameter `VAR` is specified + | ^ + | +help: consider giving this closure parameter an explicit type, where the type for type parameter `VAR` is specified + | +LL | let ex = |x: Expr<'_, VAR>| { + | +++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24036.stderr b/src/test/ui/issues/issue-24036.stderr index e6b8367f74fb5..4622501f33eda 100644 --- a/src/test/ui/issues/issue-24036.stderr +++ b/src/test/ui/issues/issue-24036.stderr @@ -15,7 +15,12 @@ error[E0282]: type annotations needed --> $DIR/issue-24036.rs:9:15 | LL | 1 => |c| c + 1, - | ^ consider giving this closure parameter a type + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | 1 => |c: _| c + 1, + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-25368.rs b/src/test/ui/issues/issue-25368.rs index 8b4dbb6e460a5..b7f0f613e8091 100644 --- a/src/test/ui/issues/issue-25368.rs +++ b/src/test/ui/issues/issue-25368.rs @@ -5,9 +5,10 @@ use std::marker::PhantomData; struct Foo {foo: PhantomData} fn main() { - let (tx, rx) = channel(); - + let (tx, rx) = //~ ERROR type annotations needed + channel(); + // FIXME(#89862): Suggest adding a generic argument to `channel` instead spawn(move || { - tx.send(Foo{ foo: PhantomData }); //~ ERROR E0282 + tx.send(Foo{ foo: PhantomData }); }); } diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr index 6a970bc049491..ffcb73849527f 100644 --- a/src/test/ui/issues/issue-25368.stderr +++ b/src/test/ui/issues/issue-25368.stderr @@ -1,11 +1,13 @@ error[E0282]: type annotations needed for `(Sender>, std::sync::mpsc::Receiver>)` - --> $DIR/issue-25368.rs:11:17 + --> $DIR/issue-25368.rs:8:9 | -LL | let (tx, rx) = channel(); - | -------- consider giving this pattern the explicit type `(Sender>, std::sync::mpsc::Receiver>)`, where the type parameter `T` is specified -... -LL | tx.send(Foo{ foo: PhantomData }); - | ^^^ cannot infer type for type parameter `T` declared on the struct `Foo` +LL | let (tx, rx) = + | ^^^^^^^^ + | +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let (tx, rx): (Sender>, std::sync::mpsc::Receiver>) = + | +++++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47486.stderr b/src/test/ui/issues/issue-47486.stderr index a029948ca3b82..ca57b2d7e01d2 100644 --- a/src/test/ui/issues/issue-47486.stderr +++ b/src/test/ui/issues/issue-47486.stderr @@ -1,8 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/issue-47486.rs:3:31 + --> $DIR/issue-47486.rs:3:11 | LL | [0u8; std::mem::size_of::<_>()]; - | ^ cannot infer type + | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `size_of` + | +help: consider specifying the generic argument + | +LL | [0u8; std::mem::size_of::<_>()]; + | ~~~~~ error[E0308]: mismatched types --> $DIR/issue-47486.rs:2:10 diff --git a/src/test/ui/issues/issue-5062.stderr b/src/test/ui/issues/issue-5062.stderr index 9fa15dc967914..3191bd3de32fe 100644 --- a/src/test/ui/issues/issue-5062.stderr +++ b/src/test/ui/issues/issue-5062.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/issue-5062.rs:1:29 | LL | fn main() { format!("{:?}", None); } - | ^^^^ cannot infer type for type parameter `T` declared on the enum `Option` + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | fn main() { format!("{:?}", None::); } + | +++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51116.rs b/src/test/ui/issues/issue-51116.rs index c0a74a679efd1..c979c7b2cdd76 100644 --- a/src/test/ui/issues/issue-51116.rs +++ b/src/test/ui/issues/issue-51116.rs @@ -2,7 +2,6 @@ fn main() { let tiles = Default::default(); for row in &mut tiles { for tile in row { - //~^ NOTE the element type for this iterator is not specified *tile = 0; //~^ ERROR type annotations needed //~| NOTE cannot infer type diff --git a/src/test/ui/issues/issue-51116.stderr b/src/test/ui/issues/issue-51116.stderr index 8501ae6a1d029..399b421ab163e 100644 --- a/src/test/ui/issues/issue-51116.stderr +++ b/src/test/ui/issues/issue-51116.stderr @@ -1,9 +1,6 @@ error[E0282]: type annotations needed - --> $DIR/issue-51116.rs:6:13 + --> $DIR/issue-51116.rs:5:13 | -LL | for tile in row { - | --- the element type for this iterator is not specified -LL | LL | *tile = 0; | ^^^^^ cannot infer type | diff --git a/src/test/ui/issues/issue-6458-2.stderr b/src/test/ui/issues/issue-6458-2.stderr index da16f95dc3de6..8dbdd9a273531 100644 --- a/src/test/ui/issues/issue-6458-2.stderr +++ b/src/test/ui/issues/issue-6458-2.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/issue-6458-2.rs:3:21 | LL | format!("{:?}", None); - | ^^^^ cannot infer type for type parameter `T` declared on the enum `Option` + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | format!("{:?}", None::); + | +++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-6458-3.stderr b/src/test/ui/issues/issue-6458-3.stderr index a71c159db0b0e..2c3ec1a331ff8 100644 --- a/src/test/ui/issues/issue-6458-3.stderr +++ b/src/test/ui/issues/issue-6458-3.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/issue-6458-3.rs:4:5 | LL | mem::transmute(0); - | ^^^^^^^^^^^^^^ cannot infer type for type parameter `U` declared on the function `transmute` + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `transmute` + | +help: consider specifying the generic arguments + | +LL | mem::transmute::(0); + | ++++++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-6458.stderr b/src/test/ui/issues/issue-6458.stderr index f548692d78583..2e93c13855f56 100644 --- a/src/test/ui/issues/issue-6458.stderr +++ b/src/test/ui/issues/issue-6458.stderr @@ -1,14 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/issue-6458.rs:9:4 + --> $DIR/issue-6458.rs:9:22 | LL | foo(TypeWithState(marker::PhantomData)); - | ^^^ cannot infer type for type parameter `State` declared on the function `foo` + | ^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` | -help: type parameter declared here - --> $DIR/issue-6458.rs:6:12 +help: consider specifying the generic argument | -LL | pub fn foo(_: TypeWithState) {} - | ^^^^^ +LL | foo(TypeWithState(marker::PhantomData::)); + | +++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-66706.stderr b/src/test/ui/issues/issue-66706.stderr index e8cb18f5c1e62..1c55560cb7c72 100644 --- a/src/test/ui/issues/issue-66706.stderr +++ b/src/test/ui/issues/issue-66706.stderr @@ -30,7 +30,7 @@ error[E0282]: type annotations needed --> $DIR/issue-66706.rs:2:11 | LL | [0; [|_: _ &_| ()].len()] - | ^ consider giving this closure parameter a type + | ^ cannot infer type error[E0308]: mismatched types --> $DIR/issue-66706.rs:2:5 diff --git a/src/test/ui/issues/issue-69455.stderr b/src/test/ui/issues/issue-69455.stderr index 378fdc97dd315..6c4eafbc8b3a1 100644 --- a/src/test/ui/issues/issue-69455.stderr +++ b/src/test/ui/issues/issue-69455.stderr @@ -1,22 +1,20 @@ error[E0282]: type annotations needed --> $DIR/issue-69455.rs:29:20 | -LL | type Output; - | ------------ `>::Output` defined here -... LL | println!("{}", 23u64.test(xs.iter().sum())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | this method call resolves to `>::Output` - | cannot infer type for type parameter `T` declared on the associated function `new_display` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the associated function `new_display` | = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider specifying the generic argument + | +LL | println!("{}", 23u64.test(xs.iter().sum())::); + | +++++ error[E0283]: type annotations needed - --> $DIR/issue-69455.rs:29:26 + --> $DIR/issue-69455.rs:29:41 | LL | println!("{}", 23u64.test(xs.iter().sum())); - | ^^^^ cannot infer type for type parameter `Rhs` declared on the trait `Test` + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` | note: multiple `impl`s satisfying `u64: Test<_>` found --> $DIR/issue-69455.rs:11:1 @@ -26,7 +24,7 @@ LL | impl Test for u64 { ... LL | impl Test for u64 { | ^^^^^^^^^^^^^^^^^^^^^^ -help: consider specifying the type argument in the method call +help: consider specifying the generic argument | LL | println!("{}", 23u64.test(xs.iter().sum::())); | +++++ diff --git a/src/test/ui/issues/issue-69683.stderr b/src/test/ui/issues/issue-69683.stderr index b53923eec1d88..9c71ecffa2682 100644 --- a/src/test/ui/issues/issue-69683.stderr +++ b/src/test/ui/issues/issue-69683.stderr @@ -8,7 +8,7 @@ error[E0283]: type annotations needed --> $DIR/issue-69683.rs:30:10 | LL | 0u16.foo(b); - | ^^^ cannot infer type for type parameter `I` declared on the trait `Foo` + | ^^^ | note: multiple `impl`s satisfying `u8: Element<_>` found --> $DIR/issue-69683.rs:5:1 @@ -26,6 +26,10 @@ LL | u8: Element, LL | { LL | fn foo(self, x: >::Array); | --- required by a bound in this +help: try using a fully qualified path to specify the expected types + | +LL | >::foo(0u16, b); + | +++++++++++++++++++++ ~ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr index f1ec678b20193..9edf14ef291f9 100644 --- a/src/test/ui/issues/issue-72690.stderr +++ b/src/test/ui/issues/issue-72690.stderr @@ -12,51 +12,60 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:7:22 | LL | String::from("x".as_ref()); - | ----^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `AsRef` - | this method call resolves to `&T` + | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef for str; - impl AsRef for str; - impl AsRef<[u8]> for str; - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ error[E0282]: type annotations needed --> $DIR/issue-72690.rs:12:6 | LL | |x| String::from("x".as_ref()); - | ^ consider giving this closure parameter a type + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | |x: _| String::from("x".as_ref()); + | +++ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:12:26 | LL | |x| String::from("x".as_ref()); - | ----^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `AsRef` - | this method call resolves to `&T` + | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef for str; - impl AsRef for str; - impl AsRef<[u8]> for str; - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | |x| String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed for `&T` - --> $DIR/issue-72690.rs:17:17 + --> $DIR/issue-72690.rs:17:9 | LL | let _ = "x".as_ref(); - | - ^^^^^^ cannot infer type for type parameter `T` declared on the trait `AsRef` - | | - | consider giving this pattern the explicit type `&T`, where the type parameter `T` is specified + | ^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef for str; - impl AsRef for str; - impl AsRef<[u8]> for str; - impl AsRef for str; +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let _: &T = "x".as_ref(); + | ++++ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:21:5 @@ -72,16 +81,17 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:21:22 | LL | String::from("x".as_ref()); - | ----^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `AsRef` - | this method call resolves to `&T` + | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef for str; - impl AsRef for str; - impl AsRef<[u8]> for str; - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:28:5 @@ -97,16 +107,17 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:28:22 | LL | String::from("x".as_ref()); - | ----^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `AsRef` - | this method call resolves to `&T` + | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef for str; - impl AsRef for str; - impl AsRef<[u8]> for str; - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:37:5 @@ -122,16 +133,17 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:37:22 | LL | String::from("x".as_ref()); - | ----^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `AsRef` - | this method call resolves to `&T` + | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef for str; - impl AsRef for str; - impl AsRef<[u8]> for str; - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:46:5 @@ -147,16 +159,17 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:46:22 | LL | String::from("x".as_ref()); - | ----^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `AsRef` - | this method call resolves to `&T` + | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef for str; - impl AsRef for str; - impl AsRef<[u8]> for str; - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:53:5 @@ -172,16 +185,17 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:53:22 | LL | String::from("x".as_ref()); - | ----^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `AsRef` - | this method call resolves to `&T` + | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef for str; - impl AsRef for str; - impl AsRef<[u8]> for str; - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:62:5 @@ -197,16 +211,17 @@ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:62:22 | LL | String::from("x".as_ref()); - | ----^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `AsRef` - | this method call resolves to `&T` + | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: - impl AsRef for str; - impl AsRef for str; - impl AsRef<[u8]> for str; - impl AsRef for str; +help: try using a fully qualified path to specify the expected types + | +LL | String::from(>::as_ref("x")); + | ++++++++++++++++++++++++++ ~ error: aborting due to 17 previous errors diff --git a/src/test/ui/issues/issue-7813.stderr b/src/test/ui/issues/issue-7813.stderr index 59be0f3be11e6..3aee61bd5a54c 100644 --- a/src/test/ui/issues/issue-7813.stderr +++ b/src/test/ui/issues/issue-7813.stderr @@ -1,10 +1,13 @@ error[E0282]: type annotations needed for `&[_; 0]` - --> $DIR/issue-7813.rs:2:13 + --> $DIR/issue-7813.rs:2:9 | LL | let v = &[]; - | - ^^^ cannot infer type - | | - | consider giving `v` the explicit type `&[_; 0]`, with the type parameters specified + | ^ + | +help: consider giving `v` an explicit type, where the placeholders `_` are specified + | +LL | let v: &[_; 0] = &[]; + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/match/match-unresolved-one-arm.stderr b/src/test/ui/match/match-unresolved-one-arm.stderr index 77df9921b754a..9eadb88a8ba81 100644 --- a/src/test/ui/match/match-unresolved-one-arm.stderr +++ b/src/test/ui/match/match-unresolved-one-arm.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/match-unresolved-one-arm.rs:4:9 | LL | let x = match () { - | ^ consider giving `x` a type + | ^ + | +help: consider giving `x` an explicit type + | +LL | let x: _ = match () { + | +++ error: aborting due to previous error diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr index f33672433dee4..66e7ada3ac5fd 100644 --- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr +++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -1,10 +1,13 @@ error[E0282]: type annotations needed for `Vec` - --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:17 + --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:9 | LL | let mut x = Vec::new(); - | ----- ^^^^^^^^ cannot infer type for type parameter `T` - | | - | consider giving `x` the explicit type `Vec`, where the type parameter `T` is specified + | ^^^^^ + | +help: consider giving `x` an explicit type, where the type for type parameter `T` is specified + | +LL | let mut x: Vec = Vec::new(); + | ++++++++ error[E0283]: type annotations needed --> $DIR/method-ambig-one-trait-unknown-int-type.rs:26:7 diff --git a/src/test/ui/missing/missing-items/missing-type-parameter.stderr b/src/test/ui/missing/missing-items/missing-type-parameter.stderr index 2aa2b0e6a3c2c..722539fca6b8e 100644 --- a/src/test/ui/missing/missing-items/missing-type-parameter.stderr +++ b/src/test/ui/missing/missing-items/missing-type-parameter.stderr @@ -2,13 +2,12 @@ error[E0282]: type annotations needed --> $DIR/missing-type-parameter.rs:4:5 | LL | foo(); - | ^^^ cannot infer type for type parameter `X` declared on the function `foo` + | ^^^ cannot infer type of the type parameter `X` declared on the function `foo` | -help: type parameter declared here - --> $DIR/missing-type-parameter.rs:1:8 +help: consider specifying the generic argument | -LL | fn foo() { } - | ^ +LL | foo::(); + | +++++ error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr index 34f1397ce1d5b..85c9fe409dbe9 100644 --- a/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr +++ b/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr @@ -116,7 +116,12 @@ error[E0282]: type annotations needed --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:14 | LL | V = [Vec::new; { [0].len() ].len() as isize, - | ^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec` + | +help: consider specifying the generic argument + | +LL | V = [Vec::::new; { [0].len() ].len() as isize, + | +++++ error: aborting due to 14 previous errors diff --git a/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr index 427234e97cf55..bad241634cbe6 100644 --- a/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr +++ b/src/test/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -40,24 +40,26 @@ LL | let v : Vec<'a> = vec![]; | + error[E0282]: type annotations needed for `Vec` - --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:25 + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:7 | LL | let v : Vec<(u32,_) = vec![]; - | - ^^^^^^ cannot infer type for type parameter `T` - | | - | consider giving `v` the explicit type `Vec`, where the type parameter `T` is specified + | ^ + | +help: consider giving `v` an explicit type, where the type for type parameter `T` is specified | - = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | let v: Vec : Vec<(u32,_) = vec![]; + | ++++++++ error[E0282]: type annotations needed for `Vec` - --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:20 + --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:7 | LL | let v : Vec<'a = vec![]; - | - ^^^^^^ cannot infer type for type parameter `T` - | | - | consider giving `v` the explicit type `Vec`, where the type parameter `T` is specified + | ^ + | +help: consider giving `v` an explicit type, where the type for type parameter `T` is specified | - = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | let v: Vec : Vec<'a = vec![]; + | ++++++++ error: aborting due to 5 previous errors diff --git a/src/test/ui/pattern/pat-tuple-bad-type.rs b/src/test/ui/pattern/pat-tuple-bad-type.rs index 01e793e868599..98481167a59d1 100644 --- a/src/test/ui/pattern/pat-tuple-bad-type.rs +++ b/src/test/ui/pattern/pat-tuple-bad-type.rs @@ -1,8 +1,8 @@ fn main() { - let x; + let x; //~ ERROR type annotations needed match x { - (..) => {} //~ ERROR type annotations needed + (..) => {} _ => {} } diff --git a/src/test/ui/pattern/pat-tuple-bad-type.stderr b/src/test/ui/pattern/pat-tuple-bad-type.stderr index 598b6a3794ef7..11b28987848d6 100644 --- a/src/test/ui/pattern/pat-tuple-bad-type.stderr +++ b/src/test/ui/pattern/pat-tuple-bad-type.stderr @@ -1,13 +1,14 @@ error[E0282]: type annotations needed - --> $DIR/pat-tuple-bad-type.rs:5:9 + --> $DIR/pat-tuple-bad-type.rs:2:9 | LL | let x; - | - consider giving `x` a type -... -LL | (..) => {} - | ^^^^ cannot infer type + | ^ | = note: type must be known at this point +help: consider giving `x` an explicit type + | +LL | let x: _; + | +++ error[E0308]: mismatched types --> $DIR/pat-tuple-bad-type.rs:10:9 diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr index 06b6e80b44f7a..e6a4e5f19b716 100644 --- a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr +++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr @@ -189,7 +189,12 @@ error[E0282]: type annotations needed --> $DIR/rest-pat-semantic-disallowed.rs:33:9 | LL | let x @ ..; - | ^^^^^^ consider giving this pattern a type + | ^^^^^^ + | +help: consider giving this pattern a type + | +LL | let x @ ..: _; + | +++ error: aborting due to 23 previous errors diff --git a/src/test/ui/resolve/issue-85348.stderr b/src/test/ui/resolve/issue-85348.stderr index f475c26f32b8f..f839dd927db99 100644 --- a/src/test/ui/resolve/issue-85348.stderr +++ b/src/test/ui/resolve/issue-85348.stderr @@ -17,7 +17,12 @@ error[E0282]: type annotations needed --> $DIR/issue-85348.rs:6:13 | LL | let mut N; - | ^^^^^ consider giving `N` a type + | ^^^^^ + | +help: consider giving `N` an explicit type + | +LL | let mut N: _; + | +++ error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr index 278d049224401..98e45ff9d0758 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr @@ -1,20 +1,26 @@ -error[E0282]: type annotations needed for `Option<_>` - --> $DIR/issue-42234-unknown-receiver-type.rs:10:7 +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:9:24 | -LL | let x: Option<_> = None; - | - consider giving `x` the explicit type `Option<_>`, where the type parameter `T` is specified -LL | x.unwrap().method_that_could_exist_on_some_type(); - | ^^^^^^ cannot infer type for type parameter `T` +LL | let x: Option<_> = None::<_>; + | ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` | = note: type must be known at this point +help: consider specifying the generic argument + | +LL | let x: Option<_> = None::<_>; + | ~~~~~ error[E0282]: type annotations needed - --> $DIR/issue-42234-unknown-receiver-type.rs:16:10 + --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 | LL | .sum::<_>() - | ^^^ cannot infer type + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` | = note: type must be known at this point +help: consider specifying the generic argument + | +LL | .sum::<_>() + | ~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr index 8d4ed4aea6a6c..0902ffa26217f 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr @@ -1,20 +1,26 @@ -error[E0282]: type annotations needed for `Option<_>` - --> $DIR/issue-42234-unknown-receiver-type.rs:10:7 +error[E0282]: type annotations needed + --> $DIR/issue-42234-unknown-receiver-type.rs:9:24 | -LL | let x: Option<_> = None; - | - consider giving `x` the explicit type `Option<_>`, where the type parameter `T` is specified -LL | x.unwrap().method_that_could_exist_on_some_type(); - | ^^^^^^ cannot infer type for type parameter `T` +LL | let x: Option<_> = None::<_>; + | ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` | = note: type must be known at this point +help: consider specifying the generic argument + | +LL | let x: Option<_> = None::; + | ~~~~~ error[E0282]: type annotations needed - --> $DIR/issue-42234-unknown-receiver-type.rs:16:16 + --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 | LL | .sum::<_>() - | ^ cannot infer type for type parameter `S` declared on the associated function `sum` + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` | = note: type must be known at this point +help: consider specifying the generic argument + | +LL | .sum::() + | ~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.rs b/src/test/ui/span/issue-42234-unknown-receiver-type.rs index 15b00de44b933..93c66eb130157 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.rs +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.rs @@ -6,9 +6,8 @@ // the fix of which this tests). fn shines_a_beacon_through_the_darkness() { - let x: Option<_> = None; + let x: Option<_> = None::<_>; //~ ERROR type annotations needed x.unwrap().method_that_could_exist_on_some_type(); - //~^ ERROR type annotations needed } fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { diff --git a/src/test/ui/span/method-and-field-eager-resolution.rs b/src/test/ui/span/method-and-field-eager-resolution.rs index a38f07d58e474..a0f0d8810e5c7 100644 --- a/src/test/ui/span/method-and-field-eager-resolution.rs +++ b/src/test/ui/span/method-and-field-eager-resolution.rs @@ -2,14 +2,14 @@ fn main() { let mut x = Default::default(); - x.0; //~^ ERROR type annotations needed + x.0; x = 1; } fn foo() { let mut x = Default::default(); - x[0]; //~^ ERROR type annotations needed + x[0]; x = 1; } 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 0ecbe4c136e00..2dd650f38ce39 100644 --- a/src/test/ui/span/method-and-field-eager-resolution.stderr +++ b/src/test/ui/span/method-and-field-eager-resolution.stderr @@ -1,22 +1,26 @@ error[E0282]: type annotations needed - --> $DIR/method-and-field-eager-resolution.rs:5:5 + --> $DIR/method-and-field-eager-resolution.rs:4:9 | LL | let mut x = Default::default(); - | ----- consider giving `x` a type -LL | x.0; - | ^ cannot infer type + | ^^^^^ | = note: type must be known at this point +help: consider giving `x` an explicit type + | +LL | let mut x: _ = Default::default(); + | +++ error[E0282]: type annotations needed - --> $DIR/method-and-field-eager-resolution.rs:12:5 + --> $DIR/method-and-field-eager-resolution.rs:11:9 | LL | let mut x = Default::default(); - | ----- consider giving `x` a type -LL | x[0]; - | ^ cannot infer type + | ^^^^^ | = note: type must be known at this point +help: consider giving `x` an explicit type + | +LL | let mut x: _ = Default::default(); + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/type-annotations-needed-expr.stderr b/src/test/ui/span/type-annotations-needed-expr.stderr index fbfbefd078202..e4a8f7464626c 100644 --- a/src/test/ui/span/type-annotations-needed-expr.stderr +++ b/src/test/ui/span/type-annotations-needed-expr.stderr @@ -2,10 +2,10 @@ error[E0282]: type annotations needed --> $DIR/type-annotations-needed-expr.rs:2:39 | LL | let _ = (vec![1,2,3]).into_iter().sum() as f64; - | ^^^ cannot infer type for type parameter `S` declared on the associated function `sum` + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` | = note: type must be known at this point -help: consider specifying the type argument in the method call +help: consider specifying the generic argument | LL | let _ = (vec![1,2,3]).into_iter().sum::() as f64; | +++++ diff --git a/src/test/ui/suggestions/fn-needing-specified-return-type-param.rs b/src/test/ui/suggestions/fn-needing-specified-return-type-param.rs index 2f140f823afb9..bcc91b5cb4c56 100644 --- a/src/test/ui/suggestions/fn-needing-specified-return-type-param.rs +++ b/src/test/ui/suggestions/fn-needing-specified-return-type-param.rs @@ -1,5 +1,7 @@ fn f() -> A { unimplemented!() } fn foo() { - let _ = f; //~ ERROR type annotations needed for `fn() -> A` + let _ = f; + //~^ ERROR type annotations needed + //~| HELP consider specifying the generic argument } fn main() {} diff --git a/src/test/ui/suggestions/fn-needing-specified-return-type-param.stderr b/src/test/ui/suggestions/fn-needing-specified-return-type-param.stderr index a4cfee5563373..9dea667fb961e 100644 --- a/src/test/ui/suggestions/fn-needing-specified-return-type-param.stderr +++ b/src/test/ui/suggestions/fn-needing-specified-return-type-param.stderr @@ -1,16 +1,13 @@ -error[E0282]: type annotations needed for `fn() -> A` +error[E0282]: type annotations needed --> $DIR/fn-needing-specified-return-type-param.rs:3:13 | LL | let _ = f; - | - ^ cannot infer type for type parameter `A` declared on the function `f` - | | - | consider giving this pattern the explicit type `fn() -> A`, where the type parameter `A` is specified + | ^ cannot infer type of the type parameter `A` declared on the function `f` | -help: type parameter declared here - --> $DIR/fn-needing-specified-return-type-param.rs:1:6 +help: consider specifying the generic argument | -LL | fn f() -> A { unimplemented!() } - | ^ +LL | let _ = f::; + | +++++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.rs b/src/test/ui/suggestions/suggest-closure-return-type-1.rs index 910f273b9722d..8bb4219039b93 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-1.rs +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.rs @@ -1,3 +1,7 @@ +fn unbound_drop(_: impl Sized) {} + fn main() { - let _v = || -> _ { [] }; //~ ERROR type annotations needed for the closure + unbound_drop(|| -> _ { [] }); + //~^ ERROR type annotations needed for `[_; 0]` + //~| HELP try giving this closure an explicit return type } diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr index 7161ca3903e61..ba70bf104bf30 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr @@ -1,13 +1,10 @@ -error[E0282]: type annotations needed for the closure `fn() -> [_; 0]` - --> $DIR/suggest-closure-return-type-1.rs:2:24 +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/suggest-closure-return-type-1.rs:4:18 | -LL | let _v = || -> _ { [] }; - | ^^ cannot infer type - | -help: give this closure an explicit return type without `_` placeholders - | -LL | let _v = || -> [_; 0] { [] }; - | ~~~~~~ +LL | unbound_drop(|| -> _ { [] }); + | ^^^^^^- + | | + | help: try giving this closure an explicit return type: `[_; 0]` error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.rs b/src/test/ui/suggestions/suggest-closure-return-type-2.rs index 6955b37ad97e4..25ed1882e8d2d 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-2.rs +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.rs @@ -1,3 +1,7 @@ +fn unbound_drop(_: impl Sized) {} + fn main() { - let _v = || { [] }; //~ ERROR type annotations needed for the closure + unbound_drop(|| { [] }) + //~^ ERROR type annotations needed for `[_; 0]` + //~| HELP try giving this closure an explicit return type } diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr index a7f5b58c4da76..f2cb6d291b3f8 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr @@ -1,13 +1,8 @@ -error[E0282]: type annotations needed for the closure `fn() -> [_; 0]` - --> $DIR/suggest-closure-return-type-2.rs:2:19 +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/suggest-closure-return-type-2.rs:4:18 | -LL | let _v = || { [] }; - | ^^ cannot infer type - | -help: give this closure an explicit return type without `_` placeholders - | -LL | let _v = || -> [_; 0] { [] }; - | +++++++++ +LL | unbound_drop(|| { [] }) + | ^^ - help: try giving this closure an explicit return type: `-> [_; 0]` error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.rs b/src/test/ui/suggestions/suggest-closure-return-type-3.rs index ec6c094027e1e..3de6c55cf1696 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-3.rs +++ b/src/test/ui/suggestions/suggest-closure-return-type-3.rs @@ -1,3 +1,7 @@ +fn unbound_drop(_: impl Sized) {} + fn main() { - let _v = || []; //~ ERROR type annotations needed for the closure + unbound_drop(|| []); + //~^ ERROR type annotations needed for `[_; 0]` + //~| HELP try giving this closure an explicit return type } diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.stderr b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr index eeec23e0da030..4176932153353 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-3.stderr +++ b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr @@ -1,13 +1,13 @@ -error[E0282]: type annotations needed for the closure `fn() -> [_; 0]` - --> $DIR/suggest-closure-return-type-3.rs:2:17 +error[E0282]: type annotations needed for `[_; 0]` + --> $DIR/suggest-closure-return-type-3.rs:4:18 | -LL | let _v = || []; - | ^^ cannot infer type +LL | unbound_drop(|| []); + | ^^ | -help: give this closure an explicit return type without `_` placeholders +help: try giving this closure an explicit return type | -LL | let _v = || -> [_; 0] { [] }; - | +++++++++++ + +LL | unbound_drop(|| -> [_; 0] { [] }); + | +++++++++++ + error: aborting due to previous error diff --git a/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr b/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr index 0e52420ec4377..57b2587ae5ccd 100644 --- a/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr +++ b/src/test/ui/traits/do-not-mention-type-params-by-name-in-suggestion-issue-96292.stderr @@ -2,19 +2,18 @@ error[E0282]: type annotations needed --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11 | LL | thing.method(42); - | ------^^^^^^---- - | | | - | | cannot infer type for type parameter `T` declared on the trait `Method` - | this method call resolves to `T` + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | as Method>::method(thing, 42); + | +++++++++++++++++++++++++++++++++++ ~ error[E0283]: type annotations needed --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:17:11 | LL | thing.method(42); - | ------^^^^^^---- - | | | - | | cannot infer type for type parameter `T` declared on the trait `Method` - | this method call resolves to `T` + | ^^^^^^ | note: multiple `impl`s satisfying `Thing: Method<_>` found --> $DIR/do-not-mention-type-params-by-name-in-suggestion-issue-96292.rs:7:1 @@ -24,12 +23,10 @@ LL | impl Method for Thing { ... LL | impl Method for Thing { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: use the fully qualified path for the potential candidates +help: try using a fully qualified path to specify the expected types | -LL | as Method>::method(thing, 42); - | ++++++++++++++++++++++++++++++++++ ~ -LL | as Method>::method(thing, 42); - | ++++++++++++++++++++++++++++++++++ ~ +LL | as Method>::method(thing, 42); + | +++++++++++++++++++++++++++++++++++ ~ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr index 63c1cb3791edf..5aa42b5b1d3ed 100644 --- a/src/test/ui/traits/issue-77982.stderr +++ b/src/test/ui/traits/issue-77982.stderr @@ -2,9 +2,7 @@ error[E0283]: type annotations needed --> $DIR/issue-77982.rs:8:10 | LL | opts.get(opt.as_ref()); - | ^^^ ------------ this method call resolves to `&T` - | | - | cannot infer type for type parameter `Q` declared on the associated function `get` + | ^^^ cannot infer type of the type parameter `Q` declared on the associated function `get` | = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`: - impl Borrow for String; @@ -15,44 +13,36 @@ note: required by a bound in `HashMap::::get` | LL | K: Borrow, | ^^^^^^^^^ required by this bound in `HashMap::::get` +help: consider specifying the generic argument + | +LL | opts.get::(opt.as_ref()); + | +++++ help: consider specifying the type argument in the function call | LL | opts.get::(opt.as_ref()); | +++++ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:8:18 + --> $DIR/issue-77982.rs:8:10 | LL | opts.get(opt.as_ref()); - | ----^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `AsRef` - | this method call resolves to `&T` + | ^^^ cannot infer type of the type parameter `Q` declared on the associated function `get` | = note: multiple `impl`s satisfying `String: AsRef<_>` found in the following crates: `alloc`, `std`: - impl AsRef for String; - impl AsRef for String; - impl AsRef<[u8]> for String; - impl AsRef for String; -help: use the fully qualified path for the potential candidates - | -LL | opts.get(>::as_ref(opt)); - | +++++++++++++++++++++++++++++++++ ~ -LL | opts.get(>::as_ref(opt)); - | ++++++++++++++++++++++++++++++++ ~ -LL | opts.get(>::as_ref(opt)); - | ++++++++++++++++++++++++++++++++ ~ -LL | opts.get(>::as_ref(opt)); - | +++++++++++++++++++++++++++++++ ~ - and 4 other candidates +help: consider specifying the generic argument + | +LL | opts.get::(opt.as_ref()); + | +++++ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:13:44 + --> $DIR/issue-77982.rs:13:59 | LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); - | ^^^^^^^^^ ----------- this method call resolves to `T` - | | - | cannot infer type for type parameter `T` declared on the trait `From` + | ^^^^ | = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`: - impl From for u32; @@ -60,14 +50,16 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect( - impl From for u32; - impl From for u32; and 3 more +help: try using a fully qualified path to specify the expected types + | +LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(>::into(0u32))).collect(); + | +++++++++++++++++++++++ ~ error[E0283]: type annotations needed for `Box` - --> $DIR/issue-77982.rs:36:16 + --> $DIR/issue-77982.rs:36:9 | LL | let _ = ().foo(); - | - ^^^ cannot infer type for type parameter `T` declared on the trait `Foo` - | | - | consider giving this pattern the explicit type `Box`, where the type parameter `T` is specified + | ^ | note: multiple `impl`s satisfying `(): Foo<'_, _>` found --> $DIR/issue-77982.rs:29:1 @@ -76,14 +68,16 @@ LL | impl Foo<'static, u32> for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | impl<'a> Foo<'a, i16> for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let _: Box = ().foo(); + | ++++++++ error[E0283]: type annotations needed for `Box` - --> $DIR/issue-77982.rs:40:19 + --> $DIR/issue-77982.rs:40:9 | LL | let _ = (&()).bar(); - | - ^^^ cannot infer type for type parameter `T` declared on the trait `Bar` - | | - | consider giving this pattern the explicit type `Box`, where the type parameter `T` is specified + | ^ | note: multiple `impl`s satisfying `&(): Bar<'_, _>` found --> $DIR/issue-77982.rs:32:1 @@ -92,6 +86,10 @@ LL | impl<'a> Bar<'static, u32> for &'a () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | impl<'a> Bar<'a, i16> for &'a () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let _: Box = (&()).bar(); + | ++++++++ error: aborting due to 5 previous errors diff --git a/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr b/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr index da7461347106f..25f8d5383776d 100644 --- a/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr +++ b/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr @@ -2,25 +2,19 @@ error[E0282]: type annotations needed --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 | LL | test(22, std::default::Default::default()); - | ^^^^ cannot infer type for type parameter `U` declared on the function `test` + | ^^^^ cannot infer type of the type parameter `U` declared on the function `test` | -help: type parameter declared here - --> $DIR/multidispatch-convert-ambig-dest.rs:20:11 +help: consider specifying the generic arguments | -LL | fn test(_: T, _: U) - | ^ +LL | test::(22, std::default::Default::default()); + | ++++++++++ error[E0283]: type annotations needed --> $DIR/multidispatch-convert-ambig-dest.rs:26:5 | LL | test(22, std::default::Default::default()); - | ^^^^ cannot infer type for type parameter `U` declared on the function `test` - | -help: type parameter declared here - --> $DIR/multidispatch-convert-ambig-dest.rs:20:11 + | ^^^^ cannot infer type of the type parameter `U` declared on the function `test` | -LL | fn test(_: T, _: U) - | ^ note: multiple `impl`s satisfying `i32: Convert<_>` found --> $DIR/multidispatch-convert-ambig-dest.rs:8:1 | @@ -36,6 +30,10 @@ LL | fn test(_: T, _: U) | ---- required by a bound in this LL | where T : Convert | ^^^^^^^^^^ required by this bound in `test` +help: consider specifying the generic arguments + | +LL | test::(22, std::default::Default::default()); + | ++++++++++ help: consider specifying the type arguments in the function call | LL | test::(22, std::default::Default::default()); diff --git a/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr index 3c8d7450f96fa..75d45d9052b46 100644 --- a/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr +++ b/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr @@ -2,25 +2,19 @@ error[E0282]: type annotations needed --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7 | LL | a.method(); - | --^^^^^^-- - | | | - | | cannot infer type for type parameter `U` declared on the trait `V` - | this method call resolves to `U` + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | as V>::method(a); + | +++++++++++++++++++++++ ~ error[E0283]: type annotations needed --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:21:7 | LL | a.method(); - | --^^^^^^-- - | | | - | | cannot infer type for type parameter `U` - | this method call resolves to `U` - | -help: type parameter declared here - --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:12:9 + | ^^^^^^ | -LL | impl V for A - | ^ note: multiple `impl`s satisfying `B: I<_>` found --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:5:1 | @@ -33,6 +27,10 @@ note: required because of the requirements on the impl of `V<_>` for `A` | LL | impl V for A | ^^^^ ^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | as V>::method(a); + | +++++++++++++++++++++++ ~ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/suggest-fully-qualified-path-with-adjustment.rs b/src/test/ui/traits/suggest-fully-qualified-path-with-adjustment.rs new file mode 100644 index 0000000000000..9a2cf469d08e4 --- /dev/null +++ b/src/test/ui/traits/suggest-fully-qualified-path-with-adjustment.rs @@ -0,0 +1,60 @@ +use std::ops::{Deref, DerefMut}; + +struct Thing; + +trait Method { + fn method(&self) -> T; + fn mut_method(&mut self) -> T; +} + +impl Method for Thing { + fn method(&self) -> i32 { 0 } + fn mut_method(&mut self) -> i32 { 0 } +} + +impl Method for Thing { + fn method(&self) -> u32 { 0 } + fn mut_method(&mut self) -> u32 { 0 } +} +trait MethodRef { + fn by_self(self); +} +impl MethodRef for &Thing { + fn by_self(self) {} +} +impl MethodRef for &Thing { + fn by_self(self) {} +} + + +struct DerefsTo(T); +impl Deref for DerefsTo { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for DerefsTo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() { + let mut thing = Thing; + thing.method(); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + thing.mut_method(); //~ ERROR type annotations needed + thing.by_self(); //~ ERROR type annotations needed + + let mut deref_to = DerefsTo(Thing); + deref_to.method(); //~ ERROR type annotations needed + deref_to.mut_method(); //~ ERROR type annotations needed + deref_to.by_self(); //~ ERROR type annotations needed + + let mut deref_deref_to = DerefsTo(DerefsTo(Thing)); + deref_deref_to.method(); //~ ERROR type annotations needed + deref_deref_to.mut_method(); //~ ERROR type annotations needed + deref_deref_to.by_self(); //~ ERROR type annotations needed +} diff --git a/src/test/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr b/src/test/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr new file mode 100644 index 0000000000000..68b31a1ca34e3 --- /dev/null +++ b/src/test/ui/traits/suggest-fully-qualified-path-with-adjustment.stderr @@ -0,0 +1,186 @@ +error[E0282]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11 + | +LL | thing.method(); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | >::method(&thing); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:45:11 + | +LL | thing.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(&thing); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:48:11 + | +LL | thing.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(&mut thing); + | +++++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:49:11 + | +LL | thing.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(&thing); + | +++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:52:14 + | +LL | deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(&deref_to); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:53:14 + | +LL | deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(&mut deref_to); + | +++++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:54:14 + | +LL | deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(&deref_to); + | +++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:57:20 + | +LL | deref_deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(&deref_deref_to); + | ++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:58:20 + | +LL | deref_deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(&mut deref_deref_to); + | +++++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:59:20 + | +LL | deref_deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-with-adjustment.rs:22:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(&deref_deref_to); + | +++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs b/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs deleted file mode 100644 index da68b996be999..0000000000000 --- a/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs +++ /dev/null @@ -1,24 +0,0 @@ -struct Thing; - -trait Method { - fn method(&self) -> T; - fn mut_method(&mut self) -> T; -} - -impl Method for Thing { - fn method(&self) -> i32 { 0 } - fn mut_method(&mut self) -> i32 { 0 } -} - -impl Method for Thing { - fn method(&self) -> u32 { 0 } - fn mut_method(&mut self) -> u32 { 0 } -} - -fn main() { - let thing = Thing; - thing.method(); - //~^ ERROR type annotations needed - //~| ERROR type annotations needed - thing.mut_method(); //~ ERROR type annotations needed -} diff --git a/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.stderr b/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.stderr deleted file mode 100644 index 0c4962417e9bc..0000000000000 --- a/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.stderr +++ /dev/null @@ -1,61 +0,0 @@ -error[E0282]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:20:11 - | -LL | thing.method(); - | ------^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `Method` - | this method call resolves to `T` - -error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:20:11 - | -LL | thing.method(); - | ------^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `Method` - | this method call resolves to `T` - | -note: multiple `impl`s satisfying `Thing: Method<_>` found - --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:8:1 - | -LL | impl Method for Thing { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | impl Method for Thing { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: use the fully qualified path for the potential candidates - | -LL | >::method(&thing); - | ++++++++++++++++++++++++++++++++ ~ -LL | >::method(&thing); - | ++++++++++++++++++++++++++++++++ ~ - -error[E0283]: type annotations needed - --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:23:11 - | -LL | thing.mut_method(); - | ------^^^^^^^^^^-- - | | | - | | cannot infer type for type parameter `T` declared on the trait `Method` - | this method call resolves to `T` - | -note: multiple `impl`s satisfying `Thing: Method<_>` found - --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:8:1 - | -LL | impl Method for Thing { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | impl Method for Thing { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: use the fully qualified path for the potential candidates - | -LL | >::mut_method(&mut thing); - | +++++++++++++++++++++++++++++++++++++++ ~ -LL | >::mut_method(&mut thing); - | +++++++++++++++++++++++++++++++++++++++ ~ - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/traits/suggest-fully-qualified-path-without-adjustment.rs b/src/test/ui/traits/suggest-fully-qualified-path-without-adjustment.rs new file mode 100644 index 0000000000000..da640c8c8c26a --- /dev/null +++ b/src/test/ui/traits/suggest-fully-qualified-path-without-adjustment.rs @@ -0,0 +1,64 @@ +use std::ops::{Deref, DerefMut}; + +struct Thing; + +trait Method { + fn method(&self) -> T; + fn mut_method(&mut self) -> T; +} + +impl Method for Thing { + fn method(&self) -> i32 { 0 } + fn mut_method(&mut self) -> i32 { 0 } +} + +impl Method for Thing { + fn method(&self) -> u32 { 0 } + fn mut_method(&mut self) -> u32 { 0 } +} + +trait MethodRef { + fn by_self(self); +} +impl MethodRef for &Thing { + fn by_self(self) {} +} +impl MethodRef for &Thing { + fn by_self(self) {} +} + +struct DerefsTo(T); +impl Deref for DerefsTo { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} +impl DerefMut for DerefsTo { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() { + let mut ref_thing = &Thing; + ref_thing.method(); + //~^ ERROR type annotations needed + //~| ERROR type annotations needed + ref_thing.by_self(); //~ ERROR type annotations needed + + let mut mut_thing = &mut Thing; + mut_thing.method(); //~ ERROR type annotations needed + mut_thing.mut_method(); //~ ERROR type annotations needed + mut_thing.by_self(); //~ ERROR type annotations needed + + let mut deref_to = &DerefsTo(Thing); + deref_to.method(); //~ ERROR type annotations needed + deref_to.mut_method(); //~ ERROR type annotations needed + deref_to.by_self(); //~ ERROR type annotations needed + + let mut deref_deref_to = &DerefsTo(DerefsTo(Thing)); + deref_deref_to.method(); //~ ERROR type annotations needed + deref_deref_to.mut_method(); //~ ERROR type annotations needed + deref_deref_to.by_self(); //~ ERROR type annotations needed +} diff --git a/src/test/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr b/src/test/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr new file mode 100644 index 0000000000000..27518a54e7507 --- /dev/null +++ b/src/test/ui/traits/suggest-fully-qualified-path-without-adjustment.stderr @@ -0,0 +1,224 @@ +error[E0282]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15 + | +LL | ref_thing.method(); + | ^^^^^^ + | +help: try using a fully qualified path to specify the expected types + | +LL | >::method(ref_thing); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:45:15 + | +LL | ref_thing.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(ref_thing); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:48:15 + | +LL | ref_thing.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(ref_thing); + | ++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:51:15 + | +LL | mut_thing.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(mut_thing); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:52:15 + | +LL | mut_thing.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(mut_thing); + | +++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:53:15 + | +LL | mut_thing.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(mut_thing); + | ++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:56:14 + | +LL | deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(deref_to); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:57:14 + | +LL | deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(deref_to); + | +++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:58:14 + | +LL | deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(deref_to); + | ++++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:61:20 + | +LL | deref_deref_to.method(); + | ^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::method(deref_deref_to); + | +++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:62:20 + | +LL | deref_deref_to.mut_method(); + | ^^^^^^^^^^ + | +note: multiple `impl`s satisfying `Thing: Method<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:10:1 + | +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | >::mut_method(deref_deref_to); + | +++++++++++++++++++++++++++++++++ ~ + +error[E0283]: type annotations needed + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:63:20 + | +LL | deref_deref_to.by_self(); + | ^^^^^^^ + | +note: multiple `impl`s satisfying `&Thing: MethodRef<_>` found + --> $DIR/suggest-fully-qualified-path-without-adjustment.rs:23:1 + | +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl MethodRef for &Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try using a fully qualified path to specify the expected types + | +LL | <&Thing as MethodRef>::by_self(deref_deref_to); + | ++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0282, E0283. +For more information about an error, try `rustc --explain E0282`. 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 cfa4a4b9d20ba..b3ca260894bc8 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 @@ -2,9 +2,13 @@ error[E0282]: type annotations needed --> $DIR/closures_in_branches.rs:21:10 | LL | |x| x.len() - | ^ consider giving this closure parameter a type + | ^ | = note: type must be known at this point +help: consider giving this closure parameter an explicit type + | +LL | |x: _| x.len() + | +++ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr b/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr index 0cdd4cc8dc3ba..9a0e71b4eed90 100644 --- a/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr +++ b/src/test/ui/type-alias-impl-trait/incomplete-inference.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/incomplete-inference.rs:6:5 | LL | None - | ^^^^ cannot infer type for type parameter `T` declared on the enum `Option` + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | None:: + | +++++ error: aborting due to previous error diff --git a/src/test/ui/type-inference/or_else-multiple-type-params.stderr b/src/test/ui/type-inference/or_else-multiple-type-params.stderr index 12a98e4d783e7..222638068ad80 100644 --- a/src/test/ui/type-inference/or_else-multiple-type-params.stderr +++ b/src/test/ui/type-inference/or_else-multiple-type-params.stderr @@ -1,13 +1,8 @@ -error[E0282]: type annotations needed - --> $DIR/or_else-multiple-type-params.rs:7:10 +error[E0282]: type annotations needed for `Result` + --> $DIR/or_else-multiple-type-params.rs:7:18 | LL | .or_else(|err| { - | ^^^^^^^ cannot infer type for type parameter `F` declared on the associated function `or_else` - | -help: consider specifying the type arguments in the method call - | -LL | .or_else::(|err| { - | ++++++++ + | ^^^^^ - help: try giving this closure an explicit return type: `-> Result` error: aborting due to previous error diff --git a/src/test/ui/type-inference/sort_by_key.stderr b/src/test/ui/type-inference/sort_by_key.stderr index 78b7386c03e1f..0a48d5756eb41 100644 --- a/src/test/ui/type-inference/sort_by_key.stderr +++ b/src/test/ui/type-inference/sort_by_key.stderr @@ -1,10 +1,10 @@ error[E0282]: type annotations needed - --> $DIR/sort_by_key.rs:3:9 + --> $DIR/sort_by_key.rs:3:40 | LL | lst.sort_by_key(|&(v, _)| v.iter().sum()); - | ^^^^^^^^^^^ cannot infer type for type parameter `K` declared on the associated function `sort_by_key` + | ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum` | -help: consider specifying the type argument in the method call +help: consider specifying the generic argument | LL | lst.sort_by_key(|&(v, _)| v.iter().sum::()); | +++++ diff --git a/src/test/ui/type-inference/unbounded-associated-type.stderr b/src/test/ui/type-inference/unbounded-associated-type.stderr index 19e2bd4513dc5..e0fecc72f3092 100644 --- a/src/test/ui/type-inference/unbounded-associated-type.stderr +++ b/src/test/ui/type-inference/unbounded-associated-type.stderr @@ -1,14 +1,13 @@ error[E0282]: type annotations needed - --> $DIR/unbounded-associated-type.rs:15:5 + --> $DIR/unbounded-associated-type.rs:15:7 | -LL | type A; - | ------- `::A` defined here -... LL | S(std::marker::PhantomData).foo(); - | ^-------------------------------- - | | - | this method call resolves to `::A` - | cannot infer type for type parameter `X` declared on the struct `S` + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData` + | +help: consider specifying the generic argument + | +LL | S(std::marker::PhantomData::).foo(); + | +++++ error: aborting due to previous error diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr index 501fa7c8c67c1..209abfe5cba49 100644 --- a/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr +++ b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr @@ -2,13 +2,12 @@ error[E0282]: type annotations needed --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:8:5 | LL | foo(); - | ^^^ cannot infer type for type parameter `T` declared on the function `foo` + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` | -help: type parameter declared here - --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:3:8 +help: consider specifying the generic arguments | -LL | fn foo() -> (T, U) { - | ^ +LL | foo::(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr b/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr index d01c3a7d4e220..d92892eeb84ed 100644 --- a/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr +++ b/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr @@ -2,13 +2,12 @@ error[E0282]: type annotations needed --> $DIR/unbounded-type-param-in-fn.rs:6:5 | LL | foo(); - | ^^^ cannot infer type for type parameter `T` declared on the function `foo` + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` | -help: type parameter declared here - --> $DIR/unbounded-type-param-in-fn.rs:1:8 +help: consider specifying the generic argument | -LL | fn foo() -> T { - | ^ +LL | foo::(); + | +++++ error: aborting due to previous error diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr index 64fdbfe7db4c8..7d7890c8b8097 100644 --- a/src/test/ui/type/type-annotation-needed.stderr +++ b/src/test/ui/type/type-annotation-needed.stderr @@ -2,19 +2,18 @@ error[E0283]: type annotations needed --> $DIR/type-annotation-needed.rs:6:5 | LL | foo(42); - | ^^^ cannot infer type for type parameter `T` declared on the function `foo` + | ^^^ cannot infer type of the type parameter `T` declared on the function `foo` | -help: type parameter declared here - --> $DIR/type-annotation-needed.rs:1:8 - | -LL | fn foo>(x: i32) {} - | ^ = note: cannot satisfy `_: Into` note: required by a bound in `foo` --> $DIR/type-annotation-needed.rs:1:11 | LL | fn foo>(x: i32) {} | ^^^^^^^^^^^^ required by this bound in `foo` +help: consider specifying the generic argument + | +LL | foo::(42); + | +++++ help: consider specifying the type argument in the function call | LL | foo::(42); diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr index 8edec6e0ea3fd..d68d5e5d40b9e 100644 --- a/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr +++ b/src/test/ui/type/type-check/cannot_infer_local_or_array.stderr @@ -1,10 +1,13 @@ error[E0282]: type annotations needed for `[_; 0]` - --> $DIR/cannot_infer_local_or_array.rs:2:13 + --> $DIR/cannot_infer_local_or_array.rs:2:9 | LL | let x = []; - | - ^^ cannot infer type - | | - | consider giving `x` the explicit type `[_; 0]`, with the type parameters specified + | ^ + | +help: consider giving `x` an explicit type, where the placeholders `_` are specified + | +LL | let x: [_; 0] = []; + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr index 69a4af4672f91..b63d2a3b61c24 100644 --- a/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr +++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr @@ -1,12 +1,13 @@ error[E0282]: type annotations needed for `Vec` - --> $DIR/cannot_infer_local_or_vec.rs:2:13 + --> $DIR/cannot_infer_local_or_vec.rs:2:9 | LL | let x = vec![]; - | - ^^^^^^ cannot infer type for type parameter `T` - | | - | consider giving `x` the explicit type `Vec`, where the type parameter `T` is specified + | ^ | - = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider giving `x` an explicit type, where the type for type parameter `T` is specified + | +LL | let x: Vec = vec![]; + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr index af7db43970442..be60cda68b9f0 100644 --- a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -1,12 +1,13 @@ error[E0282]: type annotations needed for `(Vec,)` - --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18 + --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:9 | LL | let (x, ) = (vec![], ); - | ----- ^^^^^^ cannot infer type for type parameter `T` - | | - | consider giving this pattern the explicit type `(Vec,)`, where the type parameter `T` is specified + | ^^^^^ | - = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider giving this pattern a type, where the type for type parameter `T` is specified + | +LL | let (x, ): (Vec,) = (vec![], ); + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/type/type-check/unknown_type_for_closure.rs b/src/test/ui/type/type-check/unknown_type_for_closure.rs index 0089d86e340f1..167687c187129 100644 --- a/src/test/ui/type/type-check/unknown_type_for_closure.rs +++ b/src/test/ui/type/type-check/unknown_type_for_closure.rs @@ -11,7 +11,7 @@ fn infer_ty() { } fn ambig_return() { - let x = || -> Vec<_> { Vec::new() }; //~ ERROR type annotations needed for the closure `fn() -> Vec<_>` + let x = || -> Vec<_> { Vec::new() }; //~ ERROR type annotations needed } fn main() {} 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 c3accad5f25d9..a9d0dc6e7d81c 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 @@ -1,31 +1,46 @@ -error[E0282]: type annotations needed for `Vec<_>` - --> $DIR/unknown_type_for_closure.rs:2:14 +error[E0282]: type annotations needed for the closure `fn(Vec<_>)` + --> $DIR/unknown_type_for_closure.rs:2:9 | LL | let x = |b: Vec<_>| {}; - | ^ consider giving this closure parameter a type + | ^ + | +help: consider giving `x` an explicit type, where the type for struct `Vec<_>` is specified + | +LL | let x: [closure@$DIR/unknown_type_for_closure.rs:2:13: 2:27] = |b: Vec<_>| {}; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0282]: type annotations needed --> $DIR/unknown_type_for_closure.rs:6:14 | LL | let x = |_| {}; - | ^ consider giving this closure parameter a type + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | let x = |_: _| {}; + | +++ -error[E0282]: type annotations needed - --> $DIR/unknown_type_for_closure.rs:10:14 +error[E0282]: type annotations needed for the closure `fn(_)` + --> $DIR/unknown_type_for_closure.rs:10:9 | LL | let x = |k: _| {}; - | ^ consider giving this closure parameter a type + | ^ + | +help: consider giving `x` an explicit type, where the placeholders `_` are specified + | +LL | let x: [closure@$DIR/unknown_type_for_closure.rs:10:13: 10:22] = |k: _| {}; + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -error[E0282]: type annotations needed for the closure `fn() -> Vec<_>` +error[E0282]: type annotations needed --> $DIR/unknown_type_for_closure.rs:14:28 | LL | let x = || -> Vec<_> { Vec::new() }; - | ^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec` | -help: give this closure an explicit return type without `_` placeholders +help: consider specifying the generic argument | -LL | let x = || -> Vec<_> { Vec::new() }; - | ~~~~~~ +LL | let x = || -> Vec<_> { Vec::::new() }; + | +++++ error: aborting due to 4 previous errors 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 baf218243c4c8..c1ae10efac4b4 100644 --- a/src/test/ui/type/type-path-err-node-types.stderr +++ b/src/test/ui/type/type-path-err-node-types.stderr @@ -26,7 +26,12 @@ error[E0282]: type annotations needed --> $DIR/type-path-err-node-types.rs:23:14 | LL | let _ = |a, b: _| -> _ { 0 }; - | ^ consider giving this closure parameter a type + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | let _ = |a: _, b: _| -> _ { 0 }; + | +++ error: aborting due to 5 previous errors diff --git a/src/test/ui/typeck/issue-65611.stderr b/src/test/ui/typeck/issue-65611.stderr index e3c005a0593f6..5f831291a3851 100644 --- a/src/test/ui/typeck/issue-65611.stderr +++ b/src/test/ui/typeck/issue-65611.stderr @@ -1,11 +1,8 @@ error[E0282]: type annotations needed - --> $DIR/issue-65611.rs:59:20 + --> $DIR/issue-65611.rs:59:13 | LL | let x = buffer.last().unwrap().0.clone(); - | -------^^^^-- - | | | - | | cannot infer type for type parameter `T` - | this method call resolves to `Option<&T>` + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` | = note: type must be known at this point diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs index d03001f523757..25c2dbe196fe1 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.rs @@ -6,6 +6,7 @@ fn a() { let mut closure0 = None; + //~^ ERROR type annotations needed let vec = vec![1, 2, 3]; loop { @@ -14,7 +15,6 @@ fn a() { match closure0.take() { Some(c) => { return c(); - //~^ ERROR type annotations needed } None => { } } diff --git a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr index de20a38c44750..666ab79b65c32 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr @@ -1,13 +1,14 @@ error[E0282]: type annotations needed for `Option` - --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:16:32 + --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:8:9 | LL | let mut closure0 = None; - | ------------ consider giving `closure0` the explicit type `Option`, with the type parameters specified -... -LL | return c(); - | ^^^ cannot infer type + | ^^^^^^^^^^^^ | = note: type must be known at this point +help: consider giving `closure0` an explicit type, where the placeholders `_` are specified + | +LL | let mut closure0: Option = None; + | +++++++++++ error: aborting due to previous error diff --git a/src/test/ui/unconstrained-none.stderr b/src/test/ui/unconstrained-none.stderr index fbd71bd091d0b..19ac74fdf5831 100644 --- a/src/test/ui/unconstrained-none.stderr +++ b/src/test/ui/unconstrained-none.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/unconstrained-none.rs:4:5 | LL | None; - | ^^^^ cannot infer type for type parameter `T` declared on the enum `Option` + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` + | +help: consider specifying the generic argument + | +LL | None::; + | +++++ error: aborting due to previous error diff --git a/src/test/ui/unconstrained-ref.stderr b/src/test/ui/unconstrained-ref.stderr index eb8ebb5165d18..1df6d8b446d5c 100644 --- a/src/test/ui/unconstrained-ref.stderr +++ b/src/test/ui/unconstrained-ref.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed --> $DIR/unconstrained-ref.rs:6:5 | LL | S { o: &None }; - | ^ cannot infer type for type parameter `T` declared on the struct `S` + | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `S` + | +help: consider specifying the generic argument + | +LL | S:: { o: &None }; + | +++++ error: aborting due to previous error From bc0d12cc6ccf5c6d8d9c44e67871a5b75f5a44cf Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 24 May 2022 09:57:14 +0200 Subject: [PATCH 3/7] use verbose suggestions --- .../src/infer/error_reporting/need_type_info.rs | 4 ++-- .../ui/inference/cannot-infer-partial-try-return.stderr | 9 ++++++--- .../ui/suggestions/suggest-closure-return-type-1.stderr | 9 ++++++--- .../ui/suggestions/suggest-closure-return-type-2.stderr | 7 ++++++- .../type-inference/or_else-multiple-type-params.stderr | 7 ++++++- 5 files changed, 26 insertions(+), 10 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 779735ed444af..b0b7fc6ad5af8 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 @@ -422,7 +422,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { (receiver.span.shrink_to_lo(), format!("{def_path}({adjustment}")), (receiver.span.shrink_to_hi().with_hi(successor.1), successor.0.to_string()), ]; - err.multipart_suggestion( + err.multipart_suggestion_verbose( "try using a fully qualified path to specify the expected types", suggestion, Applicability::HasPlaceholders, @@ -441,7 +441,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ], None => vec![(data.span(), format!("{}{}{}", arrow, ret, post))], }; - err.multipart_suggestion( + err.multipart_suggestion_verbose( "try giving this closure an explicit return type", suggestion, Applicability::HasPlaceholders, diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.stderr b/src/test/ui/inference/cannot-infer-partial-try-return.stderr index 3956b1a18de50..220602c124cb1 100644 --- a/src/test/ui/inference/cannot-infer-partial-try-return.stderr +++ b/src/test/ui/inference/cannot-infer-partial-try-return.stderr @@ -2,9 +2,12 @@ error[E0282]: type annotations needed for `Result<(), QualifiedError<_>>` --> $DIR/cannot-infer-partial-try-return.rs:18:13 | LL | let x = || -> Result<_, QualifiedError<_>> { - | ^^^^^^---------------------------- - | | - | help: try giving this closure an explicit return type: `Result<(), QualifiedError<_>>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try giving this closure an explicit return type + | +LL | let x = || -> Result<(), QualifiedError<_>> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr index ba70bf104bf30..3116211b52c90 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr @@ -2,9 +2,12 @@ error[E0282]: type annotations needed for `[_; 0]` --> $DIR/suggest-closure-return-type-1.rs:4:18 | LL | unbound_drop(|| -> _ { [] }); - | ^^^^^^- - | | - | help: try giving this closure an explicit return type: `[_; 0]` + | ^^^^^^^ + | +help: try giving this closure an explicit return type + | +LL | unbound_drop(|| -> [_; 0] { [] }); + | ~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr index f2cb6d291b3f8..f368e7de467ca 100644 --- a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed for `[_; 0]` --> $DIR/suggest-closure-return-type-2.rs:4:18 | LL | unbound_drop(|| { [] }) - | ^^ - help: try giving this closure an explicit return type: `-> [_; 0]` + | ^^ + | +help: try giving this closure an explicit return type + | +LL | unbound_drop(|| -> [_; 0] { [] }) + | +++++++++ error: aborting due to previous error diff --git a/src/test/ui/type-inference/or_else-multiple-type-params.stderr b/src/test/ui/type-inference/or_else-multiple-type-params.stderr index 222638068ad80..6ac63a91ee9ac 100644 --- a/src/test/ui/type-inference/or_else-multiple-type-params.stderr +++ b/src/test/ui/type-inference/or_else-multiple-type-params.stderr @@ -2,7 +2,12 @@ error[E0282]: type annotations needed for `Result` --> $DIR/or_else-multiple-type-params.rs:7:18 | LL | .or_else(|err| { - | ^^^^^ - help: try giving this closure an explicit return type: `-> Result` + | ^^^^^ + | +help: try giving this closure an explicit return type + | +LL | .or_else(|err| -> Result { + | +++++++++++++++++++ error: aborting due to previous error From 69d575e58dc21175a7365577c84c435a243029eb Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 26 May 2022 11:40:23 +0200 Subject: [PATCH 4/7] eagerly fetch the typeck_results --- .../infer/error_reporting/need_type_info.rs | 80 ++++++++++++------- 1 file changed, 52 insertions(+), 28 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 b0b7fc6ad5af8..1c06c45a923f4 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 @@ -12,7 +12,7 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMut use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, InferConst}; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{Ty, TyCtxt, TypeckResults}; use rustc_span::symbol::{kw, Ident}; use rustc_span::{BytePos, Span}; use std::borrow::Cow; @@ -272,7 +272,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { parent: None, } } else { - // FIXME: This code seems a bit wrong, idk. + // If we end up here the `FindInferSourceVisitor` + // won't work, as its expected argument isn't an inference variable. + // + // FIXME: Ideally we should look into the generic constant + // to figure out which inference var is actually unresolved so that + // this path is unreachable. let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::ValueNS); if let Some(highlight) = highlight { printer.region_highlight_mode = highlight; @@ -289,6 +294,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + /// Used as a fallback in [InferCtxt::emit_inference_failure_err] + /// in case we weren't able to get a better error. + fn bad_inference_failure_err( + &self, + span: Span, + arg_data: InferenceDiagnosticsData, + error_code: TypeAnnotationNeeded, + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { + let error_code = error_code.into(); + let mut err = self.tcx.sess.struct_span_err_with_code( + span, + &format!("type annotations needed"), + error_code, + ); + err.span_label(span, arg_data.cannot_infer_msg()); + err + } + pub fn emit_inference_failure_err( &self, body_id: Option, @@ -301,7 +324,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let arg = self.resolve_vars_if_possible(arg); let arg_data = self.extract_inference_diagnostics_data(arg, None); - let mut local_visitor = FindInferSourceVisitor::new(&self, arg); + let Some(typeck_results) = self.in_progress_typeck_results else { + // If we don't have any typeck results we're outside + // of a body, so we won't be able to get better info + // here. + return self.bad_inference_failure_err(span, arg_data, error_code); + }; + let typeck_results = typeck_results.borrow(); + let typeck_results = &typeck_results; + + let mut local_visitor = FindInferSourceVisitor::new(&self, typeck_results, arg); if let Some(body_id) = body_id { let expr = self.tcx.hir().expect_expr(body_id.hir_id); debug!(?expr); @@ -309,17 +341,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let Some(InferSource { span, kind }) = local_visitor.infer_source else { - let error_code = error_code.into(); - let mut err = self.tcx.sess.struct_span_err_with_code( - span, - &format!("type annotations needed"), - error_code, - ); - err.span_label( - span, - arg_data.cannot_infer_msg(), - ); - return err; + return self.bad_inference_failure_err(span, arg_data, error_code) }; let error_code = error_code.into(); @@ -394,8 +416,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } InferSourceKind::FullyQualifiedMethodCall { receiver, successor, substs, def_id } => { - let typeck_results = self.in_progress_typeck_results.unwrap(); - let typeck_results = typeck_results.borrow(); let printer = fmt_printer(self, Namespace::ValueNS); let def_path = printer.print_def_path(def_id, substs).unwrap().into_buffer(); @@ -548,6 +568,8 @@ struct InsertableGenericArgs<'tcx> { /// For details on how we rank spots, see [Self::source_cost] struct FindInferSourceVisitor<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, + typeck_results: &'a TypeckResults<'tcx>, + target: GenericArg<'tcx>, attempt: usize, @@ -556,9 +578,15 @@ struct FindInferSourceVisitor<'a, 'tcx> { } impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { - fn new(infcx: &'a InferCtxt<'a, 'tcx>, target: GenericArg<'tcx>) -> Self { + fn new( + infcx: &'a InferCtxt<'a, 'tcx>, + typeck_results: &'a TypeckResults<'tcx>, + target: GenericArg<'tcx>, + ) -> Self { FindInferSourceVisitor { infcx, + typeck_results, + target, attempt: 0, @@ -603,7 +631,6 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { variant_cost + generic_args.iter().map(|&arg| arg_cost(arg)).sum::() } InferSourceKind::FullyQualifiedMethodCall { substs, .. } => { - // FIXME: We should also consider the cost of lifetimes and constants here. 20 + substs.iter().map(|arg| arg_cost(arg)).sum::() } InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => { @@ -625,7 +652,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } fn opt_node_type(&self, hir_id: HirId) -> Option> { - let ty = self.infcx.in_progress_typeck_results?.borrow().node_type_opt(hir_id); + let ty = self.typeck_results.node_type_opt(hir_id); self.infcx.resolve_vars_if_possible(ty) } @@ -698,10 +725,9 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Box> + 'a> { let tcx = self.infcx.tcx; - let typeck_results = self.infcx.in_progress_typeck_results.unwrap().borrow(); match expr.kind { hir::ExprKind::Path(ref path) => { - if let Some(substs) = typeck_results.node_substs_opt(expr.hir_id) { + if let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) { return self.path_inferred_subst_iter(expr.hir_id, substs, path); } } @@ -713,13 +739,13 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { } } hir::ExprKind::MethodCall(segment, _, _) => { - if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) { + if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) { let generics = tcx.generics_of(def_id); let insertable: Option<_> = try { if generics.has_impl_trait() { None? } - let substs = typeck_results.node_substs_opt(expr.hir_id)?; + let substs = self.typeck_results.node_substs_opt(expr.hir_id)?; let span = tcx.hir().span(segment.hir_id?); let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi()); InsertableGenericArgs { @@ -793,13 +819,12 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { qpath: &'tcx hir::QPath<'tcx>, ) -> Box> + 'a> { let tcx = self.infcx.tcx; - let typeck_results = self.infcx.in_progress_typeck_results.unwrap().borrow(); match qpath { hir::QPath::Resolved(_self_ty, path) => { Box::new(self.resolved_path_inferred_subst_iter(path, substs)) } hir::QPath::TypeRelative(ty, segment) => { - let Some(def_id) = typeck_results.type_dependent_def_id(hir_id) else { + let Some(def_id) = self.typeck_results.type_dependent_def_id(hir_id) else { return Box::new(iter::empty()); }; @@ -996,10 +1021,9 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { .any(|generics| generics.has_impl_trait()) }; if let ExprKind::MethodCall(path, args, span) = expr.kind - && let Some(typeck_results) = self.infcx.in_progress_typeck_results - && let Some(substs) = typeck_results.borrow().node_substs_opt(expr.hir_id) + && let Some(substs) = self.typeck_results.node_substs_opt(expr.hir_id) && substs.iter().any(|arg| self.generic_arg_contains_target(arg)) - && let Some(def_id) = typeck_results.borrow().type_dependent_def_id(expr.hir_id) + && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) && self.infcx.tcx.trait_of_item(def_id).is_some() && !has_impl_trait(def_id) { From 681736a6b2297016bcf6964be3e14a77add276d7 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 26 May 2022 12:26:30 +0200 Subject: [PATCH 5/7] `generic_arg_contains_target`: ignore closures --- .../infer/error_reporting/need_type_info.rs | 10 +++++++-- .../cannot-infer-closure-circular.rs | 4 ++-- .../cannot-infer-closure-circular.stderr | 12 +++++----- .../unknown_type_for_closure.stderr | 22 +++++-------------- 4 files changed, 22 insertions(+), 26 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 1c06c45a923f4..7b5c377f7b4ca 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 @@ -700,8 +700,14 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { match inner.unpack() { GenericArgKind::Lifetime(_) => {} GenericArgKind::Type(ty) => { - if matches!(ty.kind(), ty::Opaque(..)) { - // Opaque types can't be named by the user right now + if matches!(ty.kind(), ty::Opaque(..) | ty::Closure(..) | ty::Generator(..)) { + // Opaque types can't be named by the user right now. + // + // Both the generic arguments of closures and generators can + // also not be named. We may want to only look into the closure + // signature in case it has no captures, as that can be represented + // using `fn(T) -> R`. + // FIXME(type_alias_impl_trait): These opaque types // can actually be named, so it would make sense to // adjust this case and add a test for it. diff --git a/src/test/ui/inference/cannot-infer-closure-circular.rs b/src/test/ui/inference/cannot-infer-closure-circular.rs index affb481496d02..ae879db68ec13 100644 --- a/src/test/ui/inference/cannot-infer-closure-circular.rs +++ b/src/test/ui/inference/cannot-infer-closure-circular.rs @@ -4,10 +4,10 @@ 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| { let v = r?; Ok(v) }; - let _ = x(x(Ok(()))); + let _ = x(x(Ok(()))); //~ ERROR type annotations needed for `Result<(), E>` } diff --git a/src/test/ui/inference/cannot-infer-closure-circular.stderr b/src/test/ui/inference/cannot-infer-closure-circular.stderr index b706cd2bc36e8..3ad8e3cda16e5 100644 --- a/src/test/ui/inference/cannot-infer-closure-circular.stderr +++ b/src/test/ui/inference/cannot-infer-closure-circular.stderr @@ -1,13 +1,13 @@ error[E0282]: type annotations needed for `Result<(), E>` - --> $DIR/cannot-infer-closure-circular.rs:7:14 + --> $DIR/cannot-infer-closure-circular.rs:12:9 | -LL | let x = |r| { - | ^ +LL | let _ = x(x(Ok(()))); + | ^ | -help: consider giving this closure parameter an explicit type, where the type for type parameter `E` is specified +help: consider giving this pattern a type, where the type for type parameter `E` is specified | -LL | let x = |r: Result<(), E>| { - | +++++++++++++++ +LL | let _: Result<(), E> = x(x(Ok(()))); + | +++++++++++++++ error: aborting due to previous error 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 a9d0dc6e7d81c..9ae97f390d3e4 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 @@ -1,13 +1,8 @@ -error[E0282]: type annotations needed for the closure `fn(Vec<_>)` - --> $DIR/unknown_type_for_closure.rs:2:9 +error[E0282]: type annotations needed + --> $DIR/unknown_type_for_closure.rs:2:13 | LL | let x = |b: Vec<_>| {}; - | ^ - | -help: consider giving `x` an explicit type, where the type for struct `Vec<_>` is specified - | -LL | let x: [closure@$DIR/unknown_type_for_closure.rs:2:13: 2:27] = |b: Vec<_>| {}; - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + | ^^^^^^^^^^^^^^ cannot infer type for struct `Vec<_>` error[E0282]: type annotations needed --> $DIR/unknown_type_for_closure.rs:6:14 @@ -20,16 +15,11 @@ help: consider giving this closure parameter an explicit type LL | let x = |_: _| {}; | +++ -error[E0282]: type annotations needed for the closure `fn(_)` - --> $DIR/unknown_type_for_closure.rs:10:9 +error[E0282]: type annotations needed + --> $DIR/unknown_type_for_closure.rs:10:14 | LL | let x = |k: _| {}; - | ^ - | -help: consider giving `x` an explicit type, where the placeholders `_` are specified - | -LL | let x: [closure@$DIR/unknown_type_for_closure.rs:10:13: 10:22] = |k: _| {}; - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + | ^ cannot infer type error[E0282]: type annotations needed --> $DIR/unknown_type_for_closure.rs:14:28 From 8b089a1a9f8849f70a98a3e489cae92aaac78cb4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 27 May 2022 08:25:50 +0200 Subject: [PATCH 6/7] remove unnecessary change --- .../ui/span/issue-42234-unknown-receiver-type.full.stderr | 8 ++++---- .../issue-42234-unknown-receiver-type.generic_arg.stderr | 6 +++--- src/test/ui/span/issue-42234-unknown-receiver-type.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr index 98e45ff9d0758..cd3ffdc6f9d60 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.full.stderr @@ -1,14 +1,14 @@ error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:9:24 | -LL | let x: Option<_> = None::<_>; - | ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` +LL | let x: Option<_> = None; + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` | = note: type must be known at this point help: consider specifying the generic argument | -LL | let x: Option<_> = None::<_>; - | ~~~~~ +LL | let x: Option<_> = None::; + | +++++ error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr index 0902ffa26217f..b6a3f07f5715f 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr @@ -1,14 +1,14 @@ error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:9:24 | -LL | let x: Option<_> = None::<_>; - | ^^^^^^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` +LL | let x: Option<_> = None; + | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option` | = note: type must be known at this point help: consider specifying the generic argument | LL | let x: Option<_> = None::; - | ~~~~~ + | +++++ error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:15:10 diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.rs b/src/test/ui/span/issue-42234-unknown-receiver-type.rs index 93c66eb130157..fd53121204c78 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.rs +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.rs @@ -6,7 +6,7 @@ // the fix of which this tests). fn shines_a_beacon_through_the_darkness() { - let x: Option<_> = None::<_>; //~ ERROR type annotations needed + let x: Option<_> = None; //~ ERROR type annotations needed x.unwrap().method_that_could_exist_on_some_type(); } From b343a466c650cd43d81b7fc98d3571eda64fe35b Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 2 Jun 2022 10:25:47 +0200 Subject: [PATCH 7/7] rebase --- src/test/ui/issues/issue-16966.stderr | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/issues/issue-16966.stderr b/src/test/ui/issues/issue-16966.stderr index 0b261b3201bee..6eb56ca5516bf 100644 --- a/src/test/ui/issues/issue-16966.stderr +++ b/src/test/ui/issues/issue-16966.stderr @@ -6,6 +6,7 @@ LL | panic!(std::default::Default::default()); | = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider specifying the generic argument + --> $SRC_DIR/std/src/panic.rs:LL:COL | LL | $crate::rt::begin_panic::($msg) | +++++