diff options
| author | Deadbeef <ent3rm4n@gmail.com> | 2021-10-12 05:06:37 +0000 |
|---|---|---|
| committer | Deadbeef <ent3rm4n@gmail.com> | 2021-10-12 05:42:23 +0000 |
| commit | 5387b6542f1d72d332c84e8325309f0c9de7b6a0 (patch) | |
| tree | 1f01043fc08bd969b58879b64b73f11f08f26624 /compiler/rustc_const_eval/src/const_eval | |
| parent | 0c87288f92b7e6365d61cfbcbc453ea4c696c030 (diff) | |
Add const_eval_select intrinsic
Diffstat (limited to 'compiler/rustc_const_eval/src/const_eval')
| -rw-r--r-- | compiler/rustc_const_eval/src/const_eval/machine.rs | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index ae20f6f97b2..202c9cad8eb 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -26,14 +26,35 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { /// "Intercept" a function call to a panic-related function /// because we have something special to do for it. /// If this returns successfully (`Ok`), the function should just be evaluated normally. - fn hook_panic_fn( + fn hook_special_const_fn( &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_panic_fn` in `transform/check_consts/mod.rs`. + // `is_lang_special_const_fn` in `transform/check_consts/mod.rs`. 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(), + )); + } + } + 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() @@ -255,31 +276,31 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, // Only check non-glue functions if let ty::InstanceDef::Item(def) = instance.def { + let mut is_const_fn = true; + // 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 // at all. if !ecx.tcx.is_const_fn_raw(def.did) { // allow calling functions marked with #[default_method_body_is_const]. if !ecx.tcx.has_attr(def.did, sym::default_method_body_is_const) { - // Some functions we support even if they are non-const -- but avoid testing - // that for const fn! - if let Some(new_instance) = ecx.hook_panic_fn(instance, args)? { - // We call another const fn instead. - return Self::find_mir_or_eval_fn( - ecx, - new_instance, - _abi, - args, - _ret, - _unwind, - ); - } else { - // 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) - } + is_const_fn = false; } } + + // 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) + } } // This is a const fn. Call it. Ok(Some(ecx.load_mir(instance.def, None)?)) |
