Change:
Since , memoization of argumentless functions is restricted to intrinsics, because other functions could perform heap allocations and thus memoization would be incorrect. I doubt we have any argumentless intrinsic that is expensive enough that memoization is worth it, so I propose we remove the leftovers of that infrastructure. Cc <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
I want to work on this but i never contributed to rust-lang before so i need some guidance.
Great! So... step 0 is to write as a comment here, this will make sure the issue is assigned to you and noone else tries to tackle it at the same time. The main change is to remove this function: entirely without a replacement. You'll then have to adjust the call site to act as if the function returned . This may allow some small cleanups at the call site; I expect nothing major to happen there. I do not think there will be further test changes due to this, so, should run through without any failures. If it doesn't, still open a PR and let us know of your findings.
claim

Discussion:
/// Uniquely identifies one of the following: /// - A constant /// - A static <del> /// - A const fn where all arguments (if any) are zero-sized types </del> #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, Lift)] pub struct GlobalId<'tcx> {

) -> InterpResult<'tcx, MPlaceTy<'tcx>> { debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env); let tcx = *ecx.tcx; <ins> assert!( cid.promoted.is_some() || matches!( ecx.tcx.def_kind(cid.instance.def_id()), DefKind::Const | DefKind::Static | DefKind::ConstParam | DefKind::AnonConst | DefKind::AssocConst ), "Unexpected DefKind: {:?}", ecx.tcx.def_kind(cid.instance.def_id()) ); </ins> let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?; assert!(!layout.is_unsized()); let ret = ecx.allocate(layout, MemoryKind::Stack);

let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom); <del> // Assert all args (if any) are zero-sized types; `eval_body_using_ecx` doesn't // make sense if the body is expecting nontrivial arguments. // (The alternative would be to use `eval_fn_call` with an args slice.) for arg in body.args_iter() { let decl = body.local_decls.get(arg).expect("arg missing from local_decls"); let layout = ecx.layout_of(decl.ty.subst(tcx, cid.instance.substs))?; assert!(layout.is_zst()) } </del> ecx.push_stack_frame( cid.instance, body,

use rustc_middle::mir; <del> use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::InstanceDef; </del> use rustc_middle::ty::{self, Ty}; use std::borrow::Borrow; use std::collections::hash_map::Entry;

use rustc_target::abi::{Align, Size}; use crate::interpret::{ <del> self, compile_time_machine, AllocId, Allocation, Frame, GlobalId, ImmTy, InterpCx, InterpResult, Memory, OpTy, PlaceTy, Pointer, Scalar, </del> <ins> self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, InterpCx, InterpResult, Memory, OpTy, PlaceTy, Pointer, Scalar, </ins> }; use super::error::*; impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { <del> /// Evaluate a const function where all arguments (if any) are zero-sized types. /// The evaluation is memoized thanks to the query system. /// /// Returns `true` if the call has been evaluated. fn try_eval_const_fn_call( &mut self, instance: ty::Instance<'tcx>, ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>, args: &[OpTy<'tcx>], ) -> InterpResult<'tcx, bool> { trace!("try_eval_const_fn_call: {:?}", instance); // Because `#[track_caller]` adds an implicit non-ZST argument, we also cannot // perform this optimization on items tagged with it. if instance.def.requires_caller_location(self.tcx()) { return Ok(false); } // Only memoize instrinsics. This was added in #79594 while adding the `const_allocate` intrinsic. // We only memoize intrinsics because it would be unsound to memoize functions // which might interact with the heap. // Additionally, const_allocate intrinsic is impure and thus should not be memoized; // it will not be memoized because it has non-ZST args if !matches!(instance.def, InstanceDef::Intrinsic(_)) { return Ok(false); } // For the moment we only do this for functions which take no arguments // (or all arguments are ZSTs) so that we don't memoize too much. if args.iter().any(|a| !a.layout.is_zst()) { return Ok(false); } let dest = match ret { Some((dest, _)) => dest, // Don't memoize diverging function calls. None => return Ok(false), }; let gid = GlobalId { instance, promoted: None }; let place = self.eval_to_allocation(gid)?; self.copy_op(place.into(), dest)?; self.return_to_block(ret.map(|r| r.1))?; trace!("{:?}", self.dump_place(*dest)); Ok(true) } </del> /// "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.

ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], <del> ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>, </del> <ins> _ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>, </ins> _unwind: Option<mir::BasicBlock>, // unwinding is not supported in consts ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> { debug!("find_mir_or_eval_fn: {:?}", instance);

// 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. <del> if ecx.tcx.is_const_fn_raw(def.did) { // If this function is a `const fn` then under certain circumstances we // can evaluate call via the query system, thus memoizing all future calls. if ecx.try_eval_const_fn_call(instance, ret, args)? { return Ok(None); } } else { </del> <ins> if !ecx.tcx.is_const_fn_raw(def.did) { </ins> // Some functions we support even if they are non-const -- but avoid testing // that for const fn! ecx.hook_panic_fn(instance, args)?;