Rollup merge of #114992 - RalfJung:rustc_do_not_const_check, r=b-naber
const-eval: ensure we never const-execute a function marked rustc_do_not_const_check
This commit is contained in:
commit
bb3cf24d15
@ -427,52 +427,41 @@ fn load_mir(
|
|||||||
|
|
||||||
fn find_mir_or_eval_fn(
|
fn find_mir_or_eval_fn(
|
||||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
instance: ty::Instance<'tcx>,
|
orig_instance: ty::Instance<'tcx>,
|
||||||
_abi: CallAbi,
|
_abi: CallAbi,
|
||||||
args: &[FnArg<'tcx>],
|
args: &[FnArg<'tcx>],
|
||||||
dest: &PlaceTy<'tcx>,
|
dest: &PlaceTy<'tcx>,
|
||||||
ret: Option<mir::BasicBlock>,
|
ret: Option<mir::BasicBlock>,
|
||||||
_unwind: mir::UnwindAction, // unwinding is not supported in consts
|
_unwind: mir::UnwindAction, // unwinding is not supported in consts
|
||||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||||
debug!("find_mir_or_eval_fn: {:?}", instance);
|
debug!("find_mir_or_eval_fn: {:?}", orig_instance);
|
||||||
|
|
||||||
|
// Replace some functions.
|
||||||
|
let Some(instance) = ecx.hook_special_const_fn(orig_instance, args, dest, ret)? else {
|
||||||
|
// Call has already been handled.
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
// Only check non-glue functions
|
// Only check non-glue functions
|
||||||
if let ty::InstanceDef::Item(def) = instance.def {
|
if let ty::InstanceDef::Item(def) = instance.def {
|
||||||
// Execution might have wandered off into other crates, so we cannot do a stability-
|
// Execution might have wandered off into other crates, so we cannot do a stability-
|
||||||
// sensitive check here. But we can at least rule out functions that are not const
|
// sensitive check here. But we can at least rule out functions that are not const at
|
||||||
// at all.
|
// all. That said, we have to allow calling functions inside a trait marked with
|
||||||
if !ecx.tcx.is_const_fn_raw(def) {
|
// #[const_trait]. These *are* const-checked!
|
||||||
// allow calling functions inside a trait marked with #[const_trait].
|
// FIXME: why does `is_const_fn_raw` not classify them as const?
|
||||||
if !ecx.tcx.is_const_default_method(def) {
|
if (!ecx.tcx.is_const_fn_raw(def) && !ecx.tcx.is_const_default_method(def))
|
||||||
// We certainly do *not* want to actually call the fn
|
|| ecx.tcx.has_attr(def, sym::rustc_do_not_const_check)
|
||||||
// though, so be sure we return here.
|
{
|
||||||
throw_unsup_format!("calling non-const function `{}`", instance)
|
// We certainly do *not* want to actually call the fn
|
||||||
}
|
// though, so be sure we return here.
|
||||||
}
|
throw_unsup_format!("calling non-const function `{}`", instance)
|
||||||
|
|
||||||
let Some(new_instance) = ecx.hook_special_const_fn(instance, args, dest, ret)? else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
|
|
||||||
if new_instance != instance {
|
|
||||||
// We call another const fn instead.
|
|
||||||
// However, we return the *original* instance to make backtraces work out
|
|
||||||
// (and we hope this does not confuse the FnAbi checks too much).
|
|
||||||
return Ok(Self::find_mir_or_eval_fn(
|
|
||||||
ecx,
|
|
||||||
new_instance,
|
|
||||||
_abi,
|
|
||||||
args,
|
|
||||||
dest,
|
|
||||||
ret,
|
|
||||||
_unwind,
|
|
||||||
)?
|
|
||||||
.map(|(body, _instance)| (body, instance)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a const fn. Call it.
|
// This is a const fn. Call it.
|
||||||
Ok(Some((ecx.load_mir(instance.def, None)?, instance)))
|
// In case of replacement, we return the *original* instance to make backtraces work out
|
||||||
|
// (and we hope this does not confuse the FnAbi checks too much).
|
||||||
|
Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_intrinsic(
|
fn call_intrinsic(
|
||||||
|
Loading…
Reference in New Issue
Block a user