Skip to main content

luaur_analysis/methods/
apply_mapped_generics_apply_mapped_generics.rs

1use crate::records::apply_mapped_generics::ApplyMappedGenerics;
2use crate::records::builtin_types::BuiltinTypes;
3use crate::records::internal_error_reporter::InternalErrorReporter;
4use crate::records::subtyping_environment::SubtypingEnvironment;
5use crate::records::tarjan::SubstitutionVtable;
6use crate::records::type_arena::TypeArena;
7use crate::type_aliases::type_id::TypeId;
8use crate::type_aliases::type_pack_id::TypePackId;
9
10use core::ffi::c_void;
11
12impl ApplyMappedGenerics {
13    pub fn apply_mapped_generics(
14        &mut self,
15        builtin_types: *mut BuiltinTypes,
16        arena: *mut TypeArena,
17        env: &mut SubtypingEnvironment,
18        ice_reporter: *mut InternalErrorReporter,
19    ) {
20        self.builtin_types = builtin_types;
21        self.arena = arena;
22        self.env = env as *mut _;
23        self.ice_reporter = ice_reporter;
24    }
25}
26
27// ---------------------------------------------------------------------------
28// Substitution virtual-override dispatch for `ApplyMappedGenerics`.
29//
30// C++ `ApplyMappedGenerics` overrides `isDirty` / `clean` / `ignoreChildren`
31// (it does NOT override `ignoreChildrenVisit`, so that defaults to
32// `ignoreChildren`). The inherited `substitute` traversal dispatches into these
33// at runtime. Each thunk casts the type-erased `owner` data pointer back to the
34// concrete `*mut ApplyMappedGenerics` it was installed for and calls the inherent
35// override. `found_dirty` is `Substitution`'s own (non-overridden) method, so its
36// thunk forwards to `self.base.found_dirty_*`.
37// ---------------------------------------------------------------------------
38
39fn amg_is_dirty_ty(owner: *mut c_void, ty: TypeId) -> bool {
40    unsafe { (*(owner as *mut ApplyMappedGenerics)).is_dirty_type_id(ty) }
41}
42
43fn amg_is_dirty_tp(owner: *mut c_void, tp: TypePackId) -> bool {
44    unsafe { (*(owner as *mut ApplyMappedGenerics)).is_dirty_type_pack_id(tp) }
45}
46
47fn amg_clean_ty(owner: *mut c_void, ty: TypeId) -> TypeId {
48    unsafe { (*(owner as *mut ApplyMappedGenerics)).clean_type_id(ty) }
49}
50
51fn amg_clean_tp(owner: *mut c_void, tp: TypePackId) -> TypePackId {
52    unsafe { (*(owner as *mut ApplyMappedGenerics)).clean_type_pack_id(tp) }
53}
54
55fn amg_found_dirty_ty(owner: *mut c_void, ty: TypeId) {
56    unsafe {
57        (*(owner as *mut ApplyMappedGenerics))
58            .base
59            .found_dirty_type_id(ty)
60    }
61}
62
63fn amg_found_dirty_tp(owner: *mut c_void, tp: TypePackId) {
64    unsafe {
65        (*(owner as *mut ApplyMappedGenerics))
66            .base
67            .found_dirty_type_pack_id(tp)
68    }
69}
70
71fn amg_ignore_children_ty(owner: *mut c_void, ty: TypeId) -> bool {
72    unsafe { (*(owner as *mut ApplyMappedGenerics)).ignore_children_type_id(ty) }
73}
74
75fn amg_ignore_children_tp(owner: *mut c_void, tp: TypePackId) -> bool {
76    unsafe { (*(owner as *mut ApplyMappedGenerics)).ignore_children_type_pack_id(tp) }
77}
78
79// AMG does not override ignoreChildrenVisit; the base default forwards to ignoreChildren.
80fn amg_ignore_children_visit_ty(owner: *mut c_void, ty: TypeId) -> bool {
81    unsafe { (*(owner as *mut ApplyMappedGenerics)).ignore_children_type_id(ty) }
82}
83
84fn amg_ignore_children_visit_tp(owner: *mut c_void, tp: TypePackId) -> bool {
85    unsafe { (*(owner as *mut ApplyMappedGenerics)).ignore_children_type_pack_id(tp) }
86}
87
88impl ApplyMappedGenerics {
89    /// Point the embedded `Substitution`'s dispatch table at this object and its
90    /// overrides. Must run with `self` at its final address (i.e. from a method
91    /// called on a settled `&mut self`), so the `owner` pointer stays valid for
92    /// the duration of the `substitute` traversal.
93    fn install_substitution_vtable(&mut self) {
94        let owner = self as *mut ApplyMappedGenerics as *mut c_void;
95        self.base.base.vtable = SubstitutionVtable {
96            owner,
97            is_dirty_ty: Some(amg_is_dirty_ty),
98            is_dirty_tp: Some(amg_is_dirty_tp),
99            clean_ty: Some(amg_clean_ty),
100            clean_tp: Some(amg_clean_tp),
101            found_dirty_ty: Some(amg_found_dirty_ty),
102            found_dirty_tp: Some(amg_found_dirty_tp),
103            ignore_children_ty: Some(amg_ignore_children_ty),
104            ignore_children_tp: Some(amg_ignore_children_tp),
105            ignore_children_visit_ty: Some(amg_ignore_children_visit_ty),
106            ignore_children_visit_tp: Some(amg_ignore_children_visit_tp),
107        };
108    }
109
110    /// Inherited `Substitution::substitute(TypeId)` with override dispatch wired.
111    pub fn substitute_type_id(&mut self, ty: TypeId) -> Option<TypeId> {
112        self.install_substitution_vtable();
113        self.base.substitute_type_id(ty)
114    }
115
116    /// Inherited `Substitution::substitute(TypePackId)` with override dispatch wired.
117    pub fn substitute_type_pack_id(&mut self, tp: TypePackId) -> Option<TypePackId> {
118        self.install_substitution_vtable();
119        self.base.substitute_type_pack_id(tp)
120    }
121}