@@ -370,45 +370,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
370370 // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
371371 let coerce_ty = expected. only_has_type ( self ) . unwrap_or ( formal_ty) ;
372372
373+ final_arg_types. push ( ( i, checked_ty, coerce_ty) ) ;
374+
373375 // Cause selection errors caused by resolving a single argument to point at the
374376 // argument and not the call. This is otherwise redundant with the `demand_coerce`
375377 // call immediately after, but it lets us customize the span pointed to in the
376378 // fulfillment error to be more accurate.
377379 let _ = self . resolve_vars_with_obligations_and_mutate_fulfillment (
378380 coerce_ty,
379381 |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+ ) ;
405390 } ,
406391 ) ;
407392
408393 // We're processing function arguments so we definitely want to use
409394 // two-phase borrows.
410395 self . demand_coerce ( & arg, checked_ty, coerce_ty, None , AllowTwoPhase :: Yes ) ;
411- final_arg_types. push ( ( i, checked_ty, coerce_ty) ) ;
412396
413397 // 3. Relate the expected type and the formal one,
414398 // if the expected type was used for the coercion.
@@ -973,45 +957,79 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
973957 continue ;
974958 }
975959
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 ;
10151033 }
10161034 }
10171035 }
0 commit comments