@@ -370,45 +370,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
370
370
// `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
371
371
let coerce_ty = expected. only_has_type ( self ) . unwrap_or ( formal_ty) ;
372
372
373
+ final_arg_types. push ( ( i, checked_ty, coerce_ty) ) ;
374
+
373
375
// Cause selection errors caused by resolving a single argument to point at the
374
376
// argument and not the call. This is otherwise redundant with the `demand_coerce`
375
377
// call immediately after, but it lets us customize the span pointed to in the
376
378
// fulfillment error to be more accurate.
377
379
let _ = self . resolve_vars_with_obligations_and_mutate_fulfillment (
378
380
coerce_ty,
379
381
|errors| {
380
- // This is not coming from a macro or a `derive`.
381
- if sp. desugaring_kind ( ) . is_none ( )
382
- && !arg. span . from_expansion ( )
383
- // Do not change the spans of `async fn`s.
384
- && !matches ! (
385
- expr. kind,
386
- hir:: ExprKind :: Call (
387
- hir:: Expr {
388
- kind: hir:: ExprKind :: Path ( hir:: QPath :: LangItem ( _, _) ) ,
389
- ..
390
- } ,
391
- _
392
- )
393
- ) {
394
- for error in errors {
395
- error. obligation . cause . make_mut ( ) . span = arg. span ;
396
- let code = error. obligation . cause . code . clone ( ) ;
397
- error. obligation . cause . make_mut ( ) . code =
398
- ObligationCauseCode :: FunctionArgumentObligation {
399
- arg_hir_id : arg. hir_id ,
400
- call_hir_id : expr. hir_id ,
401
- parent_code : Lrc :: new ( code) ,
402
- } ;
403
- }
404
- }
382
+ self . point_at_type_arg_instead_of_call_if_possible ( errors, expr) ;
383
+ self . point_at_arg_instead_of_call_if_possible (
384
+ errors,
385
+ & final_arg_types,
386
+ expr,
387
+ sp,
388
+ args,
389
+ ) ;
405
390
} ,
406
391
) ;
407
392
408
393
// We're processing function arguments so we definitely want to use
409
394
// two-phase borrows.
410
395
self . demand_coerce ( & arg, checked_ty, coerce_ty, None , AllowTwoPhase :: Yes ) ;
411
- final_arg_types. push ( ( i, checked_ty, coerce_ty) ) ;
412
396
413
397
// 3. Relate the expected type and the formal one,
414
398
// if the expected type was used for the coercion.
@@ -973,45 +957,79 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
973
957
continue ;
974
958
}
975
959
976
- if let ty:: PredicateKind :: Trait ( predicate) =
977
- error. obligation . predicate . kind ( ) . skip_binder ( )
978
- {
979
- // Collect the argument position for all arguments that could have caused this
980
- // `FulfillmentError`.
981
- let mut referenced_in = final_arg_types
982
- . iter ( )
983
- . map ( |& ( i, checked_ty, _) | ( i, checked_ty) )
984
- . chain ( final_arg_types. iter ( ) . map ( |& ( i, _, coerced_ty) | ( i, coerced_ty) ) )
985
- . flat_map ( |( i, ty) | {
986
- let ty = self . resolve_vars_if_possible ( ty) ;
987
- // We walk the argument type because the argument's type could have
988
- // been `Option<T>`, but the `FulfillmentError` references `T`.
989
- if ty. walk ( self . tcx ) . any ( |arg| arg == predicate. self_ty ( ) . into ( ) ) {
990
- Some ( i)
991
- } else {
992
- None
993
- }
994
- } )
995
- . collect :: < Vec < usize > > ( ) ;
996
-
997
- // Both checked and coerced types could have matched, thus we need to remove
998
- // duplicates.
999
-
1000
- // We sort primitive type usize here and can use unstable sort
1001
- referenced_in. sort_unstable ( ) ;
1002
- referenced_in. dedup ( ) ;
1003
-
1004
- if let ( Some ( ref_in) , None ) = ( referenced_in. pop ( ) , referenced_in. pop ( ) ) {
1005
- // We make sure that only *one* argument matches the obligation failure
1006
- // and we assign the obligation's span to its expression's.
1007
- error. obligation . cause . make_mut ( ) . span = args[ ref_in] . span ;
1008
- let code = error. obligation . cause . code . clone ( ) ;
1009
- error. obligation . cause . make_mut ( ) . code =
1010
- ObligationCauseCode :: FunctionArgumentObligation {
1011
- arg_hir_id : args[ ref_in] . hir_id ,
1012
- call_hir_id : expr. hir_id ,
1013
- parent_code : Lrc :: new ( code) ,
1014
- } ;
960
+ // Peel derived obligation, because it's the type that originally
961
+ // started this inference chain that matters, not the one we wound
962
+ // up with at the end.
963
+ fn unpeel_to_top (
964
+ mut code : Lrc < ObligationCauseCode < ' _ > > ,
965
+ ) -> Lrc < ObligationCauseCode < ' _ > > {
966
+ let mut result_code = code. clone ( ) ;
967
+ loop {
968
+ let parent = match & * code {
969
+ ObligationCauseCode :: BuiltinDerivedObligation ( c)
970
+ | ObligationCauseCode :: ImplDerivedObligation ( c)
971
+ | ObligationCauseCode :: DerivedObligation ( c) => c. parent_code . clone ( ) ,
972
+ _ => break ,
973
+ } ;
974
+ result_code = std:: mem:: replace ( & mut code, parent) ;
975
+ }
976
+ result_code
977
+ }
978
+ let self_: ty:: subst:: GenericArg < ' _ > = match & * unpeel_to_top ( Lrc :: new ( error. obligation . cause . code . clone ( ) ) ) {
979
+ ObligationCauseCode :: BuiltinDerivedObligation ( code) |
980
+ ObligationCauseCode :: ImplDerivedObligation ( code) |
981
+ ObligationCauseCode :: DerivedObligation ( code) => {
982
+ code. parent_trait_ref . self_ty ( ) . skip_binder ( ) . into ( )
983
+ }
984
+ _ if let ty:: PredicateKind :: Trait ( predicate) =
985
+ error. obligation . predicate . kind ( ) . skip_binder ( ) => {
986
+ predicate. self_ty ( ) . into ( )
987
+ }
988
+ _ => continue ,
989
+ } ;
990
+ let self_ = self . resolve_vars_if_possible ( self_) ;
991
+
992
+ // Collect the argument position for all arguments that could have caused this
993
+ // `FulfillmentError`.
994
+ let mut referenced_in = final_arg_types
995
+ . iter ( )
996
+ . map ( |& ( i, checked_ty, _) | ( i, checked_ty) )
997
+ . chain ( final_arg_types. iter ( ) . map ( |& ( i, _, coerced_ty) | ( i, coerced_ty) ) )
998
+ . flat_map ( |( i, ty) | {
999
+ let ty = self . resolve_vars_if_possible ( ty) ;
1000
+ // We walk the argument type because the argument's type could have
1001
+ // been `Option<T>`, but the `FulfillmentError` references `T`.
1002
+ if ty. walk ( self . tcx ) . any ( |arg| arg == self_) { Some ( i) } else { None }
1003
+ } )
1004
+ . collect :: < Vec < usize > > ( ) ;
1005
+
1006
+ // Both checked and coerced types could have matched, thus we need to remove
1007
+ // duplicates.
1008
+
1009
+ // We sort primitive type usize here and can use unstable sort
1010
+ referenced_in. sort_unstable ( ) ;
1011
+ referenced_in. dedup ( ) ;
1012
+
1013
+ if let ( Some ( ref_in) , None ) = ( referenced_in. pop ( ) , referenced_in. pop ( ) ) {
1014
+ // Do not point at the inside of a macro.
1015
+ // That would often result in poor error messages.
1016
+ if args[ ref_in] . span . from_expansion ( ) {
1017
+ return ;
1018
+ }
1019
+ // We make sure that only *one* argument matches the obligation failure
1020
+ // and we assign the obligation's span to its expression's.
1021
+ error. obligation . cause . make_mut ( ) . span = args[ ref_in] . span ;
1022
+ let code = error. obligation . cause . code . clone ( ) ;
1023
+ error. obligation . cause . make_mut ( ) . code =
1024
+ ObligationCauseCode :: FunctionArgumentObligation {
1025
+ arg_hir_id : args[ ref_in] . hir_id ,
1026
+ call_hir_id : expr. hir_id ,
1027
+ parent_code : Lrc :: new ( code) ,
1028
+ } ;
1029
+ } else if error. obligation . cause . make_mut ( ) . span == call_sp {
1030
+ // Make function calls point at the callee, not the whole thing.
1031
+ if let hir:: ExprKind :: Call ( callee, _) = expr. kind {
1032
+ error. obligation . cause . make_mut ( ) . span = callee. span ;
1015
1033
}
1016
1034
}
1017
1035
}
0 commit comments