diff --git a/compiler/rustc_error_codes/src/error_codes/E0282.md b/compiler/rustc_error_codes/src/error_codes/E0282.md index 49d2205f92c2a..04381f2bed8c2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0282.md +++ b/compiler/rustc_error_codes/src/error_codes/E0282.md @@ -3,7 +3,7 @@ The compiler could not infer a type and asked for a type annotation. Erroneous code example: ```compile_fail,E0282 -let x = "hello".chars().rev().collect(); +let x = None; ``` This error indicates that type inference did not result in one unique possible 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 21023a06bb2d9..9c7802cfef2fd 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 @@ -182,7 +182,7 @@ fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String { pub enum TypeAnnotationNeeded { /// ```compile_fail,E0282 - /// let x = "hello".chars().rev().collect(); + /// let _ = None; /// ``` E0282, /// An implementation cannot be chosen unambiguously because of lack of information. @@ -342,6 +342,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { span: Span, arg: GenericArg<'tcx>, error_code: TypeAnnotationNeeded, + turbofish_suggestions: &[String], ) -> DiagnosticBuilder<'tcx> { let arg = self.resolve_vars_if_possible(&arg); let arg_data = self.extract_inference_diagnostics_data(arg, None); @@ -365,12 +366,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { None }; printer.name_resolver = Some(Box::new(&getter)); - let _ = if let ty::FnDef(..) = ty.kind() { + let _ = 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.fn_sig(self.tcx).print(printer) - } else { - ty.print(printer) + ty::FnDef(..) => ty.fn_sig(self.tcx).print(printer), + ty::Ref(_, ref_ty, mutability) => { + match ref_ty.kind() { + ty::Array(ty, _) => { + // Do not suggest `&[_; 0]`, instead suggest `&[_]`. + let _ = ty.print(printer); + return format!("&{}[{}]", mutability.prefix_str(), s); + } + _ => ty.print(printer), + } + } + _ => ty.print(printer), }; s }; @@ -448,7 +458,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { error_code, ); - let suffix = match local_visitor.found_node_ty { + let (suffix, sugg_ty) = match local_visitor.found_node_ty { Some(ty) if ty.is_closure() => { let substs = if let ty::Closure(_, substs) = *ty.kind() { substs } else { unreachable!() }; @@ -483,20 +493,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // 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) + ( + format!("a boxed closure type like `Box {}>`", args, ret), + format!("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 type parameters specified", ty) + ( + format!("the explicit type `{}`, with the type parameters specified", ty), + ty.to_string(), + ) } Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => { let ty = ty_to_string(ty); - format!( - "the explicit type `{}`, where the type parameter `{}` is specified", - ty, arg_data.name, + ( + format!( + "the explicit type `{}`, where the type parameter `{}` is specified", + ty, arg_data.name, + ), + ty.to_string(), ) } - _ => "a type".to_string(), + _ if turbofish_suggestions.len() == 1 => ( + format!("the explicit type `{}`", turbofish_suggestions[0]), + turbofish_suggestions[0].clone(), + ), + _ => ("a type".to_string(), "Type".to_string()), }; if let Some(e) = local_visitor.found_exact_method_call { @@ -527,7 +550,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | 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); + self.annotate_method_call(segment, e, &mut err, turbofish_suggestions); } } else if let Some(pattern) = local_visitor.found_arg_pattern { // We don't want to show the default label for closures. @@ -551,18 +574,49 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { 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(DesugaringKind::ForLoop(_)) => { - "the element type for this iterator is not specified".to_string() - } - _ => format!("this needs {}", suffix), - } + if let (hir::Node::Local(local), None) = ( + self.tcx.hir().get(self.tcx.hir().get_parent_node(pattern.hir_id)), + pattern.span.desugaring_kind(), + ) { + let (span, prefix) = match local.ty { + Some(ty) => (ty.span, ""), + None => (local.pat.span.shrink_to_hi(), ": "), + }; + let msg = format!("consider giving this binding {}", suffix); + match &turbofish_suggestions[..] { + [] => err.span_suggestion_verbose( + span, + &msg, + format!("{}{}", prefix, sugg_ty), + Applicability::HasPlaceholders, + ), + [ty] => err.span_suggestion_verbose( + span, + &msg, + format!("{}{}", prefix, ty), + Applicability::MachineApplicable, + ), + _ => err.span_suggestions( + span, + &msg, + turbofish_suggestions.into_iter().map(|ty| format!("{}{}", prefix, ty)), + Applicability::MaybeIncorrect, + ), + }; } else { - format!("consider giving this pattern {}", suffix) - }; - err.span_label(pattern.span, msg); + let msg = if let Some(simple_ident) = pattern.simple_ident() { + match pattern.span.desugaring_kind() { + None => format!("consider giving `{}` {}", simple_ident, suffix), + Some(DesugaringKind::ForLoop(_)) => { + "the element type for this iterator is not specified".to_string() + } + _ => 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, ..) = &e.kind { // Suggest specifying type params or point out the return type of the call: @@ -591,7 +645,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | 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); + self.annotate_method_call(segment, e, &mut err, turbofish_suggestions); } } // Instead of the following: @@ -641,29 +695,49 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { segment: &hir::PathSegment<'_>, e: &Expr<'_>, err: &mut DiagnosticBuilder<'_>, + turbofish_suggestions: &[String], ) { 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() { - 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, + let msg = format!( + "consider specifying the type argument{} in the method call", + pluralize!(generics.params.len()), ); + if turbofish_suggestions.is_empty() { + err.span_suggestion_verbose( + segment.ident.span.shrink_to_hi(), + &msg, + format!( + "::<{}>", + generics + .params + .iter() + .map(|p| p.name.to_string()) + .collect::>() + .join(", ") + ), + Applicability::HasPlaceholders, + ); + } else { + if turbofish_suggestions.len() == 1 { + err.span_suggestion_verbose( + segment.ident.span.shrink_to_hi(), + &msg, + format!("::<{}>", turbofish_suggestions[0]), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestions( + segment.ident.span.shrink_to_hi(), + &msg, + turbofish_suggestions.into_iter().map(|ty| format!("::<{}>", ty)), + Applicability::MaybeIncorrect, + ); + } + } } else { let sig = self.tcx.fn_sig(did); let bound_output = sig.output(); @@ -718,18 +792,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> String { if type_name == "_" { format!("cannot infer {}", kind_str) - } else { - let parent_desc = if let Some(parent_name) = parent_name { - let parent_type_descr = if let Some(parent_descr) = parent_descr { - format!(" the {}", parent_descr) - } else { - "".into() - }; - - format!(" declared on{} `{}`", parent_type_descr, parent_name) - } else { - "".to_string() - }; + } else if let (Some(parent_name), Some(parent_descr)) = (parent_name, parent_descr) { + let parent_type_descr = format!(" the {}", parent_descr); + let parent_desc = format!(" declared on{} `{}`", parent_type_descr, parent_name); // FIXME: We really shouldn't be dealing with strings here // but instead use a sensible enum for cases like this. @@ -739,7 +804,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "cannot infer {} {} {} `{}`{}", kind_str, preposition, descr, type_name, parent_desc ) - .into() + } else { + format!("cannot infer type for {} `{}`", descr, type_name) } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index f8bd3ab96e254..3631f710560dd 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -34,7 +34,7 @@ use crate::traits::query::normalize::AtExt as _; use on_unimplemented::InferCtxtExt as _; use suggestions::InferCtxtExt as _; -pub use rustc_infer::traits::error_reporting::*; +pub use rustc_infer::traits::{self, error_reporting::*}; pub trait InferCtxtExt<'tcx> { fn report_fulfillment_errors( @@ -1462,8 +1462,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let bound_predicate = predicate.bound_atom(); let mut err = match bound_predicate.skip_binder() { ty::PredicateAtom::Trait(data, _) => { - let trait_ref = bound_predicate.rebind(data.trait_ref); - debug!("trait_ref {:?}", trait_ref); + let self_ty = data.trait_ref.self_ty(); if predicate.references_error() { return; @@ -1504,15 +1503,29 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // avoid inundating the user with unnecessary errors, but we now // check upstream for type errors and don't add the obligations to // begin with in those cases. - if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { - self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0282).emit(); - return; + let is_sized = self.tcx.lang_items().sized_trait() == Some(data.trait_ref.def_id); + + // Try to find possible types that would satisfy the bounds in the type param to + // give an appropriate turbofish suggestion. + let turbofish_suggestions = + self.get_turbofish_suggestions(obligation, data, self_ty); + let mut err = self.emit_inference_failure_err( + body_id, + span, + subst, + if is_sized { ErrorCode::E0282 } else { ErrorCode::E0283 }, + &turbofish_suggestions, + ); + if !is_sized { + err.note(&format!("cannot satisfy `{}`", predicate)); } - let mut err = - self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283); - err.note(&format!("cannot satisfy `{}`", predicate)); if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { - self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); + self.suggest_fully_qualified_path( + &mut err, + def_id, + span, + data.trait_ref.def_id, + ); } else if let ( Ok(ref snippet), ObligationCauseCode::BindingObligation(ref def_id, _), @@ -1522,6 +1535,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let generics = self.tcx.generics_of(*def_id); if generics.params.iter().any(|p| p.name != kw::SelfUpper) && !snippet.ends_with('>') + && !span.from_expansion() { // FIXME: To avoid spurious suggestions in functions where type arguments // where already supplied, we check the snippet to make sure it doesn't @@ -1544,25 +1558,55 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { // | // = note: cannot satisfy `_: Tt` - err.span_suggestion_verbose( - span.shrink_to_hi(), - &format!( - "consider specifying the type argument{} in the function call", - pluralize!(generics.params.len()), - ), - format!( - "::<{}>", - generics - .params - .iter() - .map(|p| p.name.to_string()) - .collect::>() - .join(", ") - ), - Applicability::HasPlaceholders, + let msg = format!( + "consider specifying the type argument{} in the function call", + pluralize!(generics.params.len()), ); + if turbofish_suggestions.is_empty() { + err.span_suggestion_verbose( + span.shrink_to_hi(), + &msg, + format!( + "::<{}>", + generics + .params + .iter() + // Do not suggest `foo::<'a, T>()` + .filter(|p| !matches!( + p.kind, + ty::GenericParamDefKind::Lifetime + )) + .map(|p| p.name.to_string()) + .collect::>() + .join(", ") + ), + Applicability::HasPlaceholders, + ); + } else { + if turbofish_suggestions.len() == 1 { + err.span_suggestion_verbose( + span.shrink_to_hi(), + &msg, + format!("::<{}>", turbofish_suggestions[0]), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestions( + span.shrink_to_hi(), + &msg, + turbofish_suggestions + .into_iter() + .map(|ty| format!("::<{}>", ty)), + Applicability::MaybeIncorrect, + ); + } + } } } + if is_sized { + err.emit(); + return; + } err } @@ -1573,7 +1617,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { return; } - self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282) + self.emit_inference_failure_err(body_id, span, arg, ErrorCode::E0282, &[]) } ty::PredicateAtom::Subtype(data) => { @@ -1584,7 +1628,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let SubtypePredicate { a_is_expected: _, a, b } = data; // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282) + self.emit_inference_failure_err(body_id, span, a.into(), ErrorCode::E0282, &[]) } ty::PredicateAtom::Projection(data) => { let trait_ref = bound_predicate.rebind(data).to_poly_trait_ref(self.tcx); @@ -1600,6 +1644,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { span, self_ty.into(), ErrorCode::E0284, + &[], ); err.note(&format!("cannot satisfy `{}`", predicate)); err diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index efa9bd633ba8c..525a98ec55f98 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -5,8 +5,9 @@ use super::{ use crate::autoderef::Autoderef; use crate::infer::InferCtxt; -use crate::traits::normalize_projection_type; +use crate::traits::{self, normalize_projection_type}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style}; use rustc_hir as hir; @@ -15,14 +16,15 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; +use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{ self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty, - TyCtxt, TypeFoldable, WithConstness, + TyCtxt, TypeAndMut, TypeFoldable, TypeckResults, WithConstness, }; -use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; +use std::cmp::Ordering; use std::fmt; use super::InferCtxtPrivExt; @@ -38,6 +40,13 @@ pub enum GeneratorInteriorOrUpvar { // This trait is public to expose the diagnostics methods to clippy. pub trait InferCtxtExt<'tcx> { + fn get_turbofish_suggestions( + &self, + obligation: &PredicateObligation<'tcx>, + data: ty::TraitPredicate<'tcx>, + self_ty: Ty<'tcx>, + ) -> Vec; + fn suggest_restricting_param_bound( &self, err: &mut DiagnosticBuilder<'_>, @@ -317,6 +326,86 @@ fn suggest_restriction( } impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { + /// Try to find possible types that would satisfy the bounds in the type param to give an + /// appropriate turbofish suggestion. + fn get_turbofish_suggestions( + &self, + obligation: &PredicateObligation<'tcx>, + data: ty::TraitPredicate<'tcx>, + self_ty: Ty<'tcx>, + ) -> Vec { + let mut turbofish_suggestions = FxHashSet::default(); + self.tcx.for_each_relevant_impl(data.trait_ref.def_id, self_ty, |impl_def_id| { + self.probe(|_| { + let trait_args = InternalSubsts::identity_for_item(self.tcx, data.trait_ref.def_id); + let impl_args = traits::specialize::fulfill_implication( + self, + obligation.param_env, + data.trait_ref, + impl_def_id, + ); + let substs = match impl_args { + Ok(impl_args) => trait_args.rebase_onto(self.tcx, impl_def_id, impl_args), + _ => return, + }; + let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); + + let cause = traits::ObligationCause::dummy(); + let mut selcx = SelectionContext::new(&self); + let param_env = obligation.param_env.clone(); + let (target_trait_ref, obligations) = traits::util::impl_trait_ref_and_oblig( + &mut selcx, + param_env, + impl_def_id, + substs, + ); + self.resolve_vars_if_possible(&target_trait_ref); + if let Ok(eval_result) = selcx.evaluate_predicates( + Some(Obligation::new( + cause.clone(), + param_env, + target_trait_ref.without_const().to_predicate(self.tcx), + )) + .into_iter() + .chain(obligations), + ) { + if eval_result.must_apply_modulo_regions() { + turbofish_suggestions.insert(trait_ref.self_ty()); + } + }; + }) + }); + // Sort types by always suggesting `Vec<_>` and `String` first, as they are the + // most likely desired types. + let mut turbofish_suggestions = turbofish_suggestions.into_iter().collect::>(); + turbofish_suggestions.sort_by(|left, right| { + let vec_type = self.tcx.get_diagnostic_item(sym::vec_type); + let string_type = self.tcx.get_diagnostic_item(sym::string_type); + match (&left.kind(), &right.kind()) { + ( + ty::Adt(ty::AdtDef { did: left, .. }, _), + ty::Adt(ty::AdtDef { did: right, .. }, _), + ) if Some(*left) == vec_type && Some(*right) == string_type => Ordering::Less, + ( + ty::Adt(ty::AdtDef { did: left, .. }, _), + ty::Adt(ty::AdtDef { did: right, .. }, _), + ) if Some(*right) == vec_type && Some(*left) == string_type => Ordering::Greater, + (ty::Adt(ty::AdtDef { did, .. }, _), _) + if Some(*did) == vec_type || Some(*did) == string_type => + { + Ordering::Less + } + (_, ty::Adt(ty::AdtDef { did, .. }, _)) + if Some(*did) == vec_type || Some(*did) == string_type => + { + Ordering::Greater + } + _ => left.to_string().cmp(&right.to_string()), + } + }); + turbofish_suggestions.into_iter().map(|ty| ty.to_string()).collect() + } + fn suggest_restricting_param_bound( &self, mut err: &mut DiagnosticBuilder<'_>, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4cc4bc0acdab6..2eea2bb7cd564 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -403,20 +403,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) } + crate fn evaluate_predicates( + &mut self, + predicates: impl Iterator>, + ) -> Result { + self.evaluate_predicates_recursively( + TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), + predicates, + ) + } + /// Evaluates the predicates in `predicates` recursively. Note that /// this applies projections in the predicates, and therefore /// is run within an inference probe. - fn evaluate_predicates_recursively<'o, I>( + fn evaluate_predicates_recursively<'o>( &mut self, stack: TraitObligationStackList<'o, 'tcx>, - predicates: I, - ) -> Result - where - I: IntoIterator> + std::fmt::Debug, - { + predicates: impl Iterator>, + ) -> Result { let mut result = EvaluatedToOk; - debug!(?predicates, "evaluate_predicates_recursively"); for obligation in predicates { + debug!(?obligation, "evaluate_predicates_recursively obligation"); let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?; if let EvaluatedToErr = eval { // fast-path - EvaluatedToErr is the top of the lattice, @@ -484,7 +491,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) { Some(mut obligations) => { self.add_depth(obligations.iter_mut(), obligation.recursion_depth); - self.evaluate_predicates_recursively(previous_stack, obligations) + self.evaluate_predicates_recursively( + previous_stack, + obligations.into_iter(), + ) } None => Ok(EvaluatedToAmbig), }, @@ -508,8 +518,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match project::poly_project_and_unify_type(self, &project_obligation) { Ok(Ok(Some(mut subobligations))) => { self.add_depth(subobligations.iter_mut(), obligation.recursion_depth); - let result = self - .evaluate_predicates_recursively(previous_stack, subobligations); + let result = self.evaluate_predicates_recursively( + previous_stack, + subobligations.into_iter(), + ); if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate(self, data) { @@ -1245,7 +1257,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result { self.evaluation_probe(|this| { match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { - Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations), + Ok(obligations) => { + this.evaluate_predicates_recursively(stack.list(), obligations.into_iter()) + } Err(()) => Ok(EvaluatedToErr), } }) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 4d81a3baa0edc..ef311dbef0aea 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -176,7 +176,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, /// generics of `target_impl`, including both those needed to unify with /// `source_trait_ref` and those whose identity is determined via a where /// clause in the impl. -fn fulfill_implication<'a, 'tcx>( +crate fn fulfill_implication<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, source_trait_ref: ty::TraitRef<'tcx>, diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 9990f86a36b13..2027b741abbdb 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -813,7 +813,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace); let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs)); - self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized); + self.require_type_is_sized_deferred(lhs_ty, lhs.span, traits::AssignmentLhsSized); if lhs_ty.references_error() || rhs_ty.references_error() { self.tcx.ty_error() diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 017b0abd1d607..c981188e49f2a 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1396,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282) + self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, &[]) .note("type must be known at this point") .emit(); } diff --git a/compiler/rustc_typeck/src/check/gather_locals.rs b/compiler/rustc_typeck/src/check/gather_locals.rs index 1d505cfa69804..2bffdacfb2b1e 100644 --- a/compiler/rustc_typeck/src/check/gather_locals.rs +++ b/compiler/rustc_typeck/src/check/gather_locals.rs @@ -94,7 +94,11 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { let var_ty = self.assign(p.span, p.hir_id, None); if !self.fcx.tcx.features().unsized_locals { - self.fcx.require_type_is_sized(var_ty, p.span, traits::VariableType(p.hir_id)); + self.fcx.require_type_is_sized_deferred( + var_ty, + p.span, + traits::VariableType(p.hir_id), + ); } debug!( diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 5363702a5be6d..055ee12e624b6 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -656,6 +656,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { self.span.to_span(self.tcx), t.into(), E0282, + &[], ) .emit(); } @@ -669,6 +670,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { self.span.to_span(self.tcx), c.into(), E0282, + &[], ) .emit(); } 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..3f5cabe2ba0a5 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 + | ^^^^^^ cannot infer type | = note: type must be known at this point +help: consider giving this binding a type + | +LL | let [_, _]: Type = a.into(); + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/async-await/unresolved_type_param.rs b/src/test/ui/async-await/unresolved_type_param.rs index d313691b38857..650502ab644d9 100644 --- a/src/test/ui/async-await/unresolved_type_param.rs +++ b/src/test/ui/async-await/unresolved_type_param.rs @@ -10,9 +10,9 @@ async fn foo() { //~^ ERROR type inside `async fn` body must be known in this context //~| ERROR type inside `async fn` body must be known in this context //~| ERROR type inside `async fn` body must be known in this context - //~| NOTE cannot infer type for type parameter `T` - //~| NOTE cannot infer type for type parameter `T` - //~| NOTE cannot infer type for type parameter `T` + //~| NOTE cannot infer type for type parameter `T` declared on the function `bar + //~| NOTE cannot infer type for type parameter `T` declared on the function `bar + //~| NOTE cannot infer type for type parameter `T` declared on the function `bar //~| NOTE the type is part of the `async fn` body because of this `await` //~| NOTE the type is part of the `async fn` body because of this `await` //~| NOTE the type is part of the `async fn` body because of this `await` 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..cd5539d2b9a6f 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 @@ -3,6 +3,11 @@ error[E0282]: type annotations needed | LL | with_closure(|x: u32, y| {}); | ^ consider giving this closure parameter a type + | +help: consider specifying the type arguments in the function call + | +LL | with_closure::(|x: u32, y| {}); + | ^^^^^^^^^^^ 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 e84ff8baeea53..16f371cb4c04c 100644 --- a/src/test/ui/const-generics/infer/issue-77092.stderr +++ b/src/test/ui/const-generics/infer/issue-77092.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-77092.rs:13:26 | LL | println!("{:?}", take_array_from_mut(&mut arr, i)); - | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `{_: usize}` + | ^^^^^^^^^^^^^^^^^^^ cannot infer type for the constant `{_: usize}` 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 dd281e911da96..be754ff78feed 100644 --- a/src/test/ui/consts/issue-64662.stderr +++ b/src/test/ui/consts/issue-64662.stderr @@ -3,12 +3,22 @@ error[E0282]: type annotations needed | LL | A = foo(), | ^^^ cannot infer type for type parameter `T` declared on the function `foo` + | +help: consider specifying the type argument in the function call + | +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` + | +help: consider specifying the type argument in the function call + | +LL | B = foo::(), + | ^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0282.rs b/src/test/ui/error-codes/E0282.rs index 9bd16abb7bb83..f3147572dbcc9 100644 --- a/src/test/ui/error-codes/E0282.rs +++ b/src/test/ui/error-codes/E0282.rs @@ -1,3 +1,3 @@ fn main() { - let x = "hello".chars().rev().collect(); //~ ERROR E0282 + None; //~ ERROR E0282 } diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr index 0f610a5e42f65..5ff0658339554 100644 --- a/src/test/ui/error-codes/E0282.stderr +++ b/src/test/ui/error-codes/E0282.stderr @@ -1,8 +1,8 @@ error[E0282]: type annotations needed - --> $DIR/E0282.rs:2:9 + --> $DIR/E0282.rs:2:5 | -LL | let x = "hello".chars().rev().collect(); - | ^ consider giving `x` a type +LL | None; + | ^^^^ cannot infer type for type parameter `T` declared on the enum `Option` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr index 8b1d4e6c07ceb..3d92d18e77ffe 100644 --- a/src/test/ui/error-codes/E0401.stderr +++ b/src/test/ui/error-codes/E0401.stderr @@ -37,6 +37,11 @@ error[E0282]: type annotations needed | LL | bfnr(x); | ^^^^ cannot infer type for type parameter `U` declared on the function `bfnr` + | +help: consider specifying the type arguments in the function call + | +LL | bfnr::(x); + | ^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/error-codes/E0661.stderr b/src/test/ui/error-codes/E0661.stderr index fe3887e72604d..2cb6b216e7607 100644 --- a/src/test/ui/error-codes/E0661.stderr +++ b/src/test/ui/error-codes/E0661.stderr @@ -8,7 +8,12 @@ error[E0282]: type annotations needed --> $DIR/E0661.rs:6:9 | LL | let a; - | ^ consider giving `a` a type + | ^ cannot infer type + | +help: consider giving this binding a type + | +LL | let a: Type; + | ^^^^^^ error: aborting due to 2 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 0672014a92929..cba9fbd5cf4de 100644 --- a/src/test/ui/for/for-loop-unconstrained-element-type.stderr +++ b/src/test/ui/for/for-loop-unconstrained-element-type.stderr @@ -2,7 +2,10 @@ error[E0282]: type annotations needed --> $DIR/for-loop-unconstrained-element-type.rs:8:14 | LL | for i in Vec::new() { } - | ^^^^^^^^^^ the element type for this iterator is not specified + | ^^^^^^^^-- + | | + | the element type for this iterator is not specified + | cannot infer type for type parameter `T` error: aborting due to previous error diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr index 2f630c2c9ad71..786038316f00a 100644 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr @@ -10,10 +10,13 @@ LL | #![feature(impl_trait_in_bindings)] error[E0282]: type annotations needed for `impl Future` --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20 | -LL | let fut = async { - | --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified LL | make_unit()?; | ^ cannot infer type + | +help: consider giving this binding the explicit type `impl Future`, with the type parameters specified + | +LL | let fut: impl Future = async { + | ^^^^^^^^^^^^^ error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr index 92a9045f6db50..9c19bfae50973 100644 --- a/src/test/ui/inference/cannot-infer-async.stderr +++ b/src/test/ui/inference/cannot-infer-async.stderr @@ -1,10 +1,13 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-async.rs:11:20 | -LL | let fut = async { - | --- consider giving `fut` a type LL | make_unit()?; | ^ cannot infer type + | +help: consider giving this binding a type + | +LL | let fut: Type = async { + | ^^^^^^ 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..6e5ddbbf96425 100644 --- a/src/test/ui/issues/issue-12187-1.stderr +++ b/src/test/ui/issues/issue-12187-1.stderr @@ -1,11 +1,17 @@ error[E0282]: type annotations needed for `&T` - --> $DIR/issue-12187-1.rs:6:10 + --> $DIR/issue-12187-1.rs:6:14 | LL | let &v = new(); - | -^ - | || - | |cannot infer type - | consider giving this pattern the explicit type `&T`, with the type parameters specified + | ^^^ cannot infer type for type parameter `T` declared on the function `new` + | +help: consider giving this binding the explicit type `&T`, where the type parameter `T` is specified + | +LL | let &v: &T = new(); + | ^^^^ +help: consider specifying the type argument in the function call + | +LL | let &v = 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..b01d5dc72b16f 100644 --- a/src/test/ui/issues/issue-12187-2.stderr +++ b/src/test/ui/issues/issue-12187-2.stderr @@ -1,11 +1,17 @@ error[E0282]: type annotations needed for `&T` - --> $DIR/issue-12187-2.rs:6:10 + --> $DIR/issue-12187-2.rs:6:14 | LL | let &v = new(); - | -^ - | || - | |cannot infer type - | consider giving this pattern the explicit type `&T`, with the type parameters specified + | ^^^ cannot infer type for type parameter `T` declared on the function `new` + | +help: consider giving this binding the explicit type `&T`, where the type parameter `T` is specified + | +LL | let &v: &T = new(); + | ^^^^ +help: consider specifying the type arguments in the function call + | +LL | let &v = new::(); + | ^^^^^ 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..13e90fa1422f8 100644 --- a/src/test/ui/issues/issue-17551.stderr +++ b/src/test/ui/issues/issue-17551.stderr @@ -2,9 +2,12 @@ error[E0282]: type annotations needed for `B` --> $DIR/issue-17551.rs:6:15 | 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 + | ^ cannot infer type for type parameter `T` declared on the struct `B` + | +help: consider giving this binding the explicit type `B`, where the 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..e0b3593075a4e 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 + | ^ cannot infer type + | +help: consider giving this binding a type + | +LL | let x: Type; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-2151.stderr b/src/test/ui/issues/issue-2151.stderr index a2bcc8a8ceaf0..f6154a37a847c 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 | -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 this binding a type + | +LL | let x: Type = 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..1b356e77f2f3a 100644 --- a/src/test/ui/issues/issue-23046.stderr +++ b/src/test/ui/issues/issue-23046.stderr @@ -3,6 +3,11 @@ error[E0282]: type annotations needed for `Expr<'_, VAR>` | LL | let ex = |x| { | ^ consider giving this closure parameter the explicit type `Expr<'_, VAR>`, where the type parameter `VAR` is specified + | +help: consider specifying the type arguments in the function call + | +LL | let_::(add(x,x), |y| { + | ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24036.rs b/src/test/ui/issues/issue-24036.rs index 7df036c8e3a45..48352ac87fe8c 100644 --- a/src/test/ui/issues/issue-24036.rs +++ b/src/test/ui/issues/issue-24036.rs @@ -6,11 +6,10 @@ fn closure_to_loc() { fn closure_from_match() { let x = match 1usize { - 1 => |c| c + 1, + 1 => |c| c + 1, //~ ERROR type annotations needed 2 => |c| c - 1, _ => |c| c - 1 }; - //~^^^^ ERROR type annotations needed } fn main() { } diff --git a/src/test/ui/issues/issue-24036.stderr b/src/test/ui/issues/issue-24036.stderr index e6b8367f74fb5..9bbbb4b3d6bee 100644 --- a/src/test/ui/issues/issue-24036.stderr +++ b/src/test/ui/issues/issue-24036.stderr @@ -11,11 +11,16 @@ LL | x = |c| c + 1; = note: no two closures, even if identical, have the same type = help: consider boxing your closure and/or using it as a trait object -error[E0282]: type annotations needed - --> $DIR/issue-24036.rs:9:15 +error[E0282]: type annotations needed for `fn(_) -> _` + --> $DIR/issue-24036.rs:9:18 | LL | 1 => |c| c + 1, - | ^ consider giving this closure parameter a type + | ^ cannot infer type + | +help: consider giving this binding the explicit type `fn(_) -> _`, with the type parameters specified + | +LL | let x: fn(_) -> _ = match 1usize { + | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr index 6a970bc049491..e28201d75c426 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 | -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` + | +help: consider giving this binding the explicit type `(Sender>, std::sync::mpsc::Receiver>)`, where the type parameter `T` is specified + | +LL | let (tx, rx): (Sender>, std::sync::mpsc::Receiver>) = channel(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr index 8d639304ab6e7..c3681f63c574c 100644 --- a/src/test/ui/issues/issue-5883.stderr +++ b/src/test/ui/issues/issue-5883.stderr @@ -1,16 +1,3 @@ -error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/issue-5883.rs:7:15 - | -LL | fn new_struct(r: dyn A + 'static) - | ^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn A + 'static)` - = help: unsized locals are gated as an unstable feature -help: function arguments must have a statically known size, borrowed types always have a known size - | -LL | fn new_struct(r: &dyn A + 'static) - | ^ - error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time --> $DIR/issue-5883.rs:8:8 | @@ -24,6 +11,19 @@ LL | Struct { r: r } = note: required because it appears within the type `Struct` = note: the return type of a function must have a statically known size +error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time + --> $DIR/issue-5883.rs:7:15 + | +LL | fn new_struct(r: dyn A + 'static) + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn A + 'static)` + = help: unsized locals are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn new_struct(r: &dyn A + 'static) + | ^ + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-6458-3.stderr b/src/test/ui/issues/issue-6458-3.stderr index a71c159db0b0e..162a94bffe698 100644 --- a/src/test/ui/issues/issue-6458-3.stderr +++ b/src/test/ui/issues/issue-6458-3.stderr @@ -3,6 +3,11 @@ error[E0282]: type annotations needed | LL | mem::transmute(0); | ^^^^^^^^^^^^^^ cannot infer type for type parameter `U` declared on the function `transmute` + | +help: consider specifying the type arguments in the function call + | +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 f1a982616a4a1..671624c57dbcf 100644 --- a/src/test/ui/issues/issue-6458.stderr +++ b/src/test/ui/issues/issue-6458.stderr @@ -3,6 +3,11 @@ error[E0282]: type annotations needed | LL | foo(TypeWithState(marker::PhantomData)); | ^^^ cannot infer type for type parameter `State` declared on the function `foo` + | +help: consider specifying the type argument in the function call + | +LL | foo::(TypeWithState(marker::PhantomData)); + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr index 3443cca5f3270..1e39bd66ee449 100644 --- a/src/test/ui/issues/issue-72690.stderr +++ b/src/test/ui/issues/issue-72690.stderr @@ -7,21 +7,26 @@ LL | String::from("x".as_ref()); = note: cannot satisfy `String: From<&_>` = note: required by `from` -error[E0282]: type annotations needed - --> $DIR/issue-72690.rs:11:6 +error[E0283]: type annotations needed + --> $DIR/issue-72690.rs:11:9 | LL | |x| String::from("x".as_ref()); - | ^ consider giving this closure parameter a type + | ^^^^^^^^^^^^ cannot infer type for reference `&_` + | + = note: cannot satisfy `String: From<&_>` + = note: required by `from` error[E0283]: type annotations needed for `&T` --> $DIR/issue-72690.rs:15:17 | 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 + | ^^^^^^ cannot infer type for type parameter `T` declared on the trait `AsRef` | = note: cannot satisfy `str: AsRef<_>` +help: consider giving this binding the explicit type `&T`, where the type parameter `T` is specified + | +LL | let _: str = "x".as_ref(); + | ^^^^^ error[E0283]: type annotations needed --> $DIR/issue-72690.rs:19:5 @@ -79,5 +84,4 @@ LL | String::from("x".as_ref()); error: aborting due to 9 previous errors -Some errors have detailed explanations: E0282, E0283. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/issues/issue-7813.stderr b/src/test/ui/issues/issue-7813.stderr index 59be0f3be11e6..7fb82a71ffedf 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]` +error[E0282]: type annotations needed for `&[_]` --> $DIR/issue-7813.rs:2:13 | LL | let v = &[]; - | - ^^^ cannot infer type - | | - | consider giving `v` the explicit type `&[_; 0]`, with the type parameters specified + | ^^^ cannot infer type + | +help: consider giving this binding the explicit type `&[_]`, with the type parameters specified + | +LL | let v: &[_] = &[]; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/match/match-unresolved-one-arm.rs b/src/test/ui/match/match-unresolved-one-arm.rs index fa65d87b3abbd..09640a028f0c6 100644 --- a/src/test/ui/match/match-unresolved-one-arm.rs +++ b/src/test/ui/match/match-unresolved-one-arm.rs @@ -1,7 +1,7 @@ fn foo() -> T { panic!("Rocks for my pillow") } fn main() { - let x = match () { //~ ERROR type annotations needed - () => foo() // T here should be unresolved + let x = match () { + () => foo() //~ ERROR type annotations needed }; } diff --git a/src/test/ui/match/match-unresolved-one-arm.stderr b/src/test/ui/match/match-unresolved-one-arm.stderr index 77df9921b754a..30c638391a459 100644 --- a/src/test/ui/match/match-unresolved-one-arm.stderr +++ b/src/test/ui/match/match-unresolved-one-arm.stderr @@ -1,8 +1,17 @@ error[E0282]: type annotations needed - --> $DIR/match-unresolved-one-arm.rs:4:9 + --> $DIR/match-unresolved-one-arm.rs:5:15 | -LL | let x = match () { - | ^ consider giving `x` a type +LL | () => foo() + | ^^^ cannot infer type for type parameter `T` declared on the function `foo` + | +help: consider giving this binding a type + | +LL | let x: Type = match () { + | ^^^^^^ +help: consider specifying the type argument in the function call + | +LL | () => foo::() + | ^^^^^ 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 82660a7c41693..28212d70bb32e 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 @@ -2,9 +2,12 @@ error[E0282]: type annotations needed for `Vec` --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:17 | 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 + | ^^^^^^^^ cannot infer type for type parameter `T` + | +help: consider giving this binding the explicit type `Vec`, where the type parameter `T` is specified + | +LL | let mut x: Vec = Vec::new(); + | ^^^^^^^^ error[E0308]: mismatched types --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20 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 1219badc5b3fc..baf9b2f9f3e58 100644 --- a/src/test/ui/missing/missing-items/missing-type-parameter.stderr +++ b/src/test/ui/missing/missing-items/missing-type-parameter.stderr @@ -3,6 +3,11 @@ error[E0282]: type annotations needed | LL | foo(); | ^^^ cannot infer type for type parameter `X` declared on the function `foo` + | +help: consider specifying the type argument in the function call + | +LL | foo::(); + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/pat-tuple-bad-type.stderr b/src/test/ui/pattern/pat-tuple-bad-type.stderr index 598b6a3794ef7..e6e754f622742 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 | -LL | let x; - | - consider giving `x` a type -... LL | (..) => {} | ^^^^ cannot infer type | = note: type must be known at this point +help: consider giving this binding a type + | +LL | let x: Type; + | ^^^^^^ 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 95f6d53a9d40d..678029b3ef369 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 + | ^^^^^^ cannot infer type + | +help: consider giving this binding a type + | +LL | let x @ ..: Type; + | ^^^^^^ error: aborting due to 23 previous errors diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr index c64c5b1c28f41..5501e439e0df2 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr @@ -1,12 +1,14 @@ error[E0282]: type annotations needed for `Option<_>` --> $DIR/issue-42234-unknown-receiver-type.rs:7:7 | -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` | = note: type must be known at this point +help: consider giving this binding the explicit type `Option<_>`, where the type parameter `T` is specified + | +LL | let x: Option<_> = None; + | ^^^^^^^^^ error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:13:10 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..cbdaca2c2e86a 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 | -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 this binding a type + | +LL | let mut x: Type = Default::default(); + | ^^^^^^ error[E0282]: type annotations needed --> $DIR/method-and-field-eager-resolution.rs:12:5 | -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 this binding a type + | +LL | let mut x: Type = Default::default(); + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/str/str-array-assignment.stderr b/src/test/ui/str/str-array-assignment.stderr index 73c03f09f2ebc..8d74b4d53ee12 100644 --- a/src/test/ui/str/str-array-assignment.stderr +++ b/src/test/ui/str/str-array-assignment.stderr @@ -15,6 +15,16 @@ LL | let u: &str = if true { s[..2] } else { s }; | expected `&str`, found `str` | help: consider borrowing here: `&s[..2]` +error[E0308]: mismatched types + --> $DIR/str-array-assignment.rs:9:17 + | +LL | let w: &str = s[..2]; + | ---- ^^^^^^ + | | | + | | expected `&str`, found `str` + | | help: consider borrowing here: `&s[..2]` + | expected due to this + error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/str-array-assignment.rs:7:7 | @@ -29,16 +39,6 @@ help: consider borrowing here LL | let v = &s[..2]; | ^ -error[E0308]: mismatched types - --> $DIR/str-array-assignment.rs:9:17 - | -LL | let w: &str = s[..2]; - | ---- ^^^^^^ - | | | - | | expected `&str`, found `str` - | | help: consider borrowing here: `&s[..2]` - | expected due to this - error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. diff --git a/src/test/ui/str/str-mut-idx.rs b/src/test/ui/str/str-mut-idx.rs index 575a9eae85946..c089faa8ef37a 100644 --- a/src/test/ui/str/str-mut-idx.rs +++ b/src/test/ui/str/str-mut-idx.rs @@ -1,17 +1,13 @@ fn bot() -> T { loop {} } fn mutate(s: &mut str) { - s[1..2] = bot(); - //~^ ERROR the size for values of type - //~| ERROR the size for values of type - s[1usize] = bot(); - //~^ ERROR the type `str` cannot be indexed by `usize` - s.get_mut(1); - //~^ ERROR the type `str` cannot be indexed by `{integer}` - s.get_unchecked_mut(1); - //~^ ERROR the type `str` cannot be indexed by `{integer}` - s['c']; - //~^ ERROR the type `str` cannot be indexed by `char` + s[1..2] = bot(); //~ ERROR the size for values of type + // A second error would happen due to `s[1..2]` but it isn't emitted because it is delayed and + // there are already other errors being emitted. + s[1usize] = bot(); //~ ERROR the type `str` cannot be indexed by `usize` + s.get_mut(1); //~ ERROR the type `str` cannot be indexed by `{integer}` + s.get_unchecked_mut(1); //~ ERROR the type `str` cannot be indexed by `{integer}` + s['c']; //~ ERROR the type `str` cannot be indexed by `char` } pub fn main() {} diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr index 405542820a394..dfe4b86fb3bdb 100644 --- a/src/test/ui/str/str-mut-idx.stderr +++ b/src/test/ui/str/str-mut-idx.stderr @@ -13,15 +13,6 @@ help: consider relaxing the implicit `Sized` restriction LL | fn bot() -> T { loop {} } | ^^^^^^^^ -error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/str-mut-idx.rs:4:5 - | -LL | s[1..2] = bot(); - | ^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `str` - = note: the left-hand-side of an assignment must have a statically known size - error[E0277]: the type `str` cannot be indexed by `usize` --> $DIR/str-mut-idx.rs:7:5 | @@ -32,7 +23,7 @@ LL | s[1usize] = bot(); = note: required because of the requirements on the impl of `Index` for `str` error[E0277]: the type `str` cannot be indexed by `{integer}` - --> $DIR/str-mut-idx.rs:9:15 + --> $DIR/str-mut-idx.rs:8:15 | LL | s.get_mut(1); | ^ string indices are ranges of `usize` @@ -42,7 +33,7 @@ LL | s.get_mut(1); for more information, see chapter 8 in The Book: error[E0277]: the type `str` cannot be indexed by `{integer}` - --> $DIR/str-mut-idx.rs:11:25 + --> $DIR/str-mut-idx.rs:9:25 | LL | s.get_unchecked_mut(1); | ^ string indices are ranges of `usize` @@ -52,7 +43,7 @@ LL | s.get_unchecked_mut(1); for more information, see chapter 8 in The Book: error[E0277]: the type `str` cannot be indexed by `char` - --> $DIR/str-mut-idx.rs:13:5 + --> $DIR/str-mut-idx.rs:10:5 | LL | s['c']; | ^^^^^^ string indices are ranges of `usize` @@ -60,6 +51,6 @@ LL | s['c']; = help: the trait `SliceIndex` is not implemented for `char` = note: required because of the requirements on the impl of `Index` for `str` -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/appropriate-type-param-turbofish.rs b/src/test/ui/suggestions/appropriate-type-param-turbofish.rs new file mode 100644 index 0000000000000..0e58704d1d734 --- /dev/null +++ b/src/test/ui/suggestions/appropriate-type-param-turbofish.rs @@ -0,0 +1,97 @@ +mod a { + fn foo() { + vec![1, 2, 3].into_iter().collect(); //~ ERROR type annotations needed + } + fn bar() { + vec!["a", "b", "c"].into_iter().collect(); //~ ERROR type annotations needed + } + fn qux() { + vec!['a', 'b', 'c'].into_iter().collect(); //~ ERROR type annotations needed + } +} +mod b { + fn foo() { + let _ = vec![1, 2, 3].into_iter().collect(); //~ ERROR type annotations needed + } + fn bar() { + let _ = vec!["a", "b", "c"].into_iter().collect(); //~ ERROR type annotations needed + } + fn qux() { + let _ = vec!['a', 'b', 'c'].into_iter().collect(); //~ ERROR type annotations needed + } +} + +mod c { + fn foo() { + let _x = vec![1, 2, 3].into_iter().collect(); //~ ERROR type annotations needed + } + fn bar() { + let _x = vec!["a", "b", "c"].into_iter().collect(); //~ ERROR type annotations needed + } + fn qux() { + let _x = vec!['a', 'b', 'c'].into_iter().collect(); //~ ERROR type annotations needed + } +} + +trait T: Sized { + fn new() -> Self; +} + +fn x() -> X { + T::new() +} +struct S; +impl T for S { + fn new() -> Self { + S + } +} + +struct AAA { x: X, } + +impl std::iter::FromIterator for AAA { + fn from_iter>(_iter: I) -> AAA { + panic!() + } +} + +fn foo() { + x(); //~ ERROR type annotations needed +} + +fn bar() { + let _ = x(); //~ ERROR type annotations needed +} + +fn qux() { + let x: Vec<&std::path::Path> = vec![]; + let y = x.into_iter().collect(); //~ ERROR type annotations needed +} + +trait Foo { + fn foo, K>(&self) -> T { + panic!() + } +} + +trait Bar {} + +struct R(X); +impl Bar for R {} +struct K(X); +impl Bar for K {} + +struct I; + +impl Foo for I {} + +fn bat() { + let _ = I.foo(); //~ ERROR type annotations needed +} + +// This case does not have a good suggestion yet: +fn bak>() {} + +fn main() { + bak(); //~ ERROR type annotations needed +} diff --git a/src/test/ui/suggestions/appropriate-type-param-turbofish.stderr b/src/test/ui/suggestions/appropriate-type-param-turbofish.stderr new file mode 100644 index 0000000000000..b93664aa16204 --- /dev/null +++ b/src/test/ui/suggestions/appropriate-type-param-turbofish.stderr @@ -0,0 +1,254 @@ +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:3:35 + | +LL | vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator` +help: consider specifying the type argument in the method call + | +LL | vec![1, 2, 3].into_iter().collect::>(); + | ^^^^^^^^^^ +LL | vec![1, 2, 3].into_iter().collect::>(); + | ^^^^^^^^^^ +LL | vec![1, 2, 3].into_iter().collect::>(); + | ^^^^^^^^^^^^ +LL | vec![1, 2, 3].into_iter().collect::>(); + | ^^^^^^^^^^^^^^^ + and 6 other candidates + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:6:41 + | +LL | vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator<&str>` +help: consider specifying the type argument in the method call + | +LL | vec!["a", "b", "c"].into_iter().collect::>(); + | ^^^^^^^^^^ +LL | vec!["a", "b", "c"].into_iter().collect::(); + | ^^^^^^^^^^ +LL | vec!["a", "b", "c"].into_iter().collect::>(); + | ^^^^^^^^^^ +LL | vec!["a", "b", "c"].into_iter().collect::>(); + | ^^^^^^^^^^^^ + and 9 other candidates + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:9:41 + | +LL | vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator` +help: consider specifying the type argument in the method call + | +LL | vec!['a', 'b', 'c'].into_iter().collect::>(); + | ^^^^^^^^^^ +LL | vec!['a', 'b', 'c'].into_iter().collect::(); + | ^^^^^^^^^^ +LL | vec!['a', 'b', 'c'].into_iter().collect::>(); + | ^^^^^^^^^^ +LL | vec!['a', 'b', 'c'].into_iter().collect::>(); + | ^^^^^^^^^^^^ + and 8 other candidates + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:14:43 + | +LL | let _ = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator` +help: consider giving this binding a type + | +LL | let _: Vec = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^^ +LL | let _: AAA = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^^ +LL | let _: Arc<[T]> = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^^^^ +LL | let _: BTreeSet = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^^^^^^^ + and 6 other candidates + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:17:49 + | +LL | let _ = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator<&str>` +help: consider giving this binding a type + | +LL | let _: Vec = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^^ +LL | let _: String = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^^ +LL | let _: AAA = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^^ +LL | let _: Arc<[T]> = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^^^^ + and 9 other candidates + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:20:49 + | +LL | let _ = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator` +help: consider giving this binding a type + | +LL | let _: Vec = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^^ +LL | let _: String = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^^ +LL | let _: AAA = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^^ +LL | let _: Arc<[T]> = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^^^^ + and 8 other candidates + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:26:44 + | +LL | let _x = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator` +help: consider giving this binding a type + | +LL | let _x: Vec = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^^ +LL | let _x: AAA = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^^ +LL | let _x: Arc<[T]> = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^^^^ +LL | let _x: BTreeSet = vec![1, 2, 3].into_iter().collect(); + | ^^^^^^^^^^^^^ + and 6 other candidates + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:29:50 + | +LL | let _x = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator<&str>` +help: consider giving this binding a type + | +LL | let _x: Vec = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^^ +LL | let _x: String = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^^ +LL | let _x: AAA = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^^ +LL | let _x: Arc<[T]> = vec!["a", "b", "c"].into_iter().collect(); + | ^^^^^^^^^^ + and 9 other candidates + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:32:50 + | +LL | let _x = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator` +help: consider giving this binding a type + | +LL | let _x: Vec = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^^ +LL | let _x: String = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^^ +LL | let _x: AAA = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^^ +LL | let _x: Arc<[T]> = vec!['a', 'b', 'c'].into_iter().collect(); + | ^^^^^^^^^^ + and 8 other candidates + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:59:5 + | +LL | fn x() -> X { + | - required by this bound in `x` +... +LL | x(); + | ^ cannot infer type for type parameter `X` declared on the function `x` + | + = note: cannot satisfy `_: T` +help: consider specifying the type argument in the function call + | +LL | x::(); + | ^^^^^ + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:63:13 + | +LL | fn x() -> X { + | - required by this bound in `x` +... +LL | let _ = x(); + | ^ cannot infer type for type parameter `X` declared on the function `x` + | + = note: cannot satisfy `_: T` +help: consider giving this binding the explicit type `S` + | +LL | let _: S = x(); + | ^^^ +help: consider specifying the type argument in the function call + | +LL | let _ = x::(); + | ^^^^^ + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:68:27 + | +LL | let y = x.into_iter().collect(); + | ^^^^^^^ cannot infer type for type parameter `B` declared on the associated function `collect` + | + = note: cannot satisfy `_: FromIterator<&Path>` +help: consider giving this binding a type + | +LL | let y: Vec = x.into_iter().collect(); + | ^^^^^^^^ +LL | let y: Arc<[T]> = x.into_iter().collect(); + | ^^^^^^^^^^ +LL | let y: BTreeSet = x.into_iter().collect(); + | ^^^^^^^^^^^^^ +LL | let y: BinaryHeap = x.into_iter().collect(); + | ^^^^^^^^^^^^^^^ + and 6 other candidates + +error[E0282]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:89:15 + | +LL | let _ = I.foo(); + | ^^^ cannot infer type for type parameter `T` declared on the associated function `foo` + | +help: consider giving this binding a type + | +LL | let _: Type = I.foo(); + | ^^^^^^ + +error[E0283]: type annotations needed + --> $DIR/appropriate-type-param-turbofish.rs:96:5 + | +LL | fn bak>() {} + | ------------ required by this bound in `bak` +... +LL | bak(); + | ^^^ cannot infer type for type parameter `T` declared on the function `bak` + | + = note: cannot satisfy `_: Into` +help: consider specifying the type argument in the function call + | +LL | bak::(); + | ^^^^^ + +error: aborting due to 14 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/suggestions/fn-needing-specified-return-type-param.stderr b/src/test/ui/suggestions/fn-needing-specified-return-type-param.stderr index b59a3818e7042..1b8756cb23de3 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 @@ -2,9 +2,16 @@ error[E0282]: type annotations needed for `fn() -> A` --> $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 for type parameter `A` declared on the function `f` + | +help: consider giving this binding the explicit type `fn() -> A`, where the type parameter `A` is specified + | +LL | let _: fn() -> A = f; + | ^^^^^^^^^^^ +help: consider specifying the type argument in the function call + | +LL | let _ = f::; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr index d788f1871ffac..d75b728e86078 100644 --- a/src/test/ui/traits/issue-77982.stderr +++ b/src/test/ui/traits/issue-77982.stderr @@ -23,21 +23,27 @@ error[E0283]: type annotations needed for `Box` --> $DIR/issue-77982.rs:35:16 | 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 + | ^^^ cannot infer type for type parameter `T` declared on the trait `Foo` | = note: cannot satisfy `(): Foo<'_, _>` +help: consider giving this binding the explicit type `Box`, where the type parameter `T` is specified + | +LL | let _: () = ().foo(); + | ^^^^ error[E0283]: type annotations needed for `Box` --> $DIR/issue-77982.rs:39:19 | 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 + | ^^^ cannot infer type for type parameter `T` declared on the trait `Bar` | = note: cannot satisfy `&(): Bar<'_, _>` +help: consider giving this binding the explicit type `Box`, where the type parameter `T` is specified + | +LL | let _: &'a () = (&()).bar(); + | ^^^^^^^^ +LL | let _: &'a () = (&()).bar(); + | ^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.rs b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.rs index 58cb69a05b704..36e1e868fca13 100644 --- a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.rs +++ b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.rs @@ -24,7 +24,7 @@ where T : Convert fn a() { test(22, std::default::Default::default()); - //~^ ERROR type annotations needed [E0282] + //~^ ERROR type annotations needed } fn main() {} diff --git a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr index 338c8cbf2e4f2..04400ff1893ee 100644 --- a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr +++ b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr @@ -3,6 +3,11 @@ error[E0282]: type annotations needed | LL | test(22, std::default::Default::default()); | ^^^^ cannot infer type for type parameter `U` declared on the function `test` + | +help: consider specifying the type arguments in the function call + | +LL | test::(22, std::default::Default::default()); + | ^^^^^^^^ 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 d60ca4a49325c..c02cd65c49623 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 @@ -3,6 +3,11 @@ error[E0282]: type annotations needed | LL | foo(); | ^^^ cannot infer type for type parameter `T` declared on the function `foo` + | +help: consider specifying the type arguments in the function call + | +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 45d879d8d5670..4e0f2be1b112e 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 @@ -3,6 +3,11 @@ error[E0282]: type annotations needed | LL | foo(); | ^^^ cannot infer type for type parameter `T` declared on the function `foo` + | +help: consider specifying the type argument in the function call + | +LL | foo::(); + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type/type-annotation-needed.rs b/src/test/ui/type/type-annotation-needed.rs index 553318ecac6e2..17d9838049b44 100644 --- a/src/test/ui/type/type-annotation-needed.rs +++ b/src/test/ui/type/type-annotation-needed.rs @@ -4,6 +4,6 @@ fn foo>(x: i32) {} fn main() { foo(42); //~^ ERROR type annotations needed - //~| NOTE cannot infer type + //~| NOTE cannot infer type for type parameter `T` declared on the function `foo` //~| NOTE cannot satisfy } 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..c44ae8363ef6b 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 @@ -2,9 +2,12 @@ error[E0282]: type annotations needed for `[_; 0]` --> $DIR/cannot_infer_local_or_array.rs:2:13 | LL | let x = []; - | - ^^ cannot infer type - | | - | consider giving `x` the explicit type `[_; 0]`, with the type parameters specified + | ^^ cannot infer type + | +help: consider giving this binding the explicit type `[_; 0]`, with the type parameters 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 729a8c63b6240..0b8a1f2670e58 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 @@ -2,11 +2,13 @@ error[E0282]: type annotations needed for `Vec` --> $DIR/cannot_infer_local_or_vec.rs:2:13 | 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 + | ^^^^^^ cannot infer type for type parameter `T` | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider giving this binding the explicit type `Vec`, where the 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 e24593a89b3bc..78128a266ef2d 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 @@ -2,11 +2,13 @@ error[E0282]: type annotations needed for `(Vec,)` --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18 | 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 + | ^^^^^^ cannot infer type for type parameter `T` | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider giving this binding the explicit type `(Vec,)`, where the type parameter `T` is specified + | +LL | let (x, ): (Vec,) = (vec![], ); + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type/type-path-err-node-types-2.rs b/src/test/ui/type/type-path-err-node-types-2.rs new file mode 100644 index 0000000000000..a088ad6f195e6 --- /dev/null +++ b/src/test/ui/type/type-path-err-node-types-2.rs @@ -0,0 +1,10 @@ +// Type arguments in unresolved entities (reporting errors before type checking) +// should have their types recorded. + +trait Tr {} + +fn closure() { + let _ = |a, b: _| -> _ { 0 }; //~ ERROR type annotations needed +} + +fn main() {} diff --git a/src/test/ui/type/type-path-err-node-types-2.stderr b/src/test/ui/type/type-path-err-node-types-2.stderr new file mode 100644 index 0000000000000..b7ddf24df1f54 --- /dev/null +++ b/src/test/ui/type/type-path-err-node-types-2.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/type-path-err-node-types-2.rs:7:14 + | +LL | let _ = |a, b: _| -> _ { 0 }; + | ^ consider giving this closure parameter a type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type/type-path-err-node-types.rs b/src/test/ui/type/type-path-err-node-types.rs index b3795772e6fe2..cfc8872c2791e 100644 --- a/src/test/ui/type/type-path-err-node-types.rs +++ b/src/test/ui/type/type-path-err-node-types.rs @@ -19,8 +19,4 @@ fn method() { nonexistent.nonexistent::(); //~ ERROR cannot find value `nonexistent` } -fn closure() { - let _ = |a, b: _| -> _ { 0 }; //~ ERROR type annotations needed -} - fn main() {} 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..90f56655e2901 100644 --- a/src/test/ui/type/type-path-err-node-types.stderr +++ b/src/test/ui/type/type-path-err-node-types.stderr @@ -22,13 +22,7 @@ error[E0425]: cannot find value `nonexistent` in this scope LL | nonexistent.nonexistent::(); | ^^^^^^^^^^^ not found in this scope -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 - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0282, E0412, E0425, E0433, E0576. -For more information about an error, try `rustc --explain E0282`. +Some errors have detailed explanations: E0412, E0425, E0433, E0576. +For more information about an error, try `rustc --explain E0412`. 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..c42486514d79d 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 | -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 this binding the explicit type `Option`, with the type parameters specified + | +LL | let mut closure0: Option = None; + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unsized6.rs b/src/test/ui/unsized6.rs index 79133554d5472..d6898fa3dde6b 100644 --- a/src/test/ui/unsized6.rs +++ b/src/test/ui/unsized6.rs @@ -8,31 +8,19 @@ fn f1(x: &X) { //~^ ERROR the size for values of type let y: Y; //~^ ERROR the size for values of type - let y: (isize, (Z, usize)); - //~^ ERROR the size for values of type } fn f2(x: &X) { let y: X; //~^ ERROR the size for values of type - let y: (isize, (Y, isize)); - //~^ ERROR the size for values of type } fn f3(x1: Box, x2: Box, x3: Box) { let y: X = *x1; //~^ ERROR the size for values of type - let y = *x2; - //~^ ERROR the size for values of type - let (y, z) = (*x3, 4); - //~^ ERROR the size for values of type } fn f4(x1: Box, x2: Box, x3: Box) { let y: X = *x1; //~^ ERROR the size for values of type - let y = *x2; - //~^ ERROR the size for values of type - let (y, z) = (*x3, 4); - //~^ ERROR the size for values of type } fn g1(x: X) {} diff --git a/src/test/ui/unsized6.stderr b/src/test/ui/unsized6.stderr index e85b73355e90f..2b01871f39671 100644 --- a/src/test/ui/unsized6.stderr +++ b/src/test/ui/unsized6.stderr @@ -1,15 +1,3 @@ -error[E0277]: the size for values of type `Y` cannot be known at compilation time - --> $DIR/unsized6.rs:9:9 - | -LL | fn f1(x: &X) { - | - this type parameter needs to be `Sized` -... -LL | let y: Y; - | ^ doesn't have a size known at compile-time - | - = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature - error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:7:12 | @@ -21,79 +9,34 @@ LL | let _: (isize, (X, isize)); | = note: only the last element of a tuple may have a dynamically sized type -error[E0277]: the size for values of type `Z` cannot be known at compilation time - --> $DIR/unsized6.rs:11:12 - | -LL | fn f1(x: &X) { - | - this type parameter needs to be `Sized` -... -LL | let y: (isize, (Z, usize)); - | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = note: only the last element of a tuple may have a dynamically sized type - -error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized6.rs:15:9 - | -LL | fn f2(x: &X) { - | - this type parameter needs to be `Sized` -LL | let y: X; - | ^ doesn't have a size known at compile-time - | - = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature - error[E0277]: the size for values of type `Y` cannot be known at compilation time - --> $DIR/unsized6.rs:17:12 + --> $DIR/unsized6.rs:9:9 | -LL | fn f2(x: &X) { - | - this type parameter needs to be `Sized` +LL | fn f1(x: &X) { + | - this type parameter needs to be `Sized` ... -LL | let y: (isize, (Y, isize)); - | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = note: only the last element of a tuple may have a dynamically sized type - -error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized6.rs:22:9 - | -LL | fn f3(x1: Box, x2: Box, x3: Box) { - | - this type parameter needs to be `Sized` -LL | let y: X = *x1; +LL | let y: Y; | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized6.rs:24:9 + --> $DIR/unsized6.rs:13:9 | -LL | fn f3(x1: Box, x2: Box, x3: Box) { +LL | fn f2(x: &X) { | - this type parameter needs to be `Sized` -... -LL | let y = *x2; +LL | let y: X; | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized6.rs:26:10 + --> $DIR/unsized6.rs:18:9 | LL | fn f3(x1: Box, x2: Box, x3: Box) { | - this type parameter needs to be `Sized` -... -LL | let (y, z) = (*x3, 4); - | ^ doesn't have a size known at compile-time - | - = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature - -error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized6.rs:30:9 - | -LL | fn f4(x1: Box, x2: Box, x3: Box) { - | - this type parameter needs to be `Sized` LL | let y: X = *x1; | ^ doesn't have a size known at compile-time | @@ -101,31 +44,18 @@ LL | let y: X = *x1; = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized6.rs:32:9 + --> $DIR/unsized6.rs:22:9 | LL | fn f4(x1: Box, x2: Box, x3: Box) { | - this type parameter needs to be `Sized` -... -LL | let y = *x2; +LL | let y: X = *x1; | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized6.rs:34:10 - | -LL | fn f4(x1: Box, x2: Box, x3: Box) { - | - this type parameter needs to be `Sized` -... -LL | let (y, z) = (*x3, 4); - | ^ doesn't have a size known at compile-time - | - = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature - -error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized6.rs:38:18 + --> $DIR/unsized6.rs:26:18 | LL | fn g1(x: X) {} | - ^ doesn't have a size known at compile-time @@ -139,7 +69,7 @@ LL | fn g1(x: &X) {} | ^ error[E0277]: the size for values of type `X` cannot be known at compilation time - --> $DIR/unsized6.rs:40:22 + --> $DIR/unsized6.rs:28:22 | LL | fn g2(x: X) {} | - ^ doesn't have a size known at compile-time @@ -152,6 +82,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn g2(x: &X) {} | ^ -error: aborting due to 13 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized8.rs b/src/test/ui/unsized8.rs new file mode 100644 index 0000000000000..80fc07b92bd4d --- /dev/null +++ b/src/test/ui/unsized8.rs @@ -0,0 +1,24 @@ +// Test `?Sized` local variables. + +trait T {} + +fn f1(x: &X) { + let y: (isize, (Z, usize)); + //~^ ERROR the size for values of type +} +fn f2(x: &X) { + let y: (isize, (Y, isize)); + //~^ ERROR the size for values of type +} + +fn f3(x1: Box, x2: Box, x3: Box) { + let (y, z) = (*x3, 4); + //~^ ERROR the size for values of type +} +fn f4(x1: Box, x2: Box, x3: Box) { + let (y, z) = (*x3, 4); + //~^ ERROR the size for values of type +} + +pub fn main() { +} diff --git a/src/test/ui/unsized8.stderr b/src/test/ui/unsized8.stderr new file mode 100644 index 0000000000000..a1e57db2ae27d --- /dev/null +++ b/src/test/ui/unsized8.stderr @@ -0,0 +1,45 @@ +error[E0277]: the size for values of type `Z` cannot be known at compilation time + --> $DIR/unsized8.rs:6:12 + | +LL | fn f1(x: &X) { + | - this type parameter needs to be `Sized` +LL | let y: (isize, (Z, usize)); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `Y` cannot be known at compilation time + --> $DIR/unsized8.rs:10:12 + | +LL | fn f2(x: &X) { + | - this type parameter needs to be `Sized` +LL | let y: (isize, (Y, isize)); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized8.rs:15:10 + | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | - this type parameter needs to be `Sized` +LL | let (y, z) = (*x3, 4); + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error[E0277]: the size for values of type `X` cannot be known at compilation time + --> $DIR/unsized8.rs:19:10 + | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | - this type parameter needs to be `Sized` +LL | let (y, z) = (*x3, 4); + | ^ doesn't have a size known at compile-time + | + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/vector-no-ann.stderr b/src/test/ui/vector-no-ann.stderr index 8a7b8d22760a2..a45ac324f4a6b 100644 --- a/src/test/ui/vector-no-ann.stderr +++ b/src/test/ui/vector-no-ann.stderr @@ -2,9 +2,12 @@ error[E0282]: type annotations needed for `Vec` --> $DIR/vector-no-ann.rs:2:16 | 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 + | ^^^^^^^^ cannot infer type for type parameter `T` + | +help: consider giving this binding the explicit type `Vec`, where the type parameter `T` is specified + | +LL | let _foo: Vec = Vec::new(); + | ^^^^^^^^ error: aborting due to previous error