Skip to content

Commit 410bd45

Browse files
committed
const-eval: ensure we never const-execute a function marked rustc_do_not_const_check
1 parent d06ca0f commit 410bd45

File tree

1 file changed

+21
-32
lines changed
  • compiler/rustc_const_eval/src/const_eval

1 file changed

+21
-32
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

+21-32
Original file line numberDiff line numberDiff line change
@@ -427,52 +427,41 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
427427

428428
fn find_mir_or_eval_fn(
429429
ecx: &mut InterpCx<'mir, 'tcx, Self>,
430-
instance: ty::Instance<'tcx>,
430+
orig_instance: ty::Instance<'tcx>,
431431
_abi: CallAbi,
432432
args: &[FnArg<'tcx>],
433433
dest: &PlaceTy<'tcx>,
434434
ret: Option<mir::BasicBlock>,
435435
_unwind: mir::UnwindAction, // unwinding is not supported in consts
436436
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
437-
debug!("find_mir_or_eval_fn: {:?}", instance);
437+
debug!("find_mir_or_eval_fn: {:?}", orig_instance);
438+
439+
// Replace some functions.
440+
let Some(instance) = ecx.hook_special_const_fn(orig_instance, args, dest, ret)? else {
441+
// Call has already been handled.
442+
return Ok(None);
443+
};
438444

439445
// Only check non-glue functions
440446
if let ty::InstanceDef::Item(def) = instance.def {
441447
// Execution might have wandered off into other crates, so we cannot do a stability-
442-
// sensitive check here. But we can at least rule out functions that are not const
443-
// at all.
444-
if !ecx.tcx.is_const_fn_raw(def) {
445-
// allow calling functions inside a trait marked with #[const_trait].
446-
if !ecx.tcx.is_const_default_method(def) {
447-
// We certainly do *not* want to actually call the fn
448-
// though, so be sure we return here.
449-
throw_unsup_format!("calling non-const function `{}`", instance)
450-
}
451-
}
452-
453-
let Some(new_instance) = ecx.hook_special_const_fn(instance, args, dest, ret)? else {
454-
return Ok(None);
455-
};
456-
457-
if new_instance != instance {
458-
// We call another const fn instead.
459-
// However, we return the *original* instance to make backtraces work out
460-
// (and we hope this does not confuse the FnAbi checks too much).
461-
return Ok(Self::find_mir_or_eval_fn(
462-
ecx,
463-
new_instance,
464-
_abi,
465-
args,
466-
dest,
467-
ret,
468-
_unwind,
469-
)?
470-
.map(|(body, _instance)| (body, instance)));
448+
// sensitive check here. But we can at least rule out functions that are not const at
449+
// all. That said, we have to allow calling functions inside a trait marked with
450+
// #[const_trait]. These *are* const-checked!
451+
// FIXME: why does `is_const_fn_raw` not classify them as const?
452+
if (!ecx.tcx.is_const_fn_raw(def) && !ecx.tcx.is_const_default_method(def))
453+
|| ecx.tcx.has_attr(def, sym::rustc_do_not_const_check)
454+
{
455+
// We certainly do *not* want to actually call the fn
456+
// though, so be sure we return here.
457+
throw_unsup_format!("calling non-const function `{}`", instance)
471458
}
472459
}
473460

474461
// This is a const fn. Call it.
475-
Ok(Some((ecx.load_mir(instance.def, None)?, instance)))
462+
// In case of replacement, we return the *original* instance to make backtraces work out
463+
// (and we hope this does not confuse the FnAbi checks too much).
464+
Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance)))
476465
}
477466

478467
fn call_intrinsic(

0 commit comments

Comments
 (0)