@@ -2011,9 +2011,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
20112011 // attempt to evaluate recursive bounds to see if they are
20122012 // satisfied.
20132013
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.
20172014 /// Returns true if `victim` should be dropped in favor of
20182015 /// `other`. Generally speaking we will drop duplicate
20192016 /// candidates and prefer where-clause candidates.
@@ -2025,13 +2022,46 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
20252022 other : & EvaluatedCandidate < ' tcx > )
20262023 -> bool
20272024 {
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+
20282032 if victim. candidate == other. candidate {
20292033 return true ;
20302034 }
20312035
20322036 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+ } ,
20332063 ObjectCandidate |
2034- ParamCandidate ( _ ) | ProjectionCandidate => match victim. candidate {
2064+ ProjectionCandidate => match victim. candidate {
20352065 AutoImplCandidate ( ..) => {
20362066 bug ! (
20372067 "default implementations shouldn't be recorded \
@@ -2044,8 +2074,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
20442074 BuiltinObjectCandidate |
20452075 BuiltinUnsizeCandidate |
20462076 BuiltinCandidate { .. } => {
2047- // We have a where-clause so don't go around looking
2048- // for impls.
20492077 true
20502078 }
20512079 ObjectCandidate |
@@ -2054,22 +2082,44 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
20542082 // over projection and object candidates.
20552083 true
20562084 } ,
2057- ParamCandidate ( .. ) => false ,
2085+ ParamCandidate ( ref cand ) => is_global ( cand ) ,
20582086 } ,
20592087 ImplCandidate ( other_def) => {
20602088 // See if we can toss out `victim` based on specialization.
20612089 // This requires us to know *for sure* that the `other` impl applies
20622090 // i.e. EvaluatedToOk:
20632091 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+ _ => ( )
20682103 }
20692104 }
20702105
20712106 false
20722107 } ,
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+ }
20732123 _ => false
20742124 }
20752125 }
0 commit comments