@@ -173,36 +173,61 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
173
173
& mut self ,
174
174
Goal { param_env, predicate : ct } : Goal < ' tcx , ty:: Const < ' tcx > > ,
175
175
) -> QueryResult < ' tcx > {
176
- match ct. kind ( ) {
177
- ty:: ConstKind :: Unevaluated ( uv) => {
178
- // We never return `NoSolution` here as `try_const_eval_resolve` emits an
179
- // error itself when failing to evaluate, so emitting an additional fulfillment
180
- // error in that case is unnecessary noise. This may change in the future once
181
- // evaluation failures are allowed to impact selection, e.g. generic const
182
- // expressions in impl headers or `where`-clauses.
183
-
184
- // FIXME(generic_const_exprs): Implement handling for generic
185
- // const expressions here.
186
- if let Some ( _normalized) = self . try_const_eval_resolve ( param_env, uv, ct. ty ( ) ) {
187
- self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
188
- } else {
189
- self . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
176
+ let mut responses = vec ! [ ] ;
177
+
178
+ let resolve_response = self . probe_candidate ( "const-evaluatable via resolve" ) . enter ( |ecx| {
179
+ match ct. kind ( ) {
180
+ ty:: ConstKind :: Unevaluated ( uv) => {
181
+ // We never return `NoSolution` here as `try_const_eval_resolve` emits an
182
+ // error itself when failing to evaluate, so emitting an additional fulfillment
183
+ // error in that case is unnecessary noise. This may change in the future once
184
+ // evaluation failures are allowed to impact selection, e.g. generic const
185
+ // expressions in impl headers or `where`-clauses.
186
+ if let Some ( _normalized) = ecx. try_const_eval_resolve ( param_env, uv, ct. ty ( ) ) {
187
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
188
+ } else {
189
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
190
+ }
191
+ }
192
+ ty:: ConstKind :: Infer ( _) => {
193
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
194
+ }
195
+ ty:: ConstKind :: Placeholder ( _)
196
+ | ty:: ConstKind :: Value ( _)
197
+ | ty:: ConstKind :: Error ( _) => {
198
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
199
+ }
200
+ // We can freely ICE here as:
201
+ // - `Param` gets replaced with a placeholder during canonicalization
202
+ // - `Bound` cannot exist as we don't have a binder around the self Type
203
+ // - `Expr` is part of `feature(generic_const_exprs)` and is not implemented yet
204
+ ty:: ConstKind :: Param ( _) | ty:: ConstKind :: Bound ( _, _) | ty:: ConstKind :: Expr ( _) => {
205
+ bug ! ( "unexpect const kind: {:?}" , ct)
190
206
}
191
207
}
192
- ty:: ConstKind :: Infer ( _) => {
193
- self . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
194
- }
195
- ty:: ConstKind :: Placeholder ( _) | ty:: ConstKind :: Value ( _) | ty:: ConstKind :: Error ( _) => {
196
- self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
197
- }
198
- // We can freely ICE here as:
199
- // - `Param` gets replaced with a placeholder during canonicalization
200
- // - `Bound` cannot exist as we don't have a binder around the self Type
201
- // - `Expr` is part of `feature(generic_const_exprs)` and is not implemented yet
202
- ty:: ConstKind :: Param ( _) | ty:: ConstKind :: Bound ( _, _) | ty:: ConstKind :: Expr ( _) => {
203
- bug ! ( "unexpect const kind: {:?}" , ct)
208
+ } ) ;
209
+ responses. extend ( resolve_response) ;
210
+
211
+ // FIXME(generic_const_exprs): We don't walk into these candidates, though perhaps we should.
212
+ for candidate in param_env. caller_bounds ( ) {
213
+ if let ty:: ClauseKind :: ConstEvaluatable ( candidate_ct) = candidate. kind ( ) . skip_binder ( ) {
214
+ responses. extend ( self . probe_candidate ( "const evaluatable via param-env" ) . enter (
215
+ |ecx| {
216
+ let candidate_ct = ecx. instantiate_binder_with_placeholders (
217
+ candidate. kind ( ) . rebind ( candidate_ct) ,
218
+ ) ;
219
+ ecx. eq ( param_env, ct, candidate_ct) ?;
220
+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
221
+ } ,
222
+ ) )
204
223
}
205
224
}
225
+
226
+ if let Some ( response) = self . try_merge_responses ( & responses) {
227
+ Ok ( response)
228
+ } else {
229
+ self . flounder ( & responses)
230
+ }
206
231
}
207
232
208
233
#[ instrument( level = "debug" , skip( self ) , ret) ]
0 commit comments