@@ -168,24 +168,27 @@ fn satisfied_from_param_env<'tcx>(
168
168
param_env : ty:: ParamEnv < ' tcx > ,
169
169
170
170
infcx : & ' a InferCtxt < ' tcx > ,
171
+ single_match : Option < Result < ty:: Const < ' tcx > , ( ) > > ,
171
172
}
173
+
172
174
impl < ' a , ' tcx > TypeVisitor < ' tcx > for Visitor < ' a , ' tcx > {
173
175
type BreakTy = ( ) ;
174
176
fn visit_const ( & mut self , c : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
175
177
debug ! ( "is_const_evaluatable: candidate={:?}" , c) ;
176
- if let Ok ( ( ) ) = self . infcx . commit_if_ok ( |_| {
178
+ if self . infcx . probe ( |_| {
177
179
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 ( )
180
182
&& ocx. select_all_or_error ( ) . is_empty ( )
181
- {
182
- Ok ( ( ) )
183
- } else {
184
- Err ( ( ) )
185
- }
186
183
} ) {
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 ( ) {
189
192
e. visit_with ( self )
190
193
} else {
191
194
// 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>(
200
203
}
201
204
}
202
205
206
+ let mut single_match: Option < Result < ty:: Const < ' tcx > , ( ) > > = None ;
207
+
203
208
for pred in param_env. caller_bounds ( ) {
204
209
match pred. kind ( ) . skip_binder ( ) {
205
210
ty:: PredicateKind :: ConstEvaluatable ( ce) => {
206
211
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) ;
209
214
210
- if let ControlFlow :: Break ( ( ) ) = result {
211
- debug ! ( "is_const_evaluatable: yes" ) ;
212
- return true ;
213
- }
215
+ single_match = v. single_match ;
214
216
}
215
217
_ => { } // don't care
216
218
}
217
219
}
218
220
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
+
219
229
debug ! ( "is_const_evaluatable: no" ) ;
220
230
false
221
231
}
0 commit comments