Skip to main content

luaur_analysis/functions/
are_equivalent.rs

1use crate::functions::follow_type::follow_type_id;
2use crate::functions::follow_type_pack::follow_type_pack_id;
3use crate::records::type_function_instance_type::TypeFunctionInstanceType;
4use crate::records::type_function_instance_type_pack::TypeFunctionInstanceTypePack;
5use crate::type_aliases::type_id::TypeId;
6use crate::type_aliases::type_pack_id::TypePackId;
7
8/// C++ `template<typename T> bool areEquivalent(const T& a, const T& b)`.
9pub trait TypeFunctionInstanceEquivalent {
10    fn same_function(&self, other: &Self) -> bool;
11    fn type_arguments(&self) -> &[TypeId];
12    fn pack_arguments(&self) -> &[TypePackId];
13}
14
15impl TypeFunctionInstanceEquivalent for TypeFunctionInstanceType {
16    fn same_function(&self, other: &Self) -> bool {
17        self.function == other.function
18    }
19
20    fn type_arguments(&self) -> &[TypeId] {
21        &self.type_arguments
22    }
23
24    fn pack_arguments(&self) -> &[TypePackId] {
25        &self.pack_arguments
26    }
27}
28
29impl TypeFunctionInstanceEquivalent for TypeFunctionInstanceTypePack {
30    fn same_function(&self, other: &Self) -> bool {
31        self.function == other.function
32    }
33
34    fn type_arguments(&self) -> &[TypeId] {
35        &self.typeArguments
36    }
37
38    fn pack_arguments(&self) -> &[TypePackId] {
39        &self.packArguments
40    }
41}
42
43pub fn are_equivalent<T: TypeFunctionInstanceEquivalent>(a: &T, b: &T) -> bool {
44    if !a.same_function(b) {
45        return false;
46    }
47
48    if a.type_arguments().len() != b.type_arguments().len()
49        || a.pack_arguments().len() != b.pack_arguments().len()
50    {
51        return false;
52    }
53
54    for (a_arg, b_arg) in a.type_arguments().iter().zip(b.type_arguments().iter()) {
55        if unsafe { follow_type_id(*a_arg) } != unsafe { follow_type_id(*b_arg) } {
56            return false;
57        }
58    }
59
60    for (a_arg, b_arg) in a.pack_arguments().iter().zip(b.pack_arguments().iter()) {
61        if unsafe { follow_type_pack_id(*a_arg) } != unsafe { follow_type_pack_id(*b_arg) } {
62            return false;
63        }
64    }
65
66    true
67}