1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! C++ `Frontend::Frontend(SolverMode mode, FileResolver*, ConfigResolver*,
//! FrontendOptions options)` (`Analysis/src/Frontend.cpp:435-446`).
use crate::enums::solver_mode::SolverMode;
use crate::records::builtin_types::BuiltinTypes;
use crate::records::config_resolver::ConfigResolver;
use crate::records::file_resolver::FileResolver;
use crate::records::frontend::Frontend;
use crate::records::frontend_module_resolver::FrontendModuleResolver;
use crate::records::frontend_options::FrontendOptions;
use crate::records::global_types::GlobalTypes;
use crate::records::internal_error_reporter::InternalErrorReporter;
use alloc::vec::Vec;
use core::ptr::NonNull;
use core::sync::atomic::AtomicI32;
use std::collections::HashMap;
impl Frontend {
/// Owned constructor for `Frontend::Frontend(SolverMode, FileResolver*,
/// ConfigResolver*, FrontendOptions)`.
///
/// The C++ member-init list wires several self-referential pointers:
/// `builtinTypes(NotNull{&builtinTypes_})`, `moduleResolver(this)`,
/// `moduleResolverForAutocomplete(this)`, and the two `GlobalTypes` members
/// capture `builtinTypes` (i.e. `&builtinTypes_`). None of those can be set
/// here because the returned value is moved into its final slot, so they are
/// left null/dangling-free and wired by [`Frontend::wire_self_pointers`]
/// once the `Frontend` lives at a stable address.
///
/// `builtinTypes_`'s arena is heap-boxed, so moving the `BuiltinTypes` value
/// itself is sound; `GlobalTypes::new` runs its arena mutations through the
/// temporary `&builtinTypes_` pointer (valid for the duration of this call),
/// and only the cached `builtin_types` back-pointer is re-pointed afterward.
pub fn frontend_solver_mode_file_resolver_config_resolver_frontend_options(
mode: SolverMode,
file_resolver: *mut FileResolver,
config_resolver: *mut ConfigResolver,
options: FrontendOptions,
) -> Self {
// useNewLuauSolver(mode)
let use_new_luau_solver = AtomicI32::new(mode as i32);
// builtinTypes_ is default-constructed; builtinTypes = NotNull{&builtinTypes_}.
let mut builtin_types_ = BuiltinTypes::builtin_types();
let bt_ptr: *mut BuiltinTypes = &mut builtin_types_;
// getLuauSolverMode() == useNewLuauSolver.load() == mode.
let solver_mode = mode;
// globals(builtinTypes, getLuauSolverMode())
// globalsForAutocomplete(builtinTypes, getLuauSolverMode())
let globals = GlobalTypes::new(unsafe { NonNull::new_unchecked(bt_ptr) }, solver_mode);
let globals_for_autocomplete =
GlobalTypes::new(unsafe { NonNull::new_unchecked(bt_ptr) }, solver_mode);
Frontend {
use_new_luau_solver,
environments: HashMap::new(),
builtin_definitions: HashMap::new(),
builtin_types_,
// builtinTypes(NotNull{&builtinTypes_}) — wired in wire_self_pointers.
builtin_types: core::ptr::null_mut(),
file_resolver,
// moduleResolver(this) / moduleResolverForAutocomplete(this) — wired below.
module_resolver: FrontendModuleResolver::new(core::ptr::null_mut()),
module_resolver_for_autocomplete: FrontendModuleResolver::new(core::ptr::null_mut()),
globals,
globals_for_autocomplete,
config_resolver,
options,
ice_handler: InternalErrorReporter::default(),
prepare_module_scope: None,
write_json_log: None,
source_nodes: HashMap::new(),
source_modules: HashMap::new(),
require_trace: HashMap::new(),
stats: Default::default(),
module_queue: Vec::new(),
}
}
/// Wires the self-referential pointers the C++ `Frontend` member-init list
/// sets in place: `builtinTypes(&builtinTypes_)`, the two `GlobalTypes`'
/// captured `builtinTypes`, and `moduleResolver(this)` /
/// `moduleResolverForAutocomplete(this)`.
///
/// Must be called once the `Frontend` is at its final address and before any
/// use of `builtin_types`, `globals.builtin_types`, or the module resolvers.
///
/// # Safety
/// The `Frontend` must not be moved after this call, or the wired pointers
/// dangle.
pub unsafe fn wire_self_pointers(&mut self) {
let bt_ptr: *mut BuiltinTypes = &mut self.builtin_types_;
self.builtin_types = bt_ptr;
self.globals.builtin_types = NonNull::new_unchecked(bt_ptr);
self.globals_for_autocomplete.builtin_types = NonNull::new_unchecked(bt_ptr);
let self_ptr: *mut Frontend = self;
self.module_resolver.frontend = self_ptr;
self.module_resolver_for_autocomplete.frontend = self_ptr;
}
}