@@ -26,14 +26,35 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
26
26
/// "Intercept" a function call to a panic-related function
27
27
/// because we have something special to do for it.
28
28
/// If this returns successfully (`Ok`), the function should just be evaluated normally.
29
- fn hook_panic_fn (
29
+ fn hook_special_const_fn (
30
30
& mut self ,
31
31
instance : ty:: Instance < ' tcx > ,
32
32
args : & [ OpTy < ' tcx > ] ,
33
+ is_const_fn : bool ,
33
34
) -> InterpResult < ' tcx , Option < ty:: Instance < ' tcx > > > {
34
35
// The list of functions we handle here must be in sync with
35
- // `is_lang_panic_fn ` in `transform/check_consts/mod.rs`.
36
+ // `is_lang_special_const_fn ` in `transform/check_consts/mod.rs`.
36
37
let def_id = instance. def_id ( ) ;
38
+
39
+ if is_const_fn {
40
+ if Some ( def_id) == self . tcx . lang_items ( ) . const_eval_select ( ) {
41
+ // redirect to const_eval_select_ct
42
+ if let Some ( const_eval_select) = self . tcx . lang_items ( ) . const_eval_select_ct ( ) {
43
+ return Ok ( Some (
44
+ ty:: Instance :: resolve (
45
+ * self . tcx ,
46
+ ty:: ParamEnv :: reveal_all ( ) ,
47
+ const_eval_select,
48
+ instance. substs ,
49
+ )
50
+ . unwrap ( )
51
+ . unwrap ( ) ,
52
+ ) ) ;
53
+ }
54
+ }
55
+ return Ok ( None ) ;
56
+ }
57
+
37
58
if Some ( def_id) == self . tcx . lang_items ( ) . panic_fn ( )
38
59
|| Some ( def_id) == self . tcx . lang_items ( ) . panic_str ( )
39
60
|| Some ( def_id) == self . tcx . lang_items ( ) . panic_display ( )
@@ -255,31 +276,31 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
255
276
256
277
// Only check non-glue functions
257
278
if let ty:: InstanceDef :: Item ( def) = instance. def {
279
+ let mut is_const_fn = true ;
280
+
258
281
// Execution might have wandered off into other crates, so we cannot do a stability-
259
282
// sensitive check here. But we can at least rule out functions that are not const
260
283
// at all.
261
284
if !ecx. tcx . is_const_fn_raw ( def. did ) {
262
285
// allow calling functions marked with #[default_method_body_is_const].
263
286
if !ecx. tcx . has_attr ( def. did , sym:: default_method_body_is_const) {
264
- // Some functions we support even if they are non-const -- but avoid testing
265
- // that for const fn!
266
- if let Some ( new_instance) = ecx. hook_panic_fn ( instance, args) ? {
267
- // We call another const fn instead.
268
- return Self :: find_mir_or_eval_fn (
269
- ecx,
270
- new_instance,
271
- _abi,
272
- args,
273
- _ret,
274
- _unwind,
275
- ) ;
276
- } else {
277
- // We certainly do *not* want to actually call the fn
278
- // though, so be sure we return here.
279
- throw_unsup_format ! ( "calling non-const function `{}`" , instance)
280
- }
287
+ is_const_fn = false ;
281
288
}
282
289
}
290
+
291
+ // Some functions we support even if they are non-const -- but avoid testing
292
+ // that for const fn!
293
+ // `const_eval_select` is a const fn because it must use const trait bounds.
294
+ if let Some ( new_instance) = ecx. hook_special_const_fn ( instance, args, is_const_fn) ? {
295
+ // We call another const fn instead.
296
+ return Self :: find_mir_or_eval_fn ( ecx, new_instance, _abi, args, _ret, _unwind) ;
297
+ }
298
+
299
+ if !is_const_fn {
300
+ // We certainly do *not* want to actually call the fn
301
+ // though, so be sure we return here.
302
+ throw_unsup_format ! ( "calling non-const function `{}`" , instance)
303
+ }
283
304
}
284
305
// This is a const fn. Call it.
285
306
Ok ( Some ( ecx. load_mir ( instance. def , None ) ?) )
0 commit comments