Change:
local: mir::Local, layout: Option<TyLayout<'tcx>>, ) -> InterpResult<'tcx, TyLayout<'tcx>> { <del> match frame.locals[local].layout.get() { </del> <ins> // `const_prop` runs into this with an invalid (empty) frame, so we // have to support that case (mostly by skipping all caching). match frame.locals.get(local).and_then(|state| state.layout.get()) { </ins> None => { let layout = crate::interpret::operand::from_known_layout(layout, || { let local_ty = frame.body.local_decls[local].ty; let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs)?; self.layout_of(local_ty) })?; <del> // Layouts of locals are requested a lot, so we cache them. frame.locals[local].layout.set(Some(layout)); </del> <ins> if let Some(state) = frame.locals.get(local) { // Layouts of locals are requested a lot, so we cache them. state.layout.set(Some(layout)); } </ins> Ok(layout) } Some(layout) => Ok(layout),

Discussion:
Since we have a strange condition in the Miri/interpreter code that checks if a function got called with appropriate arguments: got replaced by . That's really strange, the layout should contain all the information we need for execution, and module boundaries certainly shouldn't matter for the call ABI. So I don't think this change is right, at least not for Miri. Unfortunately, there is 0 explanation of the "why" in that PR and in the code. It also does fix an ICE. Is this a case of running the interpreter on untyped code? Or why does looking at the layout not work? Cc
This is entirely my fault and also entirely unnecessary for fixing the ICE. I just believed this to be a useful cleanup: The reason is that computing the layout in a cached way (via ) requires that we actually have an IndexVec of locals, which we don't have for const prop. The previous code was so if you prefer that, I'm fine with moving there, I just thought it to be better to fix the problem at the layout checking place instead of at the layout computation place.
I'm afraid I disagree with that being a cleanup -- AFAIK the type-based tests exist for surface language stuff, like exhaustiveness check and whatnot, also taking into account semver considerations. But for the interpreter I'd like to be sure that we use the layout information that will also be used by codegen. constprop making a mess for everyone else, again. :( That other code seems okay to me, the comment is confusing though. What does that have to do with "constants being trivial"? And "don't allocate any locals" sounds like we wouldn't make them , which is not at all what this is about. But if that explains that might be empty when we are in constprop, I'd r+ that.
actually, has just made some changes there or is in the process of further changes. We may be able to revert after those changes are through because we'll have an actual stack frame available
That would be great! I thought there were some performance reasons for this.
There were strong performance reasons in the past. We alleviated most of them, but there are some left: not even 2% regression in artificial const eval benchmarks are fine with me for the enormous reduction in code complexity and duplication.

We may be able to find further improvements that help const prop and const eval now that they have started sharing more code.
Besides this issue here, do we carry existing hacks that we can remove with the more well-behaved const_prop?
I think there are some hacks about fallback behaviour on empty stacks