Skip to main content

luaur_analysis/methods/
subtyping_is_covariant_with_super_tail.rs

1//! Faithful port of `Subtyping::isCovariantWithSuperTail`
2//! (Analysis/src/Subtyping.cpp:1260-1338).
3use crate::enums::early_exit::EarlyExit;
4use crate::enums::pack_field::PackField;
5use crate::enums::subtyping_suppression_policy::SubtypingSuppressionPolicy;
6use crate::enums::variant::Variant;
7use crate::functions::follow_type_pack::follow_type_pack_id;
8use crate::functions::get_type_pack::get_type_pack_id;
9use crate::functions::slice_type_pack::slice_type_pack;
10use crate::records::error_type_pack::ErrorTypePack;
11use crate::records::free_type_pack::FreeTypePack;
12use crate::records::generic_pack_mapping::GenericPackMapping;
13use crate::records::generic_type_pack::GenericTypePack;
14use crate::records::index::Index;
15use crate::records::pack_slice::PackSlice;
16use crate::records::pack_subtype_constraint::PackSubtypeConstraint;
17use crate::records::scope::Scope;
18use crate::records::subtyping::Subtyping;
19use crate::records::subtyping_environment::SubtypingEnvironment;
20use crate::records::subtyping_result::SubtypingResult;
21use crate::records::type_error::TypeError;
22use crate::records::type_pack::TypePack;
23use crate::records::unexpected_type_pack_in_subtyping::UnexpectedTypePackInSubtyping;
24use crate::records::variadic_type_pack::VariadicTypePack;
25use crate::type_aliases::component::Component;
26use crate::type_aliases::constraint_v::ConstraintV;
27use crate::type_aliases::lookup_result::LookupResult;
28use crate::type_aliases::path::Path;
29use crate::type_aliases::type_id::TypeId;
30use crate::type_aliases::type_pack_id::TypePackId;
31
32use crate::methods::path_builder_build::PathBuilderBuild;
33use crate::methods::path_builder_tail::PathBuilderTail;
34use crate::methods::path_builder_variadic::PathBuilderVariadic;
35use crate::records::path_builder::PathBuilder;
36
37impl Subtyping {
38    pub fn is_covariant_with_super_tail(
39        &mut self,
40        env: &mut SubtypingEnvironment,
41        output_result: &mut SubtypingResult,
42        sub_tp: TypePackId,
43        sub_head_start_index: usize,
44        sub_head: &Vec<TypeId>,
45        sub_tail: Option<TypePackId>,
46        super_tp: TypePackId,
47        super_tail: TypePackId,
48        scope: *mut Scope,
49    ) -> EarlyExit {
50        let _ = super_tp;
51
52        if let Some(vt) = unsafe { get_type_pack_id::<VariadicTypePack>(super_tail).as_ref() } {
53            for i in sub_head_start_index..sub_head.len() {
54                let mut next = self
55                    .is_covariant_with_subtyping_environment_type_id_type_id_not_null_scope(
56                        env,
57                        sub_head[i],
58                        vt.ty,
59                        scope,
60                    );
61                next.with_sub_component(Component::Index(Index {
62                    index: i,
63                    variant: Variant::Pack,
64                }));
65                next.with_super_path(
66                    PathBuilder {
67                        components: alloc::vec::Vec::new(),
68                    }
69                    .tail()
70                    .variadic()
71                    .build(),
72                );
73                output_result.and_also(next, SubtypingSuppressionPolicy::Any);
74            }
75            EarlyExit::No
76        } else if !unsafe { get_type_pack_id::<GenericTypePack>(super_tail).is_null() } {
77            let lookup_result = env.lookup_generic_pack(super_tail);
78            let result: SubtypingResult;
79            if let LookupResult::V2(_) = lookup_result {
80                // get_if<MappedGenericEnvironment::NotBindable>
81                let mut r = SubtypingResult {
82                    is_subtype: false,
83                    normalization_too_complex: false,
84                    is_cacheable: false,
85                    ..Default::default()
86                };
87                r.with_sub_component(Component::PackSlice(PackSlice {
88                    start_index: sub_head_start_index,
89                }));
90                r.with_super_component(Component::PackField(PackField::Tail));
91                result = r;
92            } else {
93                let sub_tail_pack = slice_type_pack(
94                    sub_head_start_index,
95                    sub_tp,
96                    sub_head,
97                    sub_tail,
98                    unsafe { &*self.builtin_types },
99                    unsafe { &mut *self.arena },
100                );
101
102                if let LookupResult::V0(mapped_gen) = lookup_result {
103                    // get_if<TypePackId> — subtype against the mapped generic pack.
104                    let mut super_tp_to_compare = mapped_gen;
105
106                    let tp = unsafe { get_type_pack_id::<TypePack>(mapped_gen).as_ref() };
107                    if let Some(tp) = tp {
108                        if let Some(tail) = tp.tail {
109                            let vtp = unsafe {
110                                get_type_pack_id::<VariadicTypePack>(follow_type_pack_id(tail))
111                                    .as_ref()
112                            };
113                            if let Some(vtp) = vtp {
114                                if vtp.hidden {
115                                    super_tp_to_compare = unsafe {
116                                        (*self.arena)
117                                            .add_type_pack_initializer_list_type_id(&tp.head)
118                                    };
119                                }
120                            }
121                        }
122                    }
123
124                    let mut r = self
125                        .is_covariant_with_subtyping_environment_type_pack_id_type_pack_id_not_null_scope(
126                            env,
127                            sub_tail_pack,
128                            super_tp_to_compare,
129                            scope,
130                        );
131                    r.with_sub_component(Component::PackSlice(PackSlice {
132                        start_index: sub_head_start_index,
133                    }));
134                    r.with_super_path(Path::from_components(alloc::vec![
135                        Component::PackField(PackField::Tail),
136                        Component::GenericPackMapping(GenericPackMapping {
137                            mappedType: mapped_gen
138                        }),
139                    ]));
140                    result = r;
141                } else {
142                    // get_if<MappedGenericEnvironment::Unmapped>
143                    let ok = env
144                        .mapped_generic_packs
145                        .bind_generic(super_tail, sub_tail_pack);
146                    let mut r = SubtypingResult {
147                        is_subtype: ok,
148                        normalization_too_complex: false,
149                        is_cacheable: false,
150                        ..Default::default()
151                    };
152                    r.with_sub_component(Component::PackSlice(PackSlice {
153                        start_index: sub_head_start_index,
154                    }));
155                    r.with_super_component(Component::PackField(PackField::Tail));
156                    result = r;
157                }
158            }
159
160            output_result.and_also(result, SubtypingSuppressionPolicy::Any);
161            EarlyExit::Yes
162        } else if !unsafe { get_type_pack_id::<ErrorTypePack>(super_tail).is_null() } {
163            let mut r = SubtypingResult {
164                is_subtype: true,
165                ..Default::default()
166            };
167            r.with_super_component(Component::PackField(PackField::Tail));
168            *output_result = r;
169            EarlyExit::Yes
170        } else if !unsafe { get_type_pack_id::<FreeTypePack>(super_tail).is_null() } {
171            let sub_tail_pack = slice_type_pack(
172                sub_head_start_index,
173                sub_tp,
174                sub_head,
175                sub_tail,
176                unsafe { &*self.builtin_types },
177                unsafe { &mut *self.arena },
178            );
179            let mut r = SubtypingResult {
180                is_subtype: true,
181                ..Default::default()
182            };
183            r.with_super_component(Component::PackField(PackField::Tail));
184            r.with_assumed_constraint(ConstraintV::PackSubtype(PackSubtypeConstraint {
185                sub_pack: sub_tail_pack,
186                super_pack: super_tail,
187                returns: false,
188            }));
189            output_result.and_also(r, SubtypingSuppressionPolicy::Any);
190            EarlyExit::Yes
191        } else {
192            let mut r = SubtypingResult {
193                is_subtype: false,
194                ..Default::default()
195            };
196            r.with_super_component(Component::PackField(PackField::Tail));
197            r.with_error(TypeError::type_error_location_type_error_data(
198                unsafe { (*scope).location.clone() },
199                UnexpectedTypePackInSubtyping { tp: super_tail }.into(),
200            ));
201            *output_result = r;
202            EarlyExit::Yes
203        }
204    }
205}