Clean up special function const checks

Mark them as const and `#[rustc_do_not_const_check]` instead of hard-coding
them in const-eval checks.
This commit is contained in:
Gary Guo
2021-10-25 17:07:16 +01:00
parent 235d9853d8
commit cc4345a1c5
8 changed files with 53 additions and 87 deletions

View File

@@ -30,34 +30,25 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
&mut self,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
is_const_fn: bool,
) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
// The list of functions we handle here must be in sync with
// `is_lang_special_const_fn` in `transform/check_consts/mod.rs`.
// All `#[rustc_do_not_const_check]` functions should be hooked here.
let def_id = instance.def_id();
if is_const_fn {
if Some(def_id) == self.tcx.lang_items().const_eval_select() {
// redirect to const_eval_select_ct
if let Some(const_eval_select) = self.tcx.lang_items().const_eval_select_ct() {
return Ok(Some(
ty::Instance::resolve(
*self.tcx,
ty::ParamEnv::reveal_all(),
const_eval_select,
instance.substs,
)
.unwrap()
.unwrap(),
));
}
if Some(def_id) == self.tcx.lang_items().const_eval_select() {
// redirect to const_eval_select_ct
if let Some(const_eval_select) = self.tcx.lang_items().const_eval_select_ct() {
return Ok(Some(
ty::Instance::resolve(
*self.tcx,
ty::ParamEnv::reveal_all(),
const_eval_select,
instance.substs,
)
.unwrap()
.unwrap(),
));
}
return Ok(None);
}
if Some(def_id) == self.tcx.lang_items().panic_fn()
|| Some(def_id) == self.tcx.lang_items().panic_str()
|| Some(def_id) == self.tcx.lang_items().panic_display()
} else if Some(def_id) == self.tcx.lang_items().panic_display()
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
{
// &str or &&str
@@ -286,19 +277,16 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
}
// Some functions we support even if they are non-const -- but avoid testing
// that for const fn!
// `const_eval_select` is a const fn because it must use const trait bounds.
if let Some(new_instance) = ecx.hook_special_const_fn(instance, args, is_const_fn)? {
// We call another const fn instead.
return Self::find_mir_or_eval_fn(ecx, new_instance, _abi, args, _ret, _unwind);
}
if !is_const_fn {
// 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)
}
if let Some(new_instance) = ecx.hook_special_const_fn(instance, args)? {
// We call another const fn instead.
return Self::find_mir_or_eval_fn(ecx, new_instance, _abi, args, _ret, _unwind);
}
}
// This is a const fn. Call it.
Ok(Some(ecx.load_mir(instance.def, None)?))