//! This module specifies the type based interner for constants.
//!
//! After a const evaluation has computed a value, before we destroy the const evaluator's session
//! memory, we need to extract all memory allocations to the global memory pool so they stay around.
//!
//! In principle, this is not very complicated: we recursively walk the final value, follow all the
//! pointers, and move all reachable allocations to the global `tcx` memory. The only complication
//! is picking the right mutability: the outermost allocation generally has a clear mutability, but
//! what about the other allocations it points to that have also been created with this value? We
//! don't want to do guesswork here. The rules are: `static`, `const`, and promoted can only create
//! immutable allocations that way. `static mut` can be initialized with expressions like `&mut 42`,
//! so all inner allocations are marked mutable. Some of them could potentially be made immutable,
//! but that would require relying on type information, and given how many ways Rust has to lie
//! about type information, we want to avoid doing that.

use hir::def::DefKind;
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorState};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::interpret::{
    AllocBytes, ConstAllocation, CtfeProvenance, InterpResult, Provenance,
};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::span_bug;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_span::def_id::LocalDefId;
use tracing::{instrument, trace};

use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy, interp_ok};
use crate::const_eval::DummyMachine;
use crate::{const_eval, diagnostics};

pub trait CompileTimeMachine<'tcx> = Machine<
        'tcx,
        MemoryKind = const_eval::MemoryKind,
        Provenance = CtfeProvenance,
        ExtraFnVal = !,
        FrameExtra = (),
        AllocExtra = (),
        MemoryMap = FxIndexMap<AllocId, (MemoryKind<const_eval::MemoryKind>, Allocation)>,
    > + HasStaticRootDefId;

pub trait HasStaticRootDefId {
    /// Returns the `DefId` of the static item that is currently being evaluated.
    /// Used for interning to be able to handle nested allocations.
    fn static_def_id(&self) -> Option<LocalDefId>;
}

impl HasStaticRootDefId for const_eval::CompileTimeMachine<'_> {
    fn static_def_id(&self) -> Option<LocalDefId> {
        Some(self.static_root_ids?.1)
    }
}

fn prepare_alloc<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
    tcx: TyCtxt<'tcx>,
    kind: MemoryKind<const_eval::MemoryKind>,
    alloc: &mut Allocation<Prov, Extra, Bytes>,
    mutability: Mutability,
) -> Result<(), InternError> {
    match kind {
        MemoryKind::Machine(const_eval::MemoryKind::Heap { was_made_global }) => {
            if !was_made_global {
                // Attempting to intern a `const_allocate`d pointer that was not made global via
                // `const_make_global`.
                tcx.dcx().delayed_bug("non-global heap allocation in const value");
                return Err(InternError::ConstAllocNotGlobal);
            }
        }
        MemoryKind::Stack | MemoryKind::CallerLocation => {}
    }

    if !alloc.provenance_merge_bytes(&tcx) {
        // Per-byte provenance is not supported by backends, so we cannot accept it here.
        tcx.dcx().delayed_bug("partial pointer in const value");
        return Err(InternError::PartialPointer);
    }

    // Set allocation mutability as appropriate. This is used by LLVM to put things into
    // read-only memory, and also by Miri when evaluating other globals that
    // access this one.
    match mutability {
        Mutability::Not => {
            alloc.mutability = Mutability::Not;
        }
        Mutability::Mut => {
            // This must be already mutable, we won't "un-freeze" allocations ever.
            assert_eq!(alloc.mutability, Mutability::Mut);
        }
    }
    Ok(())
}

/// Intern an allocation. Returns `Err` if the allocation does not exist in the local memory.
///
/// `mutability` can be used to force immutable interning: if it is `Mutability::Not`, the
/// allocation is interned immutably; if it is `Mutability::Mut`, then the allocation *must be*
/// already mutable (as a sanity check).
///
/// Returns an iterator over all relocations referred to by this allocation.
fn intern_shallow<'tcx, M: CompileTimeMachine<'tcx>>(
    ecx: &mut InterpCx<'tcx, M>,
    alloc_id: AllocId,
    mutability: Mutability,
    disambiguator: Option<&mut PerParentDisambiguatorState>,
) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, InternError> {
    trace!("intern_shallow {:?}", alloc_id);
    // remove allocation
    // FIXME(#120456) - is `swap_remove` correct?
    let Some((kind, mut alloc)) = ecx.memory.alloc_map.swap_remove(&alloc_id) else {
        return Err(InternError::DanglingPointer);
    };

    if let Err(err) = prepare_alloc(*ecx.tcx, kind, &mut alloc, mutability) {
        // We want to error here, but we have to first put the
        // allocation back into the `alloc_map` to keep things in a consistent state.
        ecx.memory.alloc_map.insert(alloc_id, (kind, alloc));
        return Err(err);
    }

    // link the alloc id to the actual allocation
    let alloc = ecx.tcx.mk_const_alloc(alloc);
    if let Some(static_id) = ecx.machine.static_def_id() {
        intern_as_new_static(
            ecx.tcx,
            static_id,
            alloc_id,
            alloc,
            disambiguator.expect("disambiguator needed"),
        );
    } else {
        ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
    }
    Ok(alloc.inner().provenance().ptrs().iter().map(|&(_, prov)| prov))
}

/// Creates a new `DefId` and feeds all the right queries to make this `DefId`
/// appear as if it were a user-written `static` (though it has no HIR).
fn intern_as_new_static<'tcx>(
    tcx: TyCtxtAt<'tcx>,
    static_id: LocalDefId,
    alloc_id: AllocId,
    alloc: ConstAllocation<'tcx>,
    disambiguator: &mut PerParentDisambiguatorState,
) {
    // `intern_const_alloc_recursive` is called once per static and it contains the `PerParentDisambiguatorState`.
    //  The `<static_id>::{{nested}}` path is thus unique to `intern_const_alloc_recursive` and the
    // `PerParentDisambiguatorState` ensures the generated path is unique for this call as we generate
    // `<static_id>::{{nested#n}}` where `n` is the `n`th `intern_as_new_static` call.
    let feed = tcx.create_def(
        static_id,
        None,
        DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
        Some(DefPathData::NestedStatic),
        disambiguator,
    );
    tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());

    if tcx.is_thread_local_static(static_id.into()) {
        tcx.dcx()
            .emit_err(diagnostics::NestedStaticInThreadLocal { span: tcx.def_span(static_id) });
    }

    // These do not inherit the codegen attrs of the parent static allocation, since
    // it doesn't make sense for them to inherit their `#[no_mangle]` and `#[link_name = ..]`
    // and the like.
    feed.codegen_fn_attrs(CodegenFnAttrs::new());

    feed.eval_static_initializer(Ok(alloc));
    feed.generics_of(tcx.generics_of(static_id).clone());
    feed.def_ident_span(tcx.def_ident_span(static_id));
    feed.explicit_clauses_of(tcx.explicit_clauses_of(static_id));
    feed.feed_hir();
}

/// How a constant value should be interned.
#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
pub enum InternKind {
    /// The `mutability` of the static, ignoring the type which may have interior mutability.
    Static(hir::Mutability),
    /// A `const` item
    Constant,
    Promoted,
}

#[derive(Debug)]
pub enum InternError {
    BadMutablePointer,
    DanglingPointer,
    ConstAllocNotGlobal,
    PartialPointer,
}

/// Intern `ret` and everything it references.
///
/// This *cannot raise an interpreter error*. Doing so is left to validation, which
/// tracks where in the value we are and thus can show much better error messages.
///
/// For `InternKind::Static` the root allocation will not be interned, but must be handled by the caller.
#[instrument(level = "debug", skip(ecx))]
pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx>>(
    ecx: &mut InterpCx<'tcx, M>,
    intern_kind: InternKind,
    ret: &MPlaceTy<'tcx>,
) -> Result<(), InternError> {
    let mut disambiguator =
        ecx.machine.static_def_id().map(|id| PerParentDisambiguatorState::new(id));
    let mut disambiguator = disambiguator.as_mut();

    // We are interning recursively, and for mutability we are distinguishing the "root" allocation
    // that we are starting in, and all other allocations that we are encountering recursively.
    let (base_mutability, inner_mutability, is_static) = match intern_kind {
        InternKind::Constant | InternKind::Promoted => {
            // Completely immutable. Interning anything mutably here can only lead to unsoundness,
            // since all consts are conceptually independent values but share the same underlying
            // memory.
            (Mutability::Not, Mutability::Not, false)
        }
        InternKind::Static(Mutability::Not) => {
            (
                // Outermost allocation is mutable if `!Freeze` i.e. contains interior mutable types.
                if ret.layout.ty.is_freeze(*ecx.tcx, ecx.typing_env) {
                    Mutability::Not
                } else {
                    Mutability::Mut
                },
                // Inner allocations are never mutable. They can only arise via the "tail
                // expression" / "outer scope" rule, and we treat them consistently with `const`.
                Mutability::Not,
                true,
            )
        }
        InternKind::Static(Mutability::Mut) => {
            // Just make everything mutable. We accept code like
            // `static mut X = &mut [42]`, so even inner allocations need to be mutable.
            (Mutability::Mut, Mutability::Mut, true)
        }
    };

    // Intern the base allocation, and initialize todo list for recursive interning.
    let base_alloc_id = ret.ptr().provenance.unwrap().alloc_id();
    trace!(?base_alloc_id, ?base_mutability);
    // First we intern the base allocation, as it requires a different mutability.
    // This gives us the initial set of nested allocations, which will then all be processed
    // recursively in the loop below.
    let mut todo: Vec<_> = if is_static {
        assert!(disambiguator.is_some());
        // Do not steal the root allocation, we need it later to create the return value of `eval_static_initializer`.
        // But still change its mutability to match the requested one.
        let (kind, alloc) = ecx.memory.alloc_map.get_mut(&base_alloc_id).unwrap();
        prepare_alloc(*ecx.tcx, *kind, alloc, base_mutability)?;
        alloc.provenance().ptrs().iter().map(|&(_, prov)| prov).collect()
    } else {
        assert!(disambiguator.is_none());
        intern_shallow(ecx, base_alloc_id, base_mutability, None)?.collect()
    };
    // We need to distinguish "has just been interned" from "was already in `tcx`",
    // so we track this in a separate set.
    let mut just_interned: FxHashSet<_> = std::iter::once(base_alloc_id).collect();
    // Whether we encountered a bad mutable pointer.
    // We want to first report "dangling" and then "mutable", so we need to delay reporting these
    // errors.
    let mut found_bad_mutable_ptr = false;

    // Keep interning as long as there are things to intern.
    // We show errors if there are dangling pointers, or mutable pointers in immutable contexts
    // (i.e., everything except for `static mut`). We only return these errors as a `Result`
    // so that the caller can run validation, and subsequently only report interning errors
    // if validation fails. Validation has the better error messages so we prefer those, but
    // interning has better coverage since it "sees" *all* pointers, including raw pointers and
    // references stored in unions.
    while let Some(prov) = todo.pop() {
        trace!(?prov);
        let alloc_id = prov.alloc_id();

        if base_alloc_id == alloc_id && is_static {
            // This is a pointer to the static itself. It's ok for a static to refer to itself,
            // even mutably. Whether that mutable pointer is legal at all is checked in validation.
            // See tests/ui/statics/recursive_interior_mut.rs for how such a situation can occur.
            // We also already collected all the nested allocations, so there's no need to do that again.
            continue;
        }

        // Ensure that this is derived from a shared reference. Crucially, we check this *before*
        // checking whether the `alloc_id` has already been interned. The point of this check is to
        // ensure that when there are multiple pointers to the same allocation, they are *all*
        // derived from a shared reference. Therefore it would be bad if we only checked the first
        // pointer to any given allocation.
        // (It is likely not possible to actually have multiple pointers to the same allocation,
        // so alternatively we could also check that and ICE if there are multiple such pointers.)
        // See <https://github.com/rust-lang/rust/pull/128543> for why we are checking for "shared
        // reference" and not "immutable", i.e., for why we are allowing interior-mutable shared
        // references: they can actually be created in safe code while pointing to apparently
        // "immutable" values, via promotion or tail expression lifetime extension of
        // `&None::<Cell<T>>`.
        // We also exclude promoteds from this as `&mut []` can be promoted, which is a mutable
        // reference pointing to an immutable (zero-sized) allocation. We rely on the promotion
        // analysis not screwing up to ensure that it is sound to intern promoteds as immutable.
        if intern_kind != InternKind::Promoted
            && inner_mutability == Mutability::Not
            && !prov.shared_ref()
        {
            let is_already_global = ecx.tcx.try_get_global_alloc(alloc_id).is_some();
            if is_already_global && !just_interned.contains(&alloc_id) {
                // This is a pointer to some memory from another constant. We encounter mutable
                // pointers to such memory since we do not always track immutability through
                // these "global" pointers. Allowing them is harmless; the point of these checks
                // during interning is to justify why we intern the *new* allocations immutably,
                // so we can completely ignore existing allocations.
                // We can also skip the rest of this loop iteration, since after all it is already
                // interned.
                continue;
            }
            // If this is a dangling pointer, that's actually fine -- the problematic case is
            // when there is memory there that someone might expect to be mutable, but we make it immutable.
            let dangling = !is_already_global && !ecx.memory.alloc_map.contains_key(&alloc_id);
            if !dangling {
                found_bad_mutable_ptr = true;
            }
        }
        if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
            // Already interned.
            debug_assert!(!ecx.memory.alloc_map.contains_key(&alloc_id));
            continue;
        }
        // We always intern with `inner_mutability`, and furthermore we ensured above that if
        // that is "immutable", then there are *no* mutable pointers anywhere in the newly
        // interned memory -- justifying that we can indeed intern immutably. However this also
        // means we can *not* easily intern immutably here if `prov.immutable()` is true and
        // `inner_mutability` is `Mut`: there might be other pointers to that allocation, and
        // we'd have to somehow check that they are *all* immutable before deciding that this
        // allocation can be made immutable. In the future we could consider analyzing all
        // pointers before deciding which allocations can be made immutable; but for now we are
        // okay with losing some potential for immutability here. This can anyway only affect
        // `static mut`.
        just_interned.insert(alloc_id);
        let next = intern_shallow(ecx, alloc_id, inner_mutability, disambiguator.as_deref_mut())?;
        todo.extend(next);
    }
    if found_bad_mutable_ptr {
        // We found a mutable pointer inside a const where inner allocations should be immutable,
        // and there was no other error. This should usually never happen! However, this can happen
        // in unleash-miri mode, so report it as a normal error then.
        if ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you {
            return Err(InternError::BadMutablePointer);
        } else {
            span_bug!(
                ecx.tcx.span,
                "the static const safety checks accepted a mutable pointer they should not have accepted"
            );
        }
    }
    Ok(())
}

/// Intern `ret`. This function assumes that `ret` references no other allocation.
#[instrument(level = "debug", skip(ecx))]
pub fn intern_const_alloc_for_constprop<'tcx, M: CompileTimeMachine<'tcx>>(
    ecx: &mut InterpCx<'tcx, M>,
    alloc_id: AllocId,
) -> InterpResult<'tcx, ()> {
    if ecx.tcx.try_get_global_alloc(alloc_id).is_some() {
        // The constant is already in global memory. Do nothing.
        return interp_ok(());
    }
    // Move allocation to `tcx`.
    if let Some(_) = intern_shallow(ecx, alloc_id, Mutability::Not, None).unwrap().next() {
        // We are not doing recursive interning, so we don't currently support provenance.
        // (If this assertion ever triggers, we should just implement a
        // proper recursive interning loop -- or just call `intern_const_alloc_recursive`.
        panic!("`intern_const_alloc_for_constprop` called on allocation with nested provenance")
    }
    interp_ok(())
}

impl<'tcx> InterpCx<'tcx, DummyMachine> {
    /// A helper function that allocates memory for the layout given and gives you access to mutate
    /// it. Once your own mutation code is done, the backing `Allocation` is removed from the
    /// current `Memory` and interned as read-only into the global memory.
    pub fn intern_with_temp_alloc(
        &mut self,
        layout: TyAndLayout<'tcx>,
        f: impl FnOnce(
            &mut InterpCx<'tcx, DummyMachine>,
            &PlaceTy<'tcx, CtfeProvenance>,
        ) -> InterpResult<'tcx, ()>,
    ) -> InterpResult<'tcx, AllocId> {
        // `allocate` picks a fresh AllocId that we will associate with its data below.
        let dest = self.allocate(layout, MemoryKind::Stack)?;
        f(self, &dest.clone().into())?;
        let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance
        for prov in intern_shallow(self, alloc_id, Mutability::Not, None).unwrap() {
            // We are not doing recursive interning, so we don't currently support provenance.
            // (If this assertion ever triggers, we should just implement a
            // proper recursive interning loop -- or just call `intern_const_alloc_recursive`.
            if self.tcx.try_get_global_alloc(prov.alloc_id()).is_none() {
                panic!("`intern_with_temp_alloc` with nested allocations");
            }
        }
        interp_ok(alloc_id)
    }
}
