Skip to main content

luaur_analysis/records/
magic_function.rs

1use alloc::sync::Arc;
2use luaur_ast::records::ast_expr_call::AstExprCall;
3
4use crate::records::magic_function_call_context::MagicFunctionCallContext;
5use crate::records::magic_function_type_check_context::MagicFunctionTypeCheckContext;
6use crate::records::magic_refinement_context::MagicRefinementContext;
7use crate::records::scope::Scope;
8use crate::records::type_checker::TypeChecker;
9use crate::records::with_predicate::WithPredicate;
10use crate::type_aliases::type_pack_id::TypePackId;
11
12/// MagicFunction is an abstract base class in C++. In Rust, we model this as a struct
13/// containing function pointers (vtable) to allow custom typechecking logic for builtins.
14#[derive(Clone)]
15pub struct MagicFunction {
16    pub(crate) handle_old_solver: fn(
17        &mut TypeChecker,
18        &Arc<Scope>,
19        &AstExprCall,
20        WithPredicate<TypePackId>,
21    ) -> Option<WithPredicate<TypePackId>>,
22
23    pub(crate) infer: fn(&MagicFunctionCallContext) -> bool,
24
25    pub(crate) refine: fn(&MagicRefinementContext),
26
27    pub(crate) type_check: fn(&MagicFunctionTypeCheckContext) -> bool,
28}
29
30impl MagicFunction {
31    /// Build a `MagicFunction` vtable from its four handler function pointers.
32    /// This is the public analog of constructing a `MagicFunction` subclass
33    /// (e.g. the test-only `MagicInstanceIsA`) outside this crate, where the
34    /// fields are not directly accessible.
35    pub fn from_handlers(
36        handle_old_solver: fn(
37            &mut TypeChecker,
38            &Arc<Scope>,
39            &AstExprCall,
40            WithPredicate<TypePackId>,
41        ) -> Option<WithPredicate<TypePackId>>,
42        infer: fn(&MagicFunctionCallContext) -> bool,
43        refine: fn(&MagicRefinementContext),
44        type_check: fn(&MagicFunctionTypeCheckContext) -> bool,
45    ) -> Self {
46        MagicFunction {
47            handle_old_solver,
48            infer,
49            refine,
50            type_check,
51        }
52    }
53}
54
55impl core::fmt::Debug for MagicFunction {
56    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
57        f.debug_struct("MagicFunction").finish_non_exhaustive()
58    }
59}
60
61unsafe impl Send for MagicFunction {}
62unsafe impl Sync for MagicFunction {}