@@ -1629,7 +1629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1629
1629
return ;
1630
1630
}
1631
1631
1632
- for error in errors {
1632
+ ' outer : for error in errors {
1633
1633
// Only if the cause is somewhere inside the expression we want try to point at arg.
1634
1634
// Otherwise, it means that the cause is somewhere else and we should not change
1635
1635
// anything because we can break the correct span.
@@ -1671,10 +1671,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1671
1671
_ => continue ,
1672
1672
} ;
1673
1673
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
+ }
1674
1697
1675
1698
// Collect the argument position for all arguments that could have caused this
1676
1699
// `FulfillmentError`.
1677
- let typeck_results = self . typeck_results . borrow ( ) ;
1678
1700
let mut referenced_in: Vec < _ > = std:: iter:: zip ( expected_tys, args)
1679
1701
. enumerate ( )
1680
1702
. flat_map ( |( idx, ( expected_ty, arg) ) | {
@@ -1688,7 +1710,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1688
1710
let ty = self . resolve_vars_if_possible ( ty) ;
1689
1711
// We walk the argument type because the argument's type could have
1690
1712
// 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 }
1692
1714
} )
1693
1715
. collect ( ) ;
1694
1716
@@ -1699,18 +1721,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1699
1721
referenced_in. sort_unstable ( ) ;
1700
1722
referenced_in. dedup ( ) ;
1701
1723
1702
- if let ( Some ( ref_in ) , None ) = ( referenced_in. pop ( ) , referenced_in . pop ( ) ) {
1724
+ if let & [ idx ] = & referenced_in[ .. ] {
1703
1725
// Do not point at the inside of a macro.
1704
1726
// 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 ;
1707
1729
}
1708
1730
// We make sure that only *one* argument matches the obligation failure
1709
1731
// 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 ;
1711
1733
error. obligation . cause . map_code ( |parent_code| {
1712
1734
ObligationCauseCode :: FunctionArgumentObligation {
1713
- arg_hir_id : args[ ref_in ] . hir_id ,
1735
+ arg_hir_id : args[ idx ] . hir_id ,
1714
1736
call_hir_id : expr. hir_id ,
1715
1737
parent_code,
1716
1738
}
0 commit comments