Skip to main content

luaur_analysis/functions/
clone_clone_alt_b.rs

1use crate::records::clone_state::CloneState;
2use crate::records::type_arena::TypeArena;
3use crate::records::type_cloner::TypeCloner;
4use crate::type_aliases::seen_type_packs_clone::SeenTypePacks as DenseSeenTypePacks;
5use crate::type_aliases::seen_types_clone::SeenTypes as DenseSeenTypes;
6use crate::type_aliases::type_id::TypeId;
7use crate::type_aliases::type_pack_id::TypePackId;
8use std::collections::HashMap;
9
10/// Bridge between `CloneState`'s `DenseHashMap`-backed seen-maps and the
11/// `TypeCloner`'s `std::HashMap`-backed `SeenTypes`/`SeenTypePacks`. The C++ uses
12/// a single `SeenTypes`/`SeenTypePacks` alias for both, so a faithful port has
13/// the cloner read from and write back into the `CloneState`'s caches. This
14/// seeds a local `HashMap` from the `DenseHashMap`, runs `body`, then writes any
15/// newly-discovered entries back so cross-call deduplication is preserved.
16pub(crate) fn with_clone_maps<R>(
17    seen_types: &mut DenseSeenTypes,
18    seen_type_packs: &mut DenseSeenTypePacks,
19    body: impl FnOnce(&mut HashMap<TypeId, TypeId>, &mut HashMap<TypePackId, TypePackId>) -> R,
20) -> R {
21    let mut tys: HashMap<TypeId, TypeId> = seen_types.iter().map(|(k, v)| (*k, *v)).collect();
22    let mut tps: HashMap<TypePackId, TypePackId> =
23        seen_type_packs.iter().map(|(k, v)| (*k, *v)).collect();
24
25    let result = body(&mut tys, &mut tps);
26
27    for (k, v) in tys.iter() {
28        *seen_types.get_or_insert(*k) = *v;
29    }
30    for (k, v) in tps.iter() {
31        *seen_type_packs.get_or_insert(*k) = *v;
32    }
33
34    result
35}
36
37pub fn clone(type_id: TypeId, dest: &mut TypeArena, clone_state: &mut CloneState) -> TypeId {
38    if unsafe { (*type_id).persistent } {
39        return type_id;
40    }
41
42    let builtin_types = clone_state.builtin_types;
43    with_clone_maps(
44        &mut clone_state.seen_types,
45        &mut clone_state.seen_type_packs,
46        |tys, tps| {
47            let mut cloner = TypeCloner {
48                arena: dest as *mut TypeArena,
49                builtin_types,
50                queue: alloc::vec::Vec::new(),
51                types: tys as *mut HashMap<TypeId, TypeId>,
52                packs: tps as *mut HashMap<TypePackId, TypePackId>,
53                force_ty: core::ptr::null(),
54                force_tp: core::ptr::null(),
55                steps: 0,
56                replacement_for_null_scope: core::ptr::null_mut(),
57                skip_lazy_type_clone: false,
58            };
59            cloner.clone_type_id(type_id)
60        },
61    )
62}