@@ -168,24 +168,27 @@ fn satisfied_from_param_env<'tcx>(
168168 param_env : ty:: ParamEnv < ' tcx > ,
169169
170170 infcx : & ' a InferCtxt < ' tcx > ,
171+ single_match : Option < Result < ty:: Const < ' tcx > , ( ) > > ,
171172 }
173+
172174 impl < ' a , ' tcx > TypeVisitor < ' tcx > for Visitor < ' a , ' tcx > {
173175 type BreakTy = ( ) ;
174176 fn visit_const ( & mut self , c : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
175177 debug ! ( "is_const_evaluatable: candidate={:?}" , c) ;
176- if let Ok ( ( ) ) = self . infcx . commit_if_ok ( |_| {
178+ if self . infcx . probe ( |_| {
177179 let ocx = ObligationCtxt :: new_in_snapshot ( self . infcx ) ;
178- if let Ok ( ( ) ) = ocx. eq ( & ObligationCause :: dummy ( ) , self . param_env , c. ty ( ) , self . ct . ty ( ) )
179- && let Ok ( ( ) ) = ocx. eq ( & ObligationCause :: dummy ( ) , self . param_env , c, self . ct )
180+ ocx. eq ( & ObligationCause :: dummy ( ) , self . param_env , c. ty ( ) , self . ct . ty ( ) ) . is_ok ( )
181+ && ocx. eq ( & ObligationCause :: dummy ( ) , self . param_env , c, self . ct ) . is_ok ( )
180182 && ocx. select_all_or_error ( ) . is_empty ( )
181- {
182- Ok ( ( ) )
183- } else {
184- Err ( ( ) )
185- }
186183 } ) {
187- ControlFlow :: BREAK
188- } else if let ty:: ConstKind :: Expr ( e) = c. kind ( ) {
184+ self . single_match = match self . single_match {
185+ None => Some ( Ok ( c) ) ,
186+ Some ( Ok ( o) ) if o == c => Some ( Ok ( c) ) ,
187+ Some ( _) => Some ( Err ( ( ) ) ) ,
188+ } ;
189+ }
190+
191+ if let ty:: ConstKind :: Expr ( e) = c. kind ( ) {
189192 e. visit_with ( self )
190193 } else {
191194 // FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s substs.
@@ -200,22 +203,29 @@ fn satisfied_from_param_env<'tcx>(
200203 }
201204 }
202205
206+ let mut single_match: Option < Result < ty:: Const < ' tcx > , ( ) > > = None ;
207+
203208 for pred in param_env. caller_bounds ( ) {
204209 match pred. kind ( ) . skip_binder ( ) {
205210 ty:: PredicateKind :: ConstEvaluatable ( ce) => {
206211 let b_ct = tcx. expand_abstract_consts ( ce) ;
207- let mut v = Visitor { ct, infcx, param_env } ;
208- let result = b_ct. visit_with ( & mut v) ;
212+ let mut v = Visitor { ct, infcx, param_env, single_match } ;
213+ let _ = b_ct. visit_with ( & mut v) ;
209214
210- if let ControlFlow :: Break ( ( ) ) = result {
211- debug ! ( "is_const_evaluatable: yes" ) ;
212- return true ;
213- }
215+ single_match = v. single_match ;
214216 }
215217 _ => { } // don't care
216218 }
217219 }
218220
221+ if let Some ( Ok ( c) ) = single_match {
222+ let ocx = ObligationCtxt :: new ( infcx) ;
223+ assert ! ( ocx. eq( & ObligationCause :: dummy( ) , param_env, c. ty( ) , ct. ty( ) ) . is_ok( ) ) ;
224+ assert ! ( ocx. eq( & ObligationCause :: dummy( ) , param_env, c, ct) . is_ok( ) ) ;
225+ assert ! ( ocx. select_all_or_error( ) . is_empty( ) ) ;
226+ return true ;
227+ }
228+
219229 debug ! ( "is_const_evaluatable: no" ) ;
220230 false
221231}
0 commit comments