luaur_analysis/functions/
check_frontend.rs1use crate::enums::solver_mode::SolverMode;
2use crate::functions::check_non_strict::check_non_strict;
3use crate::functions::check_type_checker_2::check as check_type_checker_2;
4use crate::functions::freeze::freeze;
5use crate::functions::synthesize_export_return::synthesize_export_return;
6use crate::functions::unfreeze::unfreeze;
7use crate::records::builtin_types::BuiltinTypes;
8use crate::records::constraint_graph::ConstraintGraph;
9use crate::records::constraint_list::ConstraintList;
10use crate::records::data_flow_graph_builder::DataFlowGraphBuilder;
11use crate::records::dcr_logger::DcrLogger;
12use crate::records::file_resolver::FileResolver;
13use crate::records::frontend_options::FrontendOptions;
14use crate::records::internal_error_reporter::InternalErrorReporter;
15use crate::records::module::Module;
16use crate::records::module_resolver::ModuleResolver;
17use crate::records::normalizer::Normalizer;
18use crate::records::require_cycle::RequireCycle;
19use crate::records::source_module::SourceModule;
20use crate::records::stats::Stats;
21use crate::records::subtyping::Subtyping;
22use crate::records::type_check_limits::TypeCheckLimits;
23use crate::records::type_function_runtime::TypeFunctionRuntime;
24use crate::records::unifier_shared_state::UnifierSharedState;
25use crate::type_aliases::module_name_type::ModuleName;
26use crate::type_aliases::module_ptr_module::ModulePtr;
27use crate::type_aliases::scope_ptr_type::ScopePtr;
28use alloc::string::String;
29use alloc::sync::Arc;
30use alloc::vec::Vec;
31use core::ptr::NonNull;
32use luaur_ast::enums::mode::Mode;
33use luaur_common::records::dense_hash_map::DenseHashMap;
34use luaur_common::records::dense_hash_set::DenseHashSet;
35use luaur_common::{FFlag, FInt};
36use std::rc::Rc;
37
38pub fn check(
39 source_module: &SourceModule,
40 mode: Mode,
41 require_cycles: &[RequireCycle],
42 builtin_types: *mut BuiltinTypes,
43 ice_handler: *mut InternalErrorReporter,
44 module_resolver: *mut ModuleResolver,
45 _file_resolver: *mut FileResolver,
46 parent_scope: &ScopePtr,
47 type_function_scope: &ScopePtr,
48 prepare_module_scope: Rc<dyn Fn(&ModuleName, &ScopePtr)>,
49 options: FrontendOptions,
50 limits: TypeCheckLimits,
51 _record_json_log: bool,
52 stats: &mut Stats,
53 _write_json_log: Rc<dyn Fn(&ModuleName, String)>,
54) -> ModulePtr {
55 let module: ModulePtr = Arc::new(Module::default());
56 let module_ptr = Arc::as_ptr(&module) as *mut Module;
57
58 unsafe {
59 (*module_ptr).checked_in_new_solver = true;
60 (*module_ptr).name = source_module.name.clone();
61 (*module_ptr).human_readable_name = source_module.human_readable_name.clone();
62 (*module_ptr).mode = mode;
63 (*module_ptr).internal_types.owning_module = module_ptr;
64 (*module_ptr).interface_types.owning_module = module_ptr;
65 (*module_ptr).internal_types.collect_singleton_stats =
66 options.collect_type_allocation_stats;
67 (*module_ptr).allocator = Some(source_module.allocator.clone());
68 (*module_ptr).names = Some(source_module.names.clone());
69 (*module_ptr).root = source_module.root;
70 (*ice_handler).module_name = source_module.name.clone();
71 }
72
73 let mut dfg = unsafe {
74 DataFlowGraphBuilder::build(
75 source_module.root,
76 &mut (*module_ptr).def_arena,
77 &mut (*module_ptr).key_arena,
78 ice_handler,
79 )
80 };
81
82 let mut unifier_state = UnifierSharedState::unifier_shared_state(ice_handler);
83 unifier_state.counters.recursion_limit = FInt::LuauTypeInferRecursionLimit.get() as i32;
84 unifier_state.counters.iteration_limit = limits
85 .unifierIterationLimit()
86 .unwrap_or_else(|| FInt::LuauTypeInferIterationLimit.get() as i32);
87
88 let mut normalizer = unsafe {
89 Normalizer::new(
90 &mut (*module_ptr).internal_types,
91 builtin_types,
92 &mut unifier_state,
93 SolverMode::New,
94 false,
95 )
96 };
97
98 let mut type_function_runtime = TypeFunctionRuntime {
99 ice: unsafe { (*ice_handler).clone() },
100 limits: limits.clone(),
101 type_arena: crate::records::typed_allocator::TypedAllocator::default(),
102 type_pack_arena: crate::records::typed_allocator::TypedAllocator::default(),
103 state: (core::ptr::null_mut(), None),
104 initialized: DenseHashSet::new(core::ptr::null_mut()),
105 allow_evaluation: true,
106 root_scope: parent_scope.clone(),
107 messages: Vec::new(),
108 runtime_builder: core::ptr::null_mut(),
109 };
110
111 let mut cgraph_storage = if FFlag::LuauConstraintGraph.get() {
112 Some(ConstraintGraph {
113 builtin_types: NonNull::new(builtin_types).expect("builtinTypes must not be null"),
114 dependencies: DenseHashMap::new(Default::default()),
115 reverse_dependencies: DenseHashMap::new(Default::default()),
116 constraint_lists: Vec::<Box<ConstraintList>>::new(),
117 })
118 } else {
119 None
120 };
121 let cgraph = cgraph_storage
122 .as_mut()
123 .map(|cgraph| cgraph as *mut ConstraintGraph)
124 .unwrap_or(core::ptr::null_mut());
125
126 let mut subtyping = unsafe {
127 Subtyping::subtyping_owned(
128 builtin_types,
129 &mut (*module_ptr).internal_types,
130 &mut normalizer,
131 &mut type_function_runtime,
132 ice_handler,
133 )
134 };
135
136 let logger: *mut DcrLogger = core::ptr::null_mut();
137 let mut cg = crate::records::constraint_generator::ConstraintGenerator::constraint_generator(
138 module.clone(),
139 NonNull::new(&mut normalizer).unwrap(),
140 NonNull::new(&mut type_function_runtime).unwrap(),
141 NonNull::new(module_resolver).expect("moduleResolver must not be null"),
142 NonNull::new(builtin_types).expect("builtinTypes must not be null"),
143 NonNull::new(ice_handler).expect("iceHandler must not be null"),
144 parent_scope.clone(),
145 type_function_scope.clone(),
146 prepare_module_scope,
147 logger,
148 NonNull::new(&mut dfg).unwrap(),
149 require_cycles.to_vec(),
150 cgraph,
151 );
152
153 let constraint_set = cg.run(source_module.root);
154 unsafe {
155 (*module_ptr).errors = constraint_set.errors.clone();
156 (*module_ptr).constraint_generation_did_not_complete = cg.recursion_limit_met;
157 }
158
159 let mut cs =
160 crate::records::constraint_solver::ConstraintSolver::constraint_solver_not_null_normalizer_not_null_type_function_runtime_module_ptr_not_null_module_resolver_vector_require_cycle_dcr_logger_not_null_data_flow_graph_type_check_limits_constraint_graph_not_null_subtyping(
161 &normalizer,
162 &type_function_runtime,
163 module.clone(),
164 module_resolver,
165 require_cycles.to_vec(),
166 logger,
167 &dfg,
168 limits.clone(),
169 constraint_set,
170 cgraph,
171 &subtyping,
172 );
173
174 if let Some(seed) = options.randomize_constraint_resolution_seed {
175 cs.randomize(seed);
176 }
177
178 cs.constraint_solver_run();
179 stats.dynamic_constraints_created += cs.solver_constraints.len();
180
181 unsafe {
182 (*module_ptr).errors.extend(cs.errors.iter().cloned());
183 (*module_ptr).scopes = core::mem::take(&mut cg.scopes);
184 (*module_ptr).r#type = source_module.r#type;
185 (*module_ptr).upper_bound_contributors = core::mem::replace(
186 &mut cs.upper_bound_contributors,
187 DenseHashMap::new(core::ptr::null()),
188 );
189 }
190
191 if !unsafe { (*module_ptr).timeout || (*module_ptr).cancelled } {
192 match mode {
193 Mode::Nonstrict => {
194 check_non_strict(
195 builtin_types,
196 &mut type_function_runtime,
197 ice_handler,
198 &mut unifier_state,
199 &dfg,
200 &mut limits.clone(),
201 source_module,
202 module_ptr,
203 );
204 }
205 Mode::Definition | Mode::Strict => {
206 check_type_checker_2(
207 builtin_types,
208 &mut type_function_runtime,
209 &mut unifier_state,
210 &mut limits.clone(),
211 logger,
212 source_module,
213 module_ptr,
214 );
215 }
216 Mode::NoCheck => {}
217 }
218
219 if FFlag::LuauExportValueSyntax.get()
220 && FFlag::LuauExportValueTypecheck.get()
221 && !unsafe { (*module_ptr).timeout || (*module_ptr).cancelled }
222 {
223 synthesize_export_return(builtin_types, module_ptr);
224 }
225 }
226
227 unsafe {
228 if (*module_ptr).errors.len() == 1
229 && !FFlag::DebugLuauAlwaysShowConstraintSolvingIncomplete.get()
230 && matches!(
231 &(&(*module_ptr).errors)[0].data,
232 crate::type_aliases::type_error_data::TypeErrorData::ConstraintSolvingIncompleteError(_)
233 )
234 {
235 (*module_ptr).errors.clear();
236 }
237
238 unfreeze(&mut (*module_ptr).interface_types);
239 (*module_ptr).clone_public_interface(builtin_types, &mut *ice_handler, SolverMode::New);
240 freeze(&mut (*module_ptr).internal_types);
241 freeze(&mut (*module_ptr).interface_types);
242 }
243
244 module
245}