Skip to main content

luaur_analysis/methods/
constraint_generator_visit_fragment_root.rs

1use crate::functions::as_mutable_type::as_mutable_type_id;
2use crate::functions::follow_type::follow_type_id;
3use crate::functions::get_type_alt_j::get_type_id;
4use crate::records::blocked_type::BlockedType;
5use crate::records::constraint_generator::ConstraintGenerator;
6use crate::records::interior_free_types::InteriorFreeTypes;
7use crate::type_aliases::scope_ptr_constraint_generator::ScopePtr;
8use crate::type_aliases::type_id::TypeId;
9use crate::type_aliases::type_variant::TypeVariant;
10use alloc::vec::Vec;
11use luaur_ast::records::ast_stat_block::AstStatBlock;
12use luaur_common::macros::luau_assert::LUAU_ASSERT;
13
14impl ConstraintGenerator {
15    // ConstraintGenerator::visitFragmentRoot (ConstraintGenerator.cpp).
16    pub fn visit_fragment_root(&mut self, resume_scope: &ScopePtr, block: *mut AstStatBlock) {
17        // We prepopulate global data in the resumeScope to avoid writing data into the old modules scopes
18        let global_scope = self.global_scope.clone().unwrap();
19        self.prepopulate_global_scope_for_fragment_typecheck(&global_scope, resume_scope, block);
20        // Pre
21        self.interior_free_types.push(InteriorFreeTypes::default());
22        self.visit_block_without_child_scope(resume_scope.as_ref() as *const _ as *mut _, block);
23        // Post
24        self.interior_free_types.pop();
25
26        self.fill_in_inferred_bindings(resume_scope, block);
27
28        if !self.logger.is_null() {
29            unsafe {
30                (*self.logger).capture_generation_module(self.module.clone().unwrap());
31            }
32        }
33
34        let local_types_pairs: Vec<(TypeId, Vec<TypeId>)> = self
35            .local_types
36            .iter()
37            .map(|(ty, domain)| (*ty, domain.order.clone()))
38            .collect();
39        for (ty, domain) in local_types_pairs {
40            // FIXME: This isn't the most efficient thing.
41            let mut domain_ty = unsafe { (*self.builtin_types).neverType };
42            for d in domain {
43                let d_followed = unsafe { follow_type_id(d) };
44                if d_followed == ty {
45                    continue;
46                }
47                domain_ty = self.simplify_union(
48                    resume_scope.clone(),
49                    unsafe { (*resume_scope.as_ref()).location },
50                    domain_ty,
51                    d_followed,
52                );
53            }
54
55            LUAU_ASSERT!(!unsafe { get_type_id::<BlockedType>(ty) }.is_null());
56            unsafe {
57                (*as_mutable_type_id(ty)).ty = TypeVariant::Bound(domain_ty);
58            }
59        }
60    }
61}