@@ -168,7 +168,9 @@ 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 > {
@@ -179,7 +181,9 @@ fn satisfied_from_param_env<'tcx>(
179
181
&& ocx. eq ( & ObligationCause :: dummy ( ) , self . param_env , c, self . ct ) . is_ok ( )
180
182
&& ocx. select_all_or_error ( ) . is_empty ( )
181
183
} ) {
182
- ControlFlow :: BREAK
184
+ self . single_match =
185
+ if self . single_match . is_none ( ) { Some ( Ok ( c) ) } else { Some ( Err ( ( ) ) ) } ;
186
+ ControlFlow :: CONTINUE
183
187
} else if let ty:: ConstKind :: Expr ( e) = c. kind ( ) {
184
188
e. visit_with ( self )
185
189
} else {
@@ -195,22 +199,37 @@ fn satisfied_from_param_env<'tcx>(
195
199
}
196
200
}
197
201
202
+ let mut single_match: Option < Result < ty:: Const < ' tcx > , ( ) > > = None ;
203
+
198
204
for pred in param_env. caller_bounds ( ) {
199
205
match pred. kind ( ) . skip_binder ( ) {
200
206
ty:: PredicateKind :: ConstEvaluatable ( ce) => {
201
207
let b_ct = tcx. expand_abstract_consts ( ce) ;
202
- let mut v = Visitor { ct, infcx, param_env } ;
203
- let result = b_ct. visit_with ( & mut v) ;
204
-
205
- if let ControlFlow :: Break ( ( ) ) = result {
206
- debug ! ( "is_const_evaluatable: yes" ) ;
207
- return true ;
208
+ let mut v = Visitor { ct, infcx, param_env, single_match : None } ;
209
+ let _ = b_ct. visit_with ( & mut v) ;
210
+ if let Some ( inner) = v. single_match {
211
+ single_match = if single_match. is_none ( ) { Some ( inner) } else { Some ( Err ( ( ) ) ) } ;
208
212
}
209
213
}
210
214
_ => { } // don't care
211
215
}
212
216
}
213
217
218
+ if let Some ( c) = single_match {
219
+ if let Ok ( c) = c {
220
+ let is_ok = infcx
221
+ . commit_if_ok ( |_| {
222
+ let ocx = ObligationCtxt :: new_in_snapshot ( 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
+ if ocx. select_all_or_error ( ) . is_empty ( ) { Ok ( ( ) ) } else { Err ( ( ) ) }
226
+ } )
227
+ . is_ok ( ) ;
228
+ assert ! ( is_ok) ;
229
+ }
230
+ return true ;
231
+ }
232
+
214
233
debug ! ( "is_const_evaluatable: no" ) ;
215
234
false
216
235
}
0 commit comments