<commit_before>use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr, MemoryExtra};
use crate::interpret::eval_nullary_intrinsic;
use crate::interpret::{
    intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, Immediate, InternKind,
    InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar,
    ScalarMaybeUninit, StackPopCleanup,
};

use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::traits::Reveal;
use rustc_middle::ty::{self, subst::Subst, TyCtxt};
use rustc_span::source_map::Span;
use rustc_target::abi::{Abi, LayoutOf};
use std::convert::TryInto;

pub fn note_on_undefined_behavior_error() -> &'static str {
    "The rules on what exactly is undefined behavior aren't clear, \
     so this check might be overzealous. Please open an issue on the rustc \
     repository if you believe it should not be considered undefined behavior."
}

// Returns a pointer to where the result lives
fn eval_body_using_ecx<'mir, 'tcx>(
    ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
    cid: GlobalId<'tcx>,
    body: &'mir mir::Body<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
    debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
    let tcx = *ecx.tcx;
    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 name = ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()));
    let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
    trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);

    // 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())
    }

    ecx.push_stack_frame(
        cid.instance,
        body,
        Some(ret.into()),
        StackPopCleanup::None { cleanup: false },
    )?;

    // The main interpreter loop.
    ecx.run()?;

    // Intern the result
    let intern_kind = match tcx.static_mutability(cid.instance.def_id()) {
        Some(m) => InternKind::Static(m),
        None if cid.promoted.is_some() => InternKind::Promoted,
        _ => InternKind::Constant,
    };
    intern_const_alloc_recursive(<commit_msg>add a FIXME concerning interning of promoteds<commit_after>use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr, MemoryExtra};
use crate::interpret::eval_nullary_intrinsic;
use crate::interpret::{
    intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, Immediate, InternKind,
    InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar,
    ScalarMaybeUninit, StackPopCleanup,
};

use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::traits::Reveal;
use rustc_middle::ty::{self, subst::Subst, TyCtxt};
use rustc_span::source_map::Span;
use rustc_target::abi::{Abi, LayoutOf};
use std::convert::TryInto;

pub fn note_on_undefined_behavior_error() -> &'static str {
    "The rules on what exactly is undefined behavior aren't clear, \
     so this check might be overzealous. Please open an issue on the rustc \
     repository if you believe it should not be considered undefined behavior."
}

// Returns a pointer to where the result lives
fn eval_body_using_ecx<'mir, 'tcx>(
    ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
    cid: GlobalId<'tcx>,
    body: &'mir mir::Body<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
    debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
    let tcx = *ecx.tcx;
    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 name = ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()));
    let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
    trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);

    // 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())
    }

    ecx.push_stack_frame(
        cid.instance,
        body,
        Some(ret.into()),
        StackPopCleanup::None { cleanup: false },
    )?;

    // The main interpreter loop.
    ecx.run()?;

    // Intern the result
    // FIXME: since the DefId of a promoted is the DefId of its owner, this
    // means that promoteds in statics are actually interned like statics!
    // However, this is also currently crucial because we promote mutable
    // non-empty slices in statics to extend their lifetime, and this
    // ensures that they are put into a mutable allocation.
    // For other kinds of promoteds in statics (like array initializers), this is rather silly.
    let intern_kind = match tcx.static_mutability(cid.instance.def_id()) {
        Some(m) => InternKind::Static(m),
        None if cid.promoted.is_some() => InternKind::Promoted,
        _ => InternKind::Constant,
    };
    intern_const_alloc_recursive(
{'fraction_non_alphanumeric': 0.13295591010464916, 'fraction_numerical': 0.0, 'mean_word_length': 4.109553023663453, 'pattern_counts': {'":': 2, '<': 15, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4928982', 'n_tokens_mistral': 1902, 'n_tokens_neox': 1915, 'n_words': 492}