@@ -2011,9 +2011,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
2011
2011
// attempt to evaluate recursive bounds to see if they are
2012
2012
// satisfied.
2013
2013
2014
- /// Returns true if `candidate_i` should be dropped in favor of
2015
- /// `candidate_j`. Generally speaking we will drop duplicate
2016
- /// candidates and prefer where-clause candidates.
2017
2014
/// Returns true if `victim` should be dropped in favor of
2018
2015
/// `other`. Generally speaking we will drop duplicate
2019
2016
/// candidates and prefer where-clause candidates.
@@ -2025,13 +2022,46 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
2025
2022
other : & EvaluatedCandidate < ' tcx > )
2026
2023
-> bool
2027
2024
{
2025
+ // Check if a bound would previously have been removed when normalizing
2026
+ // the param_env so that it can be given the lowest priority. See
2027
+ // #50825 for the motivation for this.
2028
+ let is_global = |cand : & ty:: PolyTraitRef < ' _ > | {
2029
+ cand. is_global ( ) && !cand. has_late_bound_regions ( )
2030
+ } ;
2031
+
2028
2032
if victim. candidate == other. candidate {
2029
2033
return true ;
2030
2034
}
2031
2035
2032
2036
match other. candidate {
2037
+ ParamCandidate ( ref cand) => match victim. candidate {
2038
+ AutoImplCandidate ( ..) => {
2039
+ bug ! (
2040
+ "default implementations shouldn't be recorded \
2041
+ when there are other valid candidates") ;
2042
+ }
2043
+ ImplCandidate ( ..) |
2044
+ ClosureCandidate |
2045
+ GeneratorCandidate |
2046
+ FnPointerCandidate |
2047
+ BuiltinObjectCandidate |
2048
+ BuiltinUnsizeCandidate |
2049
+ BuiltinCandidate { .. } => {
2050
+ // Global bounds from the where clause should be ignored
2051
+ // here (see issue #50825). Otherwise, we have a where
2052
+ // clause so don't go around looking for impls.
2053
+ !is_global ( cand)
2054
+ }
2055
+ ObjectCandidate |
2056
+ ProjectionCandidate => {
2057
+ // Arbitrarily give param candidates priority
2058
+ // over projection and object candidates.
2059
+ !is_global ( cand)
2060
+ } ,
2061
+ ParamCandidate ( ..) => false ,
2062
+ } ,
2033
2063
ObjectCandidate |
2034
- ParamCandidate ( _ ) | ProjectionCandidate => match victim. candidate {
2064
+ ProjectionCandidate => match victim. candidate {
2035
2065
AutoImplCandidate ( ..) => {
2036
2066
bug ! (
2037
2067
"default implementations shouldn't be recorded \
@@ -2044,8 +2074,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
2044
2074
BuiltinObjectCandidate |
2045
2075
BuiltinUnsizeCandidate |
2046
2076
BuiltinCandidate { .. } => {
2047
- // We have a where-clause so don't go around looking
2048
- // for impls.
2049
2077
true
2050
2078
}
2051
2079
ObjectCandidate |
@@ -2054,22 +2082,44 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
2054
2082
// over projection and object candidates.
2055
2083
true
2056
2084
} ,
2057
- ParamCandidate ( .. ) => false ,
2085
+ ParamCandidate ( ref cand ) => is_global ( cand ) ,
2058
2086
} ,
2059
2087
ImplCandidate ( other_def) => {
2060
2088
// See if we can toss out `victim` based on specialization.
2061
2089
// This requires us to know *for sure* that the `other` impl applies
2062
2090
// i.e. EvaluatedToOk:
2063
2091
if other. evaluation == EvaluatedToOk {
2064
- if let ImplCandidate ( victim_def) = victim. candidate {
2065
- let tcx = self . tcx ( ) . global_tcx ( ) ;
2066
- return tcx. specializes ( ( other_def, victim_def) ) ||
2067
- tcx. impls_are_allowed_to_overlap ( other_def, victim_def) ;
2092
+ match victim. candidate {
2093
+ ImplCandidate ( victim_def) => {
2094
+ let tcx = self . tcx ( ) . global_tcx ( ) ;
2095
+ return tcx. specializes ( ( other_def, victim_def) ) ||
2096
+ tcx. impls_are_allowed_to_overlap ( other_def, victim_def) ;
2097
+ }
2098
+ ParamCandidate ( ref cand) => {
2099
+ // Prefer the impl to a global where clause candidate.
2100
+ return is_global ( cand) ;
2101
+ }
2102
+ _ => ( )
2068
2103
}
2069
2104
}
2070
2105
2071
2106
false
2072
2107
} ,
2108
+ ClosureCandidate |
2109
+ GeneratorCandidate |
2110
+ FnPointerCandidate |
2111
+ BuiltinObjectCandidate |
2112
+ BuiltinUnsizeCandidate |
2113
+ BuiltinCandidate { .. } => {
2114
+ match victim. candidate {
2115
+ ParamCandidate ( ref cand) => {
2116
+ // Prefer these to a global where-clause bound
2117
+ // (see issue #50825)
2118
+ is_global ( cand) && other. evaluation == EvaluatedToOk
2119
+ }
2120
+ _ => false ,
2121
+ }
2122
+ }
2073
2123
_ => false
2074
2124
}
2075
2125
}
0 commit comments