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