Skip to main content

luaur_analysis/methods/
clone_public_interface_clone_public_interface.rs

1use crate::enums::solver_mode::SolverMode;
2use crate::records::builtin_types::BuiltinTypes;
3use crate::records::clone_public_interface::ClonePublicInterface;
4use crate::records::module::Module;
5use crate::records::substitution::Substitution;
6use crate::records::tarjan::SubstitutionVtable;
7use crate::records::txn_log::TxnLog;
8use crate::type_aliases::type_id::TypeId;
9use crate::type_aliases::type_pack_id::TypePackId;
10use core::ffi::c_void;
11use luaur_common::macros::luau_assert::LUAU_ASSERT;
12
13fn cpi_is_dirty_ty(owner: *mut c_void, ty: TypeId) -> bool {
14    unsafe { (*(owner as *mut ClonePublicInterface)).is_dirty_type_id(ty) }
15}
16
17fn cpi_is_dirty_tp(owner: *mut c_void, tp: TypePackId) -> bool {
18    unsafe { (*(owner as *mut ClonePublicInterface)).is_dirty_type_pack_id(tp) }
19}
20
21fn cpi_clean_ty(owner: *mut c_void, ty: TypeId) -> TypeId {
22    unsafe { (*(owner as *mut ClonePublicInterface)).clean_type_id(ty) }
23}
24
25fn cpi_clean_tp(owner: *mut c_void, tp: TypePackId) -> TypePackId {
26    unsafe { (*(owner as *mut ClonePublicInterface)).clean_type_pack_id(tp) }
27}
28
29fn cpi_found_dirty_ty(owner: *mut c_void, ty: TypeId) {
30    unsafe {
31        (*(owner as *mut ClonePublicInterface))
32            .base
33            .found_dirty_type_id(ty)
34    }
35}
36
37fn cpi_found_dirty_tp(owner: *mut c_void, tp: TypePackId) {
38    unsafe {
39        (*(owner as *mut ClonePublicInterface))
40            .base
41            .found_dirty_type_pack_id(tp)
42    }
43}
44
45fn cpi_ignore_children_visit_ty(owner: *mut c_void, ty: TypeId) -> bool {
46    unsafe { (*(owner as *mut ClonePublicInterface)).ignore_children_visit_type_id(ty) }
47}
48
49fn cpi_ignore_children_visit_tp(owner: *mut c_void, tp: TypePackId) -> bool {
50    unsafe { (*(owner as *mut ClonePublicInterface)).ignore_children_visit_type_pack_id(tp) }
51}
52
53impl ClonePublicInterface {
54    pub fn new(
55        _log: *const TxnLog,
56        _builtin_types: *mut BuiltinTypes,
57        _module: *mut Module,
58        _solver_mode: SolverMode,
59    ) -> Self {
60        LUAU_ASSERT!(!_module.is_null());
61
62        let arena = unsafe { &mut (*_module).interface_types };
63        let base = Substitution::substitution_new(_log, arena);
64
65        ClonePublicInterface {
66            base,
67            builtin_types: _builtin_types,
68            module: _module,
69            solver_mode: _solver_mode,
70            internal_type_escaped: false,
71        }
72    }
73
74    pub(crate) fn install_substitution_vtable(&mut self) {
75        let owner = self as *mut ClonePublicInterface as *mut c_void;
76        self.base.base.vtable = SubstitutionVtable {
77            owner,
78            is_dirty_ty: Some(cpi_is_dirty_ty),
79            is_dirty_tp: Some(cpi_is_dirty_tp),
80            clean_ty: Some(cpi_clean_ty),
81            clean_tp: Some(cpi_clean_tp),
82            found_dirty_ty: Some(cpi_found_dirty_ty),
83            found_dirty_tp: Some(cpi_found_dirty_tp),
84            // ClonePublicInterface overrides ignoreChildrenVisit in C++, but
85            // inherits Tarjan::ignoreChildren=false. Replacement must still
86            // rewrite children of clean cloned parents that were reached
87            // through dirty internal children.
88            ignore_children_ty: None,
89            ignore_children_tp: None,
90            ignore_children_visit_ty: Some(cpi_ignore_children_visit_ty),
91            ignore_children_visit_tp: Some(cpi_ignore_children_visit_tp),
92        };
93    }
94}