@@ -465,14 +465,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
465
465
if candidates. len ( ) > 1 {
466
466
let mut i = 0 ;
467
467
while i < candidates. len ( ) {
468
- let is_dup = ( 0 ..candidates. len ( ) ) . filter ( |& j| i != j) . any ( |j| {
468
+ let should_drop_i = ( 0 ..candidates. len ( ) ) . filter ( |& j| i != j) . any ( |j| {
469
469
self . candidate_should_be_dropped_in_favor_of (
470
470
& candidates[ i] ,
471
471
& candidates[ j] ,
472
472
needs_infer,
473
- )
473
+ ) == DropVictim :: Yes
474
474
} ) ;
475
- if is_dup {
475
+ if should_drop_i {
476
476
debug ! ( candidate = ?candidates[ i] , "Dropping candidate #{}/{}" , i, candidates. len( ) ) ;
477
477
candidates. swap_remove ( i) ;
478
478
} else {
@@ -1842,16 +1842,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1842
1842
ProjectionMatchesProjection :: No
1843
1843
}
1844
1844
}
1845
+ }
1845
1846
1846
- ///////////////////////////////////////////////////////////////////////////
1847
- // WINNOW
1848
- //
1849
- // Winnowing is the process of attempting to resolve ambiguity by
1850
- // probing further. During the winnowing process, we unify all
1851
- // type variables and then we also attempt to evaluate recursive
1852
- // bounds to see if they are satisfied.
1847
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
1848
+ enum DropVictim {
1849
+ Yes ,
1850
+ No ,
1851
+ }
1853
1852
1854
- /// Returns `true` if `victim` should be dropped in favor of
1853
+ /// ## Winnowing
1854
+ ///
1855
+ /// Winnowing is the process of attempting to resolve ambiguity by
1856
+ /// probing further. During the winnowing process, we unify all
1857
+ /// type variables and then we also attempt to evaluate recursive
1858
+ /// bounds to see if they are satisfied.
1859
+ impl < ' tcx > SelectionContext < ' _ , ' tcx > {
1860
+ /// Returns `DropVictim::Yes` if `victim` should be dropped in favor of
1855
1861
/// `other`. Generally speaking we will drop duplicate
1856
1862
/// candidates and prefer where-clause candidates.
1857
1863
///
@@ -1861,9 +1867,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1861
1867
victim : & EvaluatedCandidate < ' tcx > ,
1862
1868
other : & EvaluatedCandidate < ' tcx > ,
1863
1869
needs_infer : bool ,
1864
- ) -> bool {
1870
+ ) -> DropVictim {
1865
1871
if victim. candidate == other. candidate {
1866
- return true ;
1872
+ return DropVictim :: Yes ;
1867
1873
}
1868
1874
1869
1875
// Check if a bound would previously have been removed when normalizing
@@ -1887,11 +1893,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1887
1893
}
1888
1894
1889
1895
// FIXME(@jswrenn): this should probably be more sophisticated
1890
- ( TransmutabilityCandidate , _) | ( _, TransmutabilityCandidate ) => false ,
1896
+ ( TransmutabilityCandidate , _) | ( _, TransmutabilityCandidate ) => DropVictim :: No ,
1891
1897
1892
1898
// (*)
1893
- ( BuiltinCandidate { has_nested : false } | ConstDestructCandidate ( _) , _) => true ,
1894
- ( _, BuiltinCandidate { has_nested : false } | ConstDestructCandidate ( _) ) => false ,
1899
+ ( BuiltinCandidate { has_nested : false } | ConstDestructCandidate ( _) , _) => {
1900
+ DropVictim :: Yes
1901
+ }
1902
+ ( _, BuiltinCandidate { has_nested : false } | ConstDestructCandidate ( _) ) => {
1903
+ DropVictim :: No
1904
+ }
1895
1905
1896
1906
( ParamCandidate ( other) , ParamCandidate ( victim) ) => {
1897
1907
let same_except_bound_vars = other. skip_binder ( ) . trait_ref
@@ -1905,28 +1915,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1905
1915
// or the current one if tied (they should both evaluate to the same answer). This is
1906
1916
// probably best characterized as a "hack", since we might prefer to just do our
1907
1917
// best to *not* create essentially duplicate candidates in the first place.
1908
- other. bound_vars ( ) . len ( ) <= victim. bound_vars ( ) . len ( )
1918
+ if other. bound_vars ( ) . len ( ) <= victim. bound_vars ( ) . len ( ) {
1919
+ DropVictim :: Yes
1920
+ } else {
1921
+ DropVictim :: No
1922
+ }
1909
1923
} else if other. skip_binder ( ) . trait_ref == victim. skip_binder ( ) . trait_ref
1910
1924
&& victim. skip_binder ( ) . constness == ty:: BoundConstness :: NotConst
1911
1925
&& other. skip_binder ( ) . polarity == victim. skip_binder ( ) . polarity
1912
1926
{
1913
1927
// Drop otherwise equivalent non-const candidates in favor of const candidates.
1914
- true
1928
+ DropVictim :: Yes
1915
1929
} else {
1916
- false
1930
+ DropVictim :: No
1917
1931
}
1918
1932
}
1919
1933
1920
1934
// Drop otherwise equivalent non-const fn pointer candidates
1921
- ( FnPointerCandidate { .. } , FnPointerCandidate { is_const : false } ) => true ,
1935
+ ( FnPointerCandidate { .. } , FnPointerCandidate { is_const : false } ) => DropVictim :: Yes ,
1922
1936
1923
- // Global bounds from the where clause should be ignored
1924
- // here (see issue #50825). Otherwise, we have a where
1925
- // clause so don't go around looking for impls.
1926
- // Arbitrarily give param candidates priority
1927
- // over projection and object candidates.
1928
1937
(
1929
- ParamCandidate ( ref cand ) ,
1938
+ ParamCandidate ( ref other_cand ) ,
1930
1939
ImplCandidate ( ..)
1931
1940
| ClosureCandidate { .. }
1932
1941
| GeneratorCandidate
@@ -1939,11 +1948,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1939
1948
| TraitAliasCandidate
1940
1949
| ObjectCandidate ( _)
1941
1950
| ProjectionCandidate ( ..) ,
1942
- ) => !is_global ( cand) ,
1943
- ( ObjectCandidate ( _) | ProjectionCandidate ( ..) , ParamCandidate ( ref cand) ) => {
1951
+ ) => {
1952
+ if is_global ( other_cand) {
1953
+ DropVictim :: No
1954
+ } else {
1955
+ // We have a where clause so don't go around looking
1956
+ // for impls. Arbitrarily give param candidates priority
1957
+ // over projection and object candidates.
1958
+ //
1959
+ // Global bounds from the where clause should be ignored
1960
+ // here (see issue #50825).
1961
+ DropVictim :: Yes
1962
+ }
1963
+ }
1964
+ ( ObjectCandidate ( _) | ProjectionCandidate ( ..) , ParamCandidate ( ref victim_cand) ) => {
1944
1965
// Prefer these to a global where-clause bound
1945
1966
// (see issue #50825).
1946
- is_global ( cand )
1967
+ if is_global ( victim_cand ) { DropVictim :: Yes } else { DropVictim :: No }
1947
1968
}
1948
1969
(
1949
1970
ImplCandidate ( _)
@@ -1956,18 +1977,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1956
1977
| TraitUpcastingUnsizeCandidate ( _)
1957
1978
| BuiltinCandidate { has_nested : true }
1958
1979
| TraitAliasCandidate ,
1959
- ParamCandidate ( ref cand ) ,
1980
+ ParamCandidate ( ref victim_cand ) ,
1960
1981
) => {
1961
1982
// Prefer these to a global where-clause bound
1962
1983
// (see issue #50825).
1963
- is_global ( cand) && other. evaluation . must_apply_modulo_regions ( )
1984
+ if is_global ( victim_cand) && other. evaluation . must_apply_modulo_regions ( ) {
1985
+ DropVictim :: Yes
1986
+ } else {
1987
+ DropVictim :: No
1988
+ }
1964
1989
}
1965
1990
1966
1991
( ProjectionCandidate ( i, _) , ProjectionCandidate ( j, _) )
1967
1992
| ( ObjectCandidate ( i) , ObjectCandidate ( j) ) => {
1968
1993
// Arbitrarily pick the lower numbered candidate for backwards
1969
1994
// compatibility reasons. Don't let this affect inference.
1970
- i < j && !needs_infer
1995
+ if i < j && !needs_infer { DropVictim :: Yes } else { DropVictim :: No }
1971
1996
}
1972
1997
( ObjectCandidate ( _) , ProjectionCandidate ( ..) )
1973
1998
| ( ProjectionCandidate ( ..) , ObjectCandidate ( _) ) => {
@@ -1987,7 +2012,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1987
2012
| TraitUpcastingUnsizeCandidate ( _)
1988
2013
| BuiltinCandidate { .. }
1989
2014
| TraitAliasCandidate ,
1990
- ) => true ,
2015
+ ) => DropVictim :: Yes ,
1991
2016
1992
2017
(
1993
2018
ImplCandidate ( ..)
@@ -2001,7 +2026,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2001
2026
| BuiltinCandidate { .. }
2002
2027
| TraitAliasCandidate ,
2003
2028
ObjectCandidate ( _) | ProjectionCandidate ( ..) ,
2004
- ) => false ,
2029
+ ) => DropVictim :: No ,
2005
2030
2006
2031
( & ImplCandidate ( other_def) , & ImplCandidate ( victim_def) ) => {
2007
2032
// See if we can toss out `victim` based on specialization.
@@ -2014,7 +2039,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2014
2039
let tcx = self . tcx ( ) ;
2015
2040
if other. evaluation . must_apply_modulo_regions ( ) {
2016
2041
if tcx. specializes ( ( other_def, victim_def) ) {
2017
- return true ;
2042
+ return DropVictim :: Yes ;
2018
2043
}
2019
2044
}
2020
2045
@@ -2060,13 +2085,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2060
2085
// will then correctly report an inference error, since the
2061
2086
// existence of multiple marker trait impls tells us nothing
2062
2087
// about which one should actually apply.
2063
- ! needs_infer
2088
+ if needs_infer { DropVictim :: No } else { DropVictim :: Yes }
2064
2089
}
2065
- Some ( _) => true ,
2066
- None => false ,
2090
+ Some ( _) => DropVictim :: Yes ,
2091
+ None => DropVictim :: No ,
2067
2092
}
2068
2093
} else {
2069
- false
2094
+ DropVictim :: No
2070
2095
}
2071
2096
}
2072
2097
@@ -2092,10 +2117,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2092
2117
| TraitUpcastingUnsizeCandidate ( _)
2093
2118
| BuiltinCandidate { has_nested : true }
2094
2119
| TraitAliasCandidate ,
2095
- ) => false ,
2120
+ ) => DropVictim :: No ,
2096
2121
}
2097
2122
}
2123
+ }
2098
2124
2125
+ impl < ' tcx > SelectionContext < ' _ , ' tcx > {
2099
2126
fn sized_conditions (
2100
2127
& mut self ,
2101
2128
obligation : & TraitObligation < ' tcx > ,
0 commit comments