@@ -3641,7 +3641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
36413641 formal_tys. clone ( )
36423642 } ;
36433643
3644- let mut final_arg_types: Vec < ( usize , Ty < ' _ > ) > = vec ! [ ] ;
3644+ let mut final_arg_types: Vec < ( usize , Ty < ' _ > , Ty < ' _ > ) > = vec ! [ ] ;
36453645
36463646 // Check the arguments.
36473647 // We do this in a pretty awful way: first we type-check any arguments
@@ -3709,7 +3709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37093709 // We're processing function arguments so we definitely want to use
37103710 // two-phase borrows.
37113711 self . demand_coerce ( & arg, checked_ty, coerce_ty, AllowTwoPhase :: Yes ) ;
3712- final_arg_types. push ( ( i, coerce_ty) ) ;
3712+ final_arg_types. push ( ( i, checked_ty , coerce_ty) ) ;
37133713
37143714 // 3. Relate the expected type and the formal one,
37153715 // if the expected type was used for the coercion.
@@ -3756,14 +3756,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37563756 vec ! [ self . tcx. types. err; len]
37573757 }
37583758
3759- /// Given a vec of evaluated `FullfillmentError`s and an `fn` call argument expressions, we
3760- /// walk the resolved types for each argument to see if any of the `FullfillmentError`s
3761- /// reference a type argument. If they do, and there's only *one* argument that does, we point
3762- /// at the corresponding argument's expression span instead of the `fn` call path span.
3759+ /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
3760+ /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
3761+ /// reference a type argument. The reason to walk also the checked type is that the coerced type
3762+ /// can be not easily comparable with predicate type (because of coercion). If the types match
3763+ /// for either checked or coerced type, and there's only *one* argument that does, we point at
3764+ /// the corresponding argument's expression span instead of the `fn` call path span.
37633765 fn point_at_arg_instead_of_call_if_possible (
37643766 & self ,
37653767 errors : & mut Vec < traits:: FulfillmentError < ' _ > > ,
3766- final_arg_types : & [ ( usize , Ty < ' tcx > ) ] ,
3768+ final_arg_types : & [ ( usize , Ty < ' tcx > , Ty < ' tcx > ) ] ,
37673769 call_sp : Span ,
37683770 args : & ' tcx [ hir:: Expr ] ,
37693771 ) {
@@ -3773,19 +3775,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37733775 for error in errors {
37743776 if let ty:: Predicate :: Trait ( predicate) = error. obligation . predicate {
37753777 // Collect the argument position for all arguments that could have caused this
3776- // `FullfillmentError `.
3778+ // `FulfillmentError `.
37773779 let mut referenced_in = final_arg_types. iter ( )
3780+ . map ( |( i, checked_ty, _) | ( i, checked_ty) )
3781+ . chain ( final_arg_types. iter ( ) . map ( |( i, _, coerced_ty) | ( i, coerced_ty) ) )
37783782 . flat_map ( |( i, ty) | {
37793783 let ty = self . resolve_vars_if_possible ( ty) ;
37803784 // We walk the argument type because the argument's type could have
3781- // been `Option<T>`, but the `FullfillmentError ` references `T`.
3785+ // been `Option<T>`, but the `FulfillmentError ` references `T`.
37823786 ty. walk ( )
37833787 . filter ( |& ty| ty == predicate. skip_binder ( ) . self_ty ( ) )
37843788 . map ( move |_| * i)
3785- } ) ;
3786- if let ( Some ( ref_in) , None ) = ( referenced_in. next ( ) , referenced_in. next ( ) ) {
3789+ } )
3790+ . collect :: < Vec < _ > > ( ) ;
3791+
3792+ // Both checked and coerced types could have matched, thus we need to remove
3793+ // duplicates.
3794+ referenced_in. dedup ( ) ;
3795+
3796+ if let ( Some ( ref_in) , None ) = ( referenced_in. pop ( ) , referenced_in. pop ( ) ) {
37873797 // We make sure that only *one* argument matches the obligation failure
3788- // and thet the obligation's span to its expression's.
3798+ // and we assign the obligation's span to its expression's.
37893799 error. obligation . cause . span = args[ ref_in] . span ;
37903800 error. points_at_arg_span = true ;
37913801 }
@@ -3794,8 +3804,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37943804 }
37953805 }
37963806
3797- /// Given a vec of evaluated `FullfillmentError `s and an `fn` call expression, we walk the
3798- /// `PathSegment`s and resolve their type parameters to see if any of the `FullfillmentError `s
3807+ /// Given a vec of evaluated `FulfillmentError `s and an `fn` call expression, we walk the
3808+ /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError `s
37993809 /// were caused by them. If they were, we point at the corresponding type argument's span
38003810 /// instead of the `fn` call path span.
38013811 fn point_at_type_arg_instead_of_call_if_possible (
0 commit comments