diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index ae20f6f97b212..930b2f18b207b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -23,10 +23,9 @@ use crate::interpret::{ use super::error::*; 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. + /// "Intercept" a function call to functions that require special handling. /// If this returns successfully (`Ok`), the function should just be evaluated normally. - fn hook_panic_fn( + fn hook_fn( &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], @@ -67,6 +66,19 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { .unwrap(), )); } + } else if Some(def_id) == self.tcx.lang_items().call_if_rt() { + if let Some(const_call_if_rt) = self.tcx.lang_items().const_call_if_rt() { + return Ok(Some( + ty::Instance::resolve( + *self.tcx, + ty::ParamEnv::reveal_all(), + const_call_if_rt, + instance.substs, + ) + .unwrap() + .unwrap(), + )); + } } Ok(None) } @@ -263,7 +275,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 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)? { + if let Some(new_instance) = ecx.hook_fn(instance, args)? { // We call another const fn instead. return Self::find_mir_or_eval_fn( ecx, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 57d92005a5649..0d2a03468d047 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -913,6 +913,10 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { return; } + if Some(callee) == tcx.lang_items().call_if_rt() { + return; + } + if Some(callee) == tcx.lang_items().exchange_malloc_fn() { self.check_op(ops::HeapAllocation); return; diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index d69a247054026..7f2f4ec48142d 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -294,6 +294,9 @@ language_item_table! { BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None; BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn, GenericRequirement::None; + CallIfRt, sym::call_if_rt, call_if_rt, Target::Fn, GenericRequirement::None; + ConstCallIfRt, sym::const_call_if_rt, const_call_if_rt, Target::Fn, GenericRequirement::None; + ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None; BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1); DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7cb4e18398cdc..d1214978dd151 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -378,6 +378,7 @@ symbols! { c_unwind, c_variadic, call, + call_if_rt, call_mut, call_once, caller_location, @@ -429,6 +430,7 @@ symbols! { console, const_allocate, const_async_blocks, + const_call_if_rt, const_compare_raw_pointers, const_constructor, const_eval_limit, diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 3e26d46ddcaf9..8ac898fced97e 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2221,3 +2221,18 @@ pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. unsafe { write_bytes(dst, val, count) } } + +#[cfg(not(bootstrap))] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[lang = "call_if_rt"] +#[inline(always)] +pub fn call_if_rt R + Copy>(f: F) -> Option { + Some(f()) +} + +#[cfg(not(bootstrap))] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[lang = "const_call_if_rt"] +pub const fn const_call_if_rt R + Copy>(_f: F) -> Option { + None +}