@@ -657,7 +657,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
657
657
Applicability :: MachineApplicable ,
658
658
) ;
659
659
} ;
660
- self . label_fn_like ( & mut err, fn_def_id, callee_ty, Some ( mismatch_idx) , is_method) ;
660
+ self . label_fn_like (
661
+ & mut err,
662
+ fn_def_id,
663
+ callee_ty,
664
+ Some ( mismatch_idx) ,
665
+ is_method,
666
+ ) ;
661
667
err. emit ( ) ;
662
668
return ;
663
669
}
@@ -1064,8 +1070,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1064
1070
}
1065
1071
let suggestion_text = if let Some ( provided_idx) = provided_idx
1066
1072
&& let ( _, provided_span) = provided_arg_tys[ * provided_idx]
1067
- && let Ok ( arg_text) =
1068
- source_map. span_to_snippet ( provided_span)
1073
+ && let Ok ( arg_text) = source_map. span_to_snippet ( provided_span)
1069
1074
{
1070
1075
arg_text
1071
1076
} else {
@@ -1603,22 +1608,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1603
1608
}
1604
1609
}
1605
1610
1606
- /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
1607
- /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
1608
- /// reference a type argument. The reason to walk also the checked type is that the coerced type
1609
- /// can be not easily comparable with predicate type (because of coercion). If the types match
1610
- /// for either checked or coerced type, and there's only *one* argument that does, we point at
1611
- /// the corresponding argument's expression span instead of the `fn` call path span .
1611
+ /// Given a vector of fulfillment errors, try to adjust the spans of the
1612
+ /// errors to more accurately point at the cause of the failure.
1613
+ ///
1614
+ /// This applies to calls, methods, and struct expressions. This will also
1615
+ /// try to deduplicate errors that are due to the same cause but might
1616
+ /// have been created with different [`ObligationCause`][traits::ObligationCause]s .
1612
1617
pub ( super ) fn adjust_fulfillment_errors_for_expr_obligation (
1613
1618
& self ,
1614
1619
errors : & mut Vec < traits:: FulfillmentError < ' tcx > > ,
1615
1620
) {
1621
+ // Store a mapping from `(Span, Predicate) -> ObligationCause`, so that
1622
+ // other errors that have the same span and predicate can also get fixed,
1623
+ // even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind.
1624
+ // This is important since if we adjust one span but not the other, then
1625
+ // we will have "duplicated" the error on the UI side.
1616
1626
let mut remap_cause = FxHashSet :: default ( ) ;
1617
1627
let mut not_adjusted = vec ! [ ] ;
1618
1628
1619
1629
for error in errors {
1620
1630
let before_span = error. obligation . cause . span ;
1621
- if self . adjust_fulfillment_error_for_expr_obligation ( error) {
1631
+ if self . adjust_fulfillment_error_for_expr_obligation ( error)
1632
+ || before_span != error. obligation . cause . span
1633
+ {
1634
+ // Store both the predicate and the predicate *without constness*
1635
+ // since sometimes we instantiate and check both of these in a
1636
+ // method call, for example.
1622
1637
remap_cause. insert ( (
1623
1638
before_span,
1624
1639
error. obligation . predicate ,
@@ -1630,6 +1645,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1630
1645
error. obligation . cause . clone ( ) ,
1631
1646
) ) ;
1632
1647
} else {
1648
+ // If it failed to be adjusted once around, it may be adjusted
1649
+ // via the "remap cause" mapping the second time...
1633
1650
not_adjusted. push ( error) ;
1634
1651
}
1635
1652
}
@@ -1697,7 +1714,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1697
1714
} ;
1698
1715
1699
1716
// Prefer generics that are local to the fn item, since these are likely
1700
- // to be the cause of the unsatisfied predicaete .
1717
+ // to be the cause of the unsatisfied predicate .
1701
1718
let mut param_to_point_at = find_param_matching ( & |param_ty| {
1702
1719
self . tcx . parent ( generics. type_param ( param_ty, self . tcx ) . def_id ) == def_id
1703
1720
} ) ;
@@ -1708,14 +1725,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1708
1725
&& param_ty. name != rustc_span:: symbol:: kw:: SelfUpper
1709
1726
} ) ;
1710
1727
// Finally, the `Self` parameter is possibly the reason that the predicate
1711
- // is unsatisfied. This is less likely to be true for methods, because the
1728
+ // is unsatisfied. This is less likely to be true for methods, because
1712
1729
// method probe means that we already kinda check that the predicates due
1713
1730
// to the `Self` type are true.
1714
1731
let mut self_param_to_point_at =
1715
1732
find_param_matching ( & |param_ty| param_ty. name == rustc_span:: symbol:: kw:: SelfUpper ) ;
1716
1733
1717
- // For ambiguity errors, we actually want to look for a parameter that is
1718
- // the source of the inference type left over in this predicate.
1734
+ // Finally, for ambiguity-related errors, we actually want to look
1735
+ // for a parameter that is the source of the inference type left
1736
+ // over in this predicate.
1719
1737
if let traits:: FulfillmentErrorCode :: CodeAmbiguity = error. code {
1720
1738
fallback_param_to_point_at = None ;
1721
1739
self_param_to_point_at = None ;
@@ -1724,25 +1742,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1724
1742
}
1725
1743
1726
1744
let hir = self . tcx . hir ( ) ;
1727
-
1728
1745
match hir. get ( hir_id) {
1729
1746
hir:: Node :: Expr ( hir:: Expr { kind : hir:: ExprKind :: Path ( qpath) , hir_id, .. } ) => {
1730
- if let hir:: Node :: Expr ( hir:: Expr { kind : hir:: ExprKind :: Call ( callee, args) , hir_id : call_hir_id, .. } )
1731
- = hir. get ( hir. get_parent_node ( * hir_id) )
1747
+ if let hir:: Node :: Expr ( hir:: Expr {
1748
+ kind : hir:: ExprKind :: Call ( callee, args) ,
1749
+ hir_id : call_hir_id,
1750
+ ..
1751
+ } ) = hir. get ( hir. get_parent_node ( * hir_id) )
1732
1752
&& callee. hir_id == * hir_id
1733
1753
{
1734
- for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] {
1754
+ for param in
1755
+ [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
1756
+ {
1735
1757
if let Some ( param) = param
1736
- && self . point_at_arg_if_possible ( error, def_id, param, * call_hir_id, callee. span , args)
1758
+ && self . point_at_arg_if_possible (
1759
+ error,
1760
+ def_id,
1761
+ param,
1762
+ * call_hir_id,
1763
+ callee. span ,
1764
+ args,
1765
+ )
1737
1766
{
1738
1767
return true ;
1739
1768
}
1740
1769
}
1741
-
1742
1770
// Notably, we only point to params that are local to the
1743
1771
// item we're checking, since those are the ones we are able
1744
- // to look in the hir::PathSegment for. Everything else
1745
- // would require a deeper search into the qpath than I think
1772
+ // to look in the final ` hir::PathSegment` for. Everything else
1773
+ // would require a deeper search into the ` qpath` than I think
1746
1774
// is worthwhile.
1747
1775
if let Some ( param_to_point_at) = param_to_point_at
1748
1776
&& self . point_at_path_if_possible ( error, def_id, param_to_point_at, qpath)
@@ -1758,12 +1786,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1758
1786
for param in [ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
1759
1787
{
1760
1788
if let Some ( param) = param
1761
- && self . point_at_arg_if_possible ( error, def_id, param, hir_id, segment. ident . span , args)
1789
+ && self . point_at_arg_if_possible (
1790
+ error,
1791
+ def_id,
1792
+ param,
1793
+ hir_id,
1794
+ segment. ident . span ,
1795
+ args,
1796
+ )
1762
1797
{
1763
1798
return true ;
1764
1799
}
1765
1800
}
1766
-
1767
1801
if let Some ( param_to_point_at) = param_to_point_at
1768
1802
&& self . point_at_generic_if_possible ( error, def_id, param_to_point_at, segment)
1769
1803
{
@@ -1780,13 +1814,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1780
1814
[ param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
1781
1815
{
1782
1816
if let Some ( param) = param
1783
- && self . point_at_field_if_possible ( error, def_id, param, variant_def_id, fields)
1817
+ && self . point_at_field_if_possible (
1818
+ error,
1819
+ def_id,
1820
+ param,
1821
+ variant_def_id,
1822
+ fields,
1823
+ )
1784
1824
{
1785
1825
return true ;
1786
1826
}
1787
1827
}
1788
1828
}
1789
-
1790
1829
if let Some ( param_to_point_at) = param_to_point_at
1791
1830
&& self . point_at_path_if_possible ( error, def_id, param_to_point_at, qpath)
1792
1831
{
@@ -1799,32 +1838,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1799
1838
false
1800
1839
}
1801
1840
1802
- fn point_at_path_if_possible (
1803
- & self ,
1804
- error : & mut traits:: FulfillmentError < ' tcx > ,
1805
- def_id : DefId ,
1806
- param : ty:: GenericArg < ' tcx > ,
1807
- qpath : & QPath < ' tcx > ,
1808
- ) -> bool {
1809
- match qpath {
1810
- hir:: QPath :: Resolved ( _, path) => {
1811
- if let Some ( segment) = path. segments . last ( )
1812
- && self . point_at_generic_if_possible ( error, def_id, param, segment)
1813
- {
1814
- return true ;
1815
- }
1816
- }
1817
- hir:: QPath :: TypeRelative ( _, segment) => {
1818
- if self . point_at_generic_if_possible ( error, def_id, param, segment) {
1819
- return true ;
1820
- }
1821
- }
1822
- _ => { }
1823
- }
1824
-
1825
- false
1826
- }
1827
-
1828
1841
fn point_at_arg_if_possible (
1829
1842
& self ,
1830
1843
error : & mut traits:: FulfillmentError < ' tcx > ,
@@ -1839,29 +1852,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1839
1852
. inputs ( )
1840
1853
. iter ( )
1841
1854
. enumerate ( )
1842
- . filter ( |( _, ty) | find_param_in_ty ( ty, param_to_point_at) )
1855
+ . filter ( |( _, ty) | find_param_in_ty ( * * ty, param_to_point_at) )
1843
1856
. collect ( ) ;
1844
1857
1845
- if let [ ( idx, _) ] = args_referencing_param. as_slice ( )
1846
- && let Some ( arg) = args. get ( * idx)
1847
- {
1848
- error. obligation . cause . span = arg. span ;
1858
+ // If there's one field that references the given generic, great!
1859
+ if let [ ( idx, _) ] = args_referencing_param. as_slice ( ) && let Some ( arg) = args. get ( * idx) {
1860
+ error. obligation . cause . span = arg. span . find_ancestor_in_same_ctxt ( error. obligation . cause . span ) . unwrap_or ( arg. span ) ;
1849
1861
error. obligation . cause . map_code ( |parent_code| {
1850
1862
ObligationCauseCode :: FunctionArgumentObligation {
1851
1863
arg_hir_id : arg. hir_id ,
1852
1864
call_hir_id,
1853
1865
parent_code,
1854
1866
}
1855
1867
} ) ;
1856
- true
1868
+ return true ;
1857
1869
} else if args_referencing_param. len ( ) > 0 {
1858
- // If more than one argument applies, then point to the callee
1870
+ // If more than one argument applies, then point to the callee span at least...
1859
1871
// We have chance to fix this up further in `point_at_generics_if_possible`
1860
1872
error. obligation . cause . span = callee_span;
1861
- false
1862
- } else {
1863
- false
1864
1873
}
1874
+
1875
+ false
1865
1876
}
1866
1877
1867
1878
fn point_at_field_if_possible (
@@ -1873,30 +1884,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1873
1884
expr_fields : & [ hir:: ExprField < ' tcx > ] ,
1874
1885
) -> bool {
1875
1886
let def = self . tcx . adt_def ( def_id) ;
1887
+
1876
1888
let identity_substs = ty:: InternalSubsts :: identity_for_item ( self . tcx , def_id) ;
1877
1889
let fields_referencing_param: Vec < _ > = def
1878
1890
. variant_with_id ( variant_def_id)
1879
1891
. fields
1880
1892
. iter ( )
1881
1893
. filter ( |field| {
1882
1894
let field_ty = field. ty ( self . tcx , identity_substs) ;
1883
- match find_param_in_ty ( field_ty, param_to_point_at) {
1884
- Ok ( value) => value,
1885
- Err ( value) => return value,
1886
- }
1895
+ find_param_in_ty ( field_ty, param_to_point_at)
1887
1896
} )
1888
1897
. collect ( ) ;
1898
+
1889
1899
if let [ field] = fields_referencing_param. as_slice ( ) {
1890
1900
for expr_field in expr_fields {
1901
+ // Look for the ExprField that matches the field, using the
1902
+ // same rules that check_expr_struct uses for macro hygiene.
1891
1903
if self . tcx . adjust_ident ( expr_field. ident , variant_def_id) == field. ident ( self . tcx )
1892
1904
{
1893
- error. obligation . cause . span = expr_field. span ;
1905
+ error. obligation . cause . span = expr_field
1906
+ . span
1907
+ . find_ancestor_in_same_ctxt ( error. obligation . cause . span )
1908
+ . unwrap_or ( expr_field. span ) ;
1909
+ return true ;
1894
1910
}
1895
1911
}
1896
- true
1897
- } else {
1898
- false
1899
1912
}
1913
+
1914
+ false
1915
+ }
1916
+
1917
+ fn point_at_path_if_possible (
1918
+ & self ,
1919
+ error : & mut traits:: FulfillmentError < ' tcx > ,
1920
+ def_id : DefId ,
1921
+ param : ty:: GenericArg < ' tcx > ,
1922
+ qpath : & QPath < ' tcx > ,
1923
+ ) -> bool {
1924
+ match qpath {
1925
+ hir:: QPath :: Resolved ( _, path) => {
1926
+ if let Some ( segment) = path. segments . last ( )
1927
+ && self . point_at_generic_if_possible ( error, def_id, param, segment)
1928
+ {
1929
+ return true ;
1930
+ }
1931
+ }
1932
+ hir:: QPath :: TypeRelative ( _, segment) => {
1933
+ if self . point_at_generic_if_possible ( error, def_id, param, segment) {
1934
+ return true ;
1935
+ }
1936
+ }
1937
+ _ => { }
1938
+ }
1939
+
1940
+ false
1900
1941
}
1901
1942
1902
1943
fn point_at_generic_if_possible (
@@ -1921,7 +1962,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1921
1962
. iter ( )
1922
1963
. filter ( |arg| matches ! ( arg, hir:: GenericArg :: Type ( _) ) )
1923
1964
. nth ( index) else { return false ; } ;
1924
- error. obligation . cause . span = arg. span ( ) ;
1965
+ error. obligation . cause . span = arg
1966
+ . span ( )
1967
+ . find_ancestor_in_same_ctxt ( error. obligation . cause . span )
1968
+ . unwrap_or ( arg. span ( ) ) ;
1925
1969
true
1926
1970
}
1927
1971
@@ -1935,11 +1979,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1935
1979
type BreakTy = ty:: GenericArg < ' tcx > ;
1936
1980
fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> std:: ops:: ControlFlow < Self :: BreakTy > {
1937
1981
if let Some ( origin) = self . 0 . type_var_origin ( ty)
1938
- && let TypeVariableOriginKind :: TypeParameterDefinition ( _, Some ( def_id) )
1939
- = origin. kind
1982
+ && let TypeVariableOriginKind :: TypeParameterDefinition ( _, Some ( def_id) ) =
1983
+ origin. kind
1940
1984
&& let generics = self . 0 . tcx . generics_of ( self . 1 )
1941
1985
&& let Some ( index) = generics. param_def_id_to_index ( self . 0 . tcx , def_id)
1942
- && let Some ( subst) = ty:: InternalSubsts :: identity_for_item ( self . 0 . tcx , self . 1 ) . get ( index as usize )
1986
+ && let Some ( subst) = ty:: InternalSubsts :: identity_for_item ( self . 0 . tcx , self . 1 )
1987
+ . get ( index as usize )
1943
1988
{
1944
1989
ControlFlow :: Break ( * subst)
1945
1990
} else {
@@ -2015,14 +2060,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2015
2060
let new_def_id = self . probe ( |_| {
2016
2061
let trait_ref = ty:: TraitRef :: new (
2017
2062
call_kind. to_def_id ( self . tcx ) ,
2018
- self . tcx . mk_substs ( [
2019
- ty:: GenericArg :: from ( callee_ty) ,
2020
- self . next_ty_var ( TypeVariableOrigin {
2021
- kind : TypeVariableOriginKind :: MiscVariable ,
2022
- span : rustc_span:: DUMMY_SP ,
2023
- } )
2024
- . into ( ) ,
2025
- ] . into_iter ( ) ) ,
2063
+ self . tcx . mk_substs (
2064
+ [
2065
+ ty:: GenericArg :: from ( callee_ty) ,
2066
+ self . next_ty_var ( TypeVariableOrigin {
2067
+ kind : TypeVariableOriginKind :: MiscVariable ,
2068
+ span : rustc_span:: DUMMY_SP ,
2069
+ } )
2070
+ . into ( ) ,
2071
+ ]
2072
+ . into_iter ( ) ,
2073
+ ) ,
2026
2074
) ;
2027
2075
let obligation = traits:: Obligation :: new (
2028
2076
traits:: ObligationCause :: dummy ( ) ,
@@ -2037,7 +2085,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2037
2085
Ok ( Some ( traits:: ImplSource :: UserDefined ( impl_source) ) ) => {
2038
2086
Some ( impl_source. impl_def_id )
2039
2087
}
2040
- _ => None
2088
+ _ => None ,
2041
2089
}
2042
2090
} ) ;
2043
2091
if let Some ( new_def_id) = new_def_id {
@@ -2092,22 +2140,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2092
2140
}
2093
2141
}
2094
2142
2095
- fn find_param_in_ty ( ty : Ty , param_to_point_at : ty:: GenericArg ) -> bool {
2143
+ fn find_param_in_ty < ' tcx > ( ty : Ty < ' tcx > , param_to_point_at : ty:: GenericArg < ' tcx > ) -> bool {
2096
2144
let mut walk = ty. walk ( ) ;
2097
2145
while let Some ( arg) = walk. next ( ) {
2098
2146
if arg == param_to_point_at {
2099
- return true ;
2100
- } else if let ty:: GenericArgKind :: Type ( ty) = arg. unpack ( )
2101
- && let ty:: Projection ( ..) = ty. kind ( )
2102
- {
2103
- // This logic may seem a bit strange, but typically when
2104
- // we have a projection type in a function signature, the
2105
- // argument that's being passed into that signature is
2106
- // not actually constraining that projection's substs in
2107
- // a meaningful way. So we skip it, and see improvements
2108
- // in some UI tests.
2109
- walk. skip_current_subtree ( ) ;
2110
- }
2147
+ return true ;
2148
+ } else if let ty:: GenericArgKind :: Type ( ty) = arg. unpack ( )
2149
+ && let ty:: Projection ( ..) = ty. kind ( )
2150
+ {
2151
+ // This logic may seem a bit strange, but typically when
2152
+ // we have a projection type in a function signature, the
2153
+ // argument that's being passed into that signature is
2154
+ // not actually constraining that projection's substs in
2155
+ // a meaningful way. So we skip it, and see improvements
2156
+ // in some UI tests.
2157
+ walk. skip_current_subtree ( ) ;
2158
+ }
2111
2159
}
2112
2160
false
2113
2161
}
0 commit comments