@@ -3641,7 +3641,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3641
3641
formal_tys. clone ( )
3642
3642
} ;
3643
3643
3644
- let mut final_arg_types: Vec < ( usize , Ty < ' _ > ) > = vec ! [ ] ;
3644
+ let mut final_arg_types: Vec < ( usize , Ty < ' _ > , Ty < ' _ > ) > = vec ! [ ] ;
3645
3645
3646
3646
// Check the arguments.
3647
3647
// We do this in a pretty awful way: first we type-check any arguments
@@ -3709,7 +3709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3709
3709
// We're processing function arguments so we definitely want to use
3710
3710
// two-phase borrows.
3711
3711
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) ) ;
3713
3713
3714
3714
// 3. Relate the expected type and the formal one,
3715
3715
// if the expected type was used for the coercion.
@@ -3756,14 +3756,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3756
3756
vec ! [ self . tcx. types. err; len]
3757
3757
}
3758
3758
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.
3763
3765
fn point_at_arg_instead_of_call_if_possible (
3764
3766
& self ,
3765
3767
errors : & mut Vec < traits:: FulfillmentError < ' _ > > ,
3766
- final_arg_types : & [ ( usize , Ty < ' tcx > ) ] ,
3768
+ final_arg_types : & [ ( usize , Ty < ' tcx > , Ty < ' tcx > ) ] ,
3767
3769
call_sp : Span ,
3768
3770
args : & ' tcx [ hir:: Expr ] ,
3769
3771
) {
@@ -3773,19 +3775,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3773
3775
for error in errors {
3774
3776
if let ty:: Predicate :: Trait ( predicate) = error. obligation . predicate {
3775
3777
// Collect the argument position for all arguments that could have caused this
3776
- // `FullfillmentError `.
3778
+ // `FulfillmentError `.
3777
3779
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) ) )
3778
3782
. flat_map ( |( i, ty) | {
3779
3783
let ty = self . resolve_vars_if_possible ( ty) ;
3780
3784
// 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`.
3782
3786
ty. walk ( )
3783
3787
. filter ( |& ty| ty == predicate. skip_binder ( ) . self_ty ( ) )
3784
3788
. 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 ( ) ) {
3787
3797
// 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.
3789
3799
error. obligation . cause . span = args[ ref_in] . span ;
3790
3800
error. points_at_arg_span = true ;
3791
3801
}
@@ -3794,8 +3804,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3794
3804
}
3795
3805
}
3796
3806
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
3799
3809
/// were caused by them. If they were, we point at the corresponding type argument's span
3800
3810
/// instead of the `fn` call path span.
3801
3811
fn point_at_type_arg_instead_of_call_if_possible (
0 commit comments