@@ -3748,7 +3748,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3748
3748
formal_tys. clone ( )
3749
3749
} ;
3750
3750
3751
- let mut final_arg_types: Vec < ( usize , Ty < ' _ > ) > = vec ! [ ] ;
3751
+ let mut final_arg_types: Vec < ( usize , Ty < ' _ > , Ty < ' _ > ) > = vec ! [ ] ;
3752
3752
3753
3753
// Check the arguments.
3754
3754
// We do this in a pretty awful way: first we type-check any arguments
@@ -3816,7 +3816,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3816
3816
// We're processing function arguments so we definitely want to use
3817
3817
// two-phase borrows.
3818
3818
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) ) ;
3820
3820
3821
3821
// 3. Relate the expected type and the formal one,
3822
3822
// if the expected type was used for the coercion.
@@ -3863,14 +3863,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3863
3863
vec ! [ self . tcx. types. err; len]
3864
3864
}
3865
3865
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.
3870
3872
fn point_at_arg_instead_of_call_if_possible (
3871
3873
& self ,
3872
3874
errors : & mut Vec < traits:: FulfillmentError < ' _ > > ,
3873
- final_arg_types : & [ ( usize , Ty < ' tcx > ) ] ,
3875
+ final_arg_types : & [ ( usize , Ty < ' tcx > , Ty < ' tcx > ) ] ,
3874
3876
call_sp : Span ,
3875
3877
args : & ' tcx [ hir:: Expr ] ,
3876
3878
) {
@@ -3880,19 +3882,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3880
3882
for error in errors {
3881
3883
if let ty:: Predicate :: Trait ( predicate) = error. obligation . predicate {
3882
3884
// Collect the argument position for all arguments that could have caused this
3883
- // `FullfillmentError `.
3885
+ // `FulfillmentError `.
3884
3886
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) ) )
3885
3889
. flat_map ( |( i, ty) | {
3886
3890
let ty = self . resolve_vars_if_possible ( ty) ;
3887
3891
// 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`.
3889
3893
ty. walk ( )
3890
3894
. filter ( |& ty| ty == predicate. skip_binder ( ) . self_ty ( ) )
3891
3895
. 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 ( ) ) {
3894
3904
// 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.
3896
3906
error. obligation . cause . span = args[ ref_in] . span ;
3897
3907
error. points_at_arg_span = true ;
3898
3908
}
@@ -3901,8 +3911,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3901
3911
}
3902
3912
}
3903
3913
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
3906
3916
/// were caused by them. If they were, we point at the corresponding type argument's span
3907
3917
/// instead of the `fn` call path span.
3908
3918
fn point_at_type_arg_instead_of_call_if_possible (
0 commit comments