@@ -3748,7 +3748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37483748 formal_tys. clone ( )
37493749 } ;
37503750
3751- let mut final_arg_types: Vec < ( usize , Ty < ' _ > ) > = vec ! [ ] ;
3751+ let mut final_arg_types: Vec < ( usize , Ty < ' _ > , Ty < ' _ > ) > = vec ! [ ] ;
37523752
37533753 // Check the arguments.
37543754 // We do this in a pretty awful way: first we type-check any arguments
@@ -3816,7 +3816,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38163816 // We're processing function arguments so we definitely want to use
38173817 // two-phase borrows.
38183818 self . demand_coerce ( & arg, checked_ty, coerce_ty, AllowTwoPhase :: Yes ) ;
3819- final_arg_types. push ( ( i, coerce_ty) ) ;
3819+ final_arg_types. push ( ( i, checked_ty , coerce_ty) ) ;
38203820
38213821 // 3. Relate the expected type and the formal one,
38223822 // if the expected type was used for the coercion.
@@ -3863,14 +3863,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38633863 vec ! [ self . tcx. types. err; len]
38643864 }
38653865
3866- /// Given a vec of evaluated `FullfillmentError`s and an `fn` call argument expressions, we
3867- /// walk the resolved types for each argument to see if any of the `FullfillmentError`s
3868- /// reference a type argument. If they do, and there's only *one* argument that does, we point
3869- /// at the corresponding argument's expression span instead of the `fn` call path span.
3866+ /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
3867+ /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
3868+ /// reference a type argument. The reason to walk also the checked type is that the coerced type
3869+ /// can be not easily comparable with predicate type (because of coercion). If the types match
3870+ /// for either checked or coerced type, and there's only *one* argument that does, we point at
3871+ /// the corresponding argument's expression span instead of the `fn` call path span.
38703872 fn point_at_arg_instead_of_call_if_possible (
38713873 & self ,
38723874 errors : & mut Vec < traits:: FulfillmentError < ' _ > > ,
3873- final_arg_types : & [ ( usize , Ty < ' tcx > ) ] ,
3875+ final_arg_types : & [ ( usize , Ty < ' tcx > , Ty < ' tcx > ) ] ,
38743876 call_sp : Span ,
38753877 args : & ' tcx [ hir:: Expr ] ,
38763878 ) {
@@ -3880,19 +3882,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
38803882 for error in errors {
38813883 if let ty:: Predicate :: Trait ( predicate) = error. obligation . predicate {
38823884 // Collect the argument position for all arguments that could have caused this
3883- // `FullfillmentError `.
3885+ // `FulfillmentError `.
38843886 let mut referenced_in = final_arg_types. iter ( )
3887+ . map ( |( i, checked_ty, _) | ( i, checked_ty) )
3888+ . chain ( final_arg_types. iter ( ) . map ( |( i, _, coerced_ty) | ( i, coerced_ty) ) )
38853889 . flat_map ( |( i, ty) | {
38863890 let ty = self . resolve_vars_if_possible ( ty) ;
38873891 // We walk the argument type because the argument's type could have
3888- // been `Option<T>`, but the `FullfillmentError ` references `T`.
3892+ // been `Option<T>`, but the `FulfillmentError ` references `T`.
38893893 ty. walk ( )
38903894 . filter ( |& ty| ty == predicate. skip_binder ( ) . self_ty ( ) )
38913895 . map ( move |_| * i)
3892- } ) ;
3893- if let ( Some ( ref_in) , None ) = ( referenced_in. next ( ) , referenced_in. next ( ) ) {
3896+ } )
3897+ . collect :: < Vec < _ > > ( ) ;
3898+
3899+ // Both checked and coerced types could have matched, thus we need to remove
3900+ // duplicates.
3901+ referenced_in. dedup ( ) ;
3902+
3903+ if let ( Some ( ref_in) , None ) = ( referenced_in. pop ( ) , referenced_in. pop ( ) ) {
38943904 // We make sure that only *one* argument matches the obligation failure
3895- // and thet the obligation's span to its expression's.
3905+ // and we assign the obligation's span to its expression's.
38963906 error. obligation . cause . span = args[ ref_in] . span ;
38973907 error. points_at_arg_span = true ;
38983908 }
@@ -3901,8 +3911,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
39013911 }
39023912 }
39033913
3904- /// Given a vec of evaluated `FullfillmentError `s and an `fn` call expression, we walk the
3905- /// `PathSegment`s and resolve their type parameters to see if any of the `FullfillmentError `s
3914+ /// Given a vec of evaluated `FulfillmentError `s and an `fn` call expression, we walk the
3915+ /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError `s
39063916 /// were caused by them. If they were, we point at the corresponding type argument's span
39073917 /// instead of the `fn` call path span.
39083918 fn point_at_type_arg_instead_of_call_if_possible (
0 commit comments