Skip to main content

luaur_analysis/methods/
unifier_try_unify_variadics.rs

1//! Source: `Analysis/src/Unifier.cpp` (Unifier::tryUnifyVariadics, L2432-2493)
2use crate::functions::begin_type_pack_alt_d::begin;
3use crate::functions::end_type_pack::end;
4use crate::functions::follow_type::follow as follow_type;
5use crate::functions::follow_type_pack::follow as follow_pack;
6use crate::functions::get_type_pack::get_type_pack_id;
7use crate::functions::is_blocked_unifier_alt_c::is_blocked_txn_log_type_pack_id;
8use crate::records::any_type::AnyType;
9use crate::records::free_type_pack::FreeTypePack;
10use crate::records::generic_error::GenericError;
11use crate::records::generic_type_pack::GenericTypePack;
12use crate::records::type_pack::TypePack;
13use crate::records::type_pack_var::TypePackVar;
14use crate::records::unifier::Unifier;
15use crate::records::variadic_type_pack::VariadicTypePack;
16use crate::type_aliases::error_type_pack::ErrorTypePack;
17use crate::type_aliases::type_error_data::TypeErrorData;
18use crate::type_aliases::type_pack_id::TypePackId;
19use crate::type_aliases::type_pack_variant::TypePackVariant;
20use alloc::string::String;
21
22impl Unifier {
23    /// `void Unifier::tryUnifyVariadics(TypePackId subTp, TypePackId superTp, bool reversed, int subOffset)`
24    pub fn unifier_try_unify_variadics(
25        &mut self,
26        sub_tp: TypePackId,
27        super_tp: TypePackId,
28        reversed: bool,
29        sub_offset: i32,
30    ) {
31        let super_variadic = self
32            .log
33            .txn_log_get_mutable::<VariadicTypePack, TypePackId>(super_tp);
34        let variadic_ty = unsafe { follow_type((*super_variadic).ty) };
35
36        if super_variadic.is_null() {
37            self.ice_string("passed non-variadic pack to tryUnifyVariadics");
38        }
39
40        let sub_variadic = self.log.txn_log_get::<VariadicTypePack, TypePackId>(sub_tp);
41        if !sub_variadic.is_null() {
42            let (a, b) = if reversed {
43                (variadic_ty, unsafe { (*sub_variadic).ty })
44            } else {
45                (unsafe { (*sub_variadic).ty }, variadic_ty)
46            };
47            self.try_unify_type_id_type_id_bool_bool_literal_properties(a, b, false, false, None);
48        } else if !self
49            .log
50            .txn_log_get::<TypePack, TypePackId>(sub_tp)
51            .is_null()
52        {
53            let mut sub_iter = begin(sub_tp, &self.log as *const _);
54            let sub_end = end(sub_tp);
55
56            for _ in 0..sub_offset {
57                sub_iter.operator_inc();
58            }
59
60            while sub_iter.operator_ne(&sub_end) {
61                let cur = *sub_iter.operator_deref();
62                let (a, b) = if reversed {
63                    (variadic_ty, cur)
64                } else {
65                    (cur, variadic_ty)
66                };
67                self.try_unify_type_id_type_id_bool_bool_literal_properties(
68                    a, b, false, false, None,
69                );
70                sub_iter.operator_inc();
71            }
72
73            if let Some(maybe_tail) = sub_iter.tail() {
74                let tail = unsafe { follow_pack(maybe_tail) };
75
76                if is_blocked_txn_log_type_pack_id(&self.log, tail) {
77                    self.blocked_type_packs.push(tail);
78                } else if !unsafe { get_type_pack_id::<FreeTypePack>(tail) }.is_null() {
79                    // log.replace(tail, BoundTypePack(superTp));
80                    let bound = TypePackVar {
81                        ty: TypePackVariant::Bound(super_tp),
82                        persistent: false,
83                        owningArena: core::ptr::null_mut(),
84                    };
85                    self.log.replace_type_pack_id_type_pack_var(tail, bound);
86                } else if let Some(vtp) =
87                    unsafe { get_type_pack_id::<VariadicTypePack>(tail).as_ref() }
88                {
89                    self.try_unify_type_id_type_id_bool_bool_literal_properties(
90                        vtp.ty,
91                        variadic_ty,
92                        false,
93                        false,
94                        None,
95                    );
96                } else if !unsafe { get_type_pack_id::<GenericTypePack>(tail) }.is_null() {
97                    self.report_error_location_type_error_data(
98                        self.location,
99                        TypeErrorData::GenericError(GenericError::new(String::from(
100                            "Cannot unify variadic and generic packs",
101                        ))),
102                    );
103                } else if !unsafe { get_type_pack_id::<ErrorTypePack>(tail) }.is_null() {
104                    // Nothing to do here.
105                } else {
106                    self.ice_string("Unknown TypePack kind");
107                }
108            }
109        } else if !unsafe { crate::functions::get_type_alt_j::get_type_id::<AnyType>(variadic_ty) }
110            .is_null()
111            && !self
112                .log
113                .txn_log_get::<GenericTypePack, TypePackId>(sub_tp)
114                .is_null()
115        {
116            // Nothing to do.  This is ok.
117        } else {
118            self.report_error_location_type_error_data(
119                self.location,
120                TypeErrorData::GenericError(GenericError::new(String::from(
121                    "Failed to unify variadic packs",
122                ))),
123            );
124        }
125    }
126}