@@ -1629,7 +1629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16291629 return ;
16301630 }
16311631
1632- for error in errors {
1632+ ' outer : for error in errors {
16331633 // Only if the cause is somewhere inside the expression we want try to point at arg.
16341634 // Otherwise, it means that the cause is somewhere else and we should not change
16351635 // anything because we can break the correct span.
@@ -1671,10 +1671,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16711671 _ => continue ,
16721672 } ;
16731673 let self_ = self . resolve_vars_if_possible ( self_) ;
1674+ let ty_matches_self = |ty : Ty < ' tcx > | ty. walk ( ) . any ( |arg| arg == self_) ;
1675+
1676+ let typeck_results = self . typeck_results . borrow ( ) ;
1677+
1678+ for ( idx, arg) in args. iter ( ) . enumerate ( ) {
1679+ // Don't adjust the span if we already have a more precise span
1680+ // within one of the args.
1681+ if arg. span . contains ( error. obligation . cause . span ) {
1682+ let references_arg =
1683+ typeck_results. expr_ty_opt ( arg) . map_or ( false , & ty_matches_self)
1684+ || expected_tys. get ( idx) . copied ( ) . map_or ( false , & ty_matches_self) ;
1685+ if references_arg && !arg. span . from_expansion ( ) {
1686+ error. obligation . cause . map_code ( |parent_code| {
1687+ ObligationCauseCode :: FunctionArgumentObligation {
1688+ arg_hir_id : args[ idx] . hir_id ,
1689+ call_hir_id : expr. hir_id ,
1690+ parent_code,
1691+ }
1692+ } )
1693+ }
1694+ continue ' outer;
1695+ }
1696+ }
16741697
16751698 // Collect the argument position for all arguments that could have caused this
16761699 // `FulfillmentError`.
1677- let typeck_results = self . typeck_results . borrow ( ) ;
16781700 let mut referenced_in: Vec < _ > = std:: iter:: zip ( expected_tys, args)
16791701 . enumerate ( )
16801702 . flat_map ( |( idx, ( expected_ty, arg) ) | {
@@ -1688,7 +1710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16881710 let ty = self . resolve_vars_if_possible ( ty) ;
16891711 // We walk the argument type because the argument's type could have
16901712 // been `Option<T>`, but the `FulfillmentError` references `T`.
1691- if ty . walk ( ) . any ( |arg| arg == self_ ) { Some ( i) } else { None }
1713+ if ty_matches_self ( ty ) { Some ( i) } else { None }
16921714 } )
16931715 . collect ( ) ;
16941716
@@ -1699,18 +1721,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16991721 referenced_in. sort_unstable ( ) ;
17001722 referenced_in. dedup ( ) ;
17011723
1702- if let ( Some ( ref_in ) , None ) = ( referenced_in. pop ( ) , referenced_in . pop ( ) ) {
1724+ if let & [ idx ] = & referenced_in[ .. ] {
17031725 // Do not point at the inside of a macro.
17041726 // That would often result in poor error messages.
1705- if args[ ref_in ] . span . from_expansion ( ) {
1706- return ;
1727+ if args[ idx ] . span . from_expansion ( ) {
1728+ continue ;
17071729 }
17081730 // We make sure that only *one* argument matches the obligation failure
17091731 // and we assign the obligation's span to its expression's.
1710- error. obligation . cause . span = args[ ref_in ] . span ;
1732+ error. obligation . cause . span = args[ idx ] . span ;
17111733 error. obligation . cause . map_code ( |parent_code| {
17121734 ObligationCauseCode :: FunctionArgumentObligation {
1713- arg_hir_id : args[ ref_in ] . hir_id ,
1735+ arg_hir_id : args[ idx ] . hir_id ,
17141736 call_hir_id : expr. hir_id ,
17151737 parent_code,
17161738 }
0 commit comments