Skip to main content

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}