Skip to main content

luaur_analysis/methods/
overload_resolver_report_errors.rs

1//! Source: `Analysis/src/OverloadResolver.cpp:289-453` (hand-ported)
2use crate::enums::subtyping_variance::SubtypingVariance;
3use crate::enums::value::Value;
4use crate::functions::flatten_type_pack::flatten_type_pack_id;
5use crate::functions::get_argument_index::get_argument_index;
6use crate::functions::get_parameter_extents::get_parameter_extents;
7use crate::functions::get_type_pack::get_type_pack_id;
8use crate::functions::is_path_on_argument_list::is_path_on_argument_list;
9use crate::functions::is_variadic_type_pack::is_variadic;
10use crate::functions::should_suppress_errors_type_utils_alt_b::should_suppress_errors_not_null_normalizer_type_pack_id;
11use crate::functions::traverse_for_flattened_pack::traverse_for_flattened_pack;
12use crate::functions::traverse_for_pack_type_path::traverse_for_pack;
13use crate::functions::traverse_type_path_alt_b::traverse as traverse_pack_root;
14use crate::functions::traverse_type_path_alt_c::traverse as traverse_type_root;
15use crate::records::count_mismatch::{CountMismatch, CountMismatchContext};
16use crate::records::function_type::FunctionType;
17use crate::records::generic_type_pack::GenericTypePack;
18use crate::records::internal_error::InternalError;
19use crate::records::normalization_too_complex::NormalizationTooComplex;
20use crate::records::overload_resolver::OverloadResolver;
21use crate::records::subtyping_reasoning::SubtypingReasoning;
22use crate::records::txn_log::TxnLog;
23use crate::records::type_error::TypeError;
24use crate::records::type_pack_mismatch::TypePackMismatch;
25use crate::type_aliases::error_vec::ErrorVec;
26use crate::type_aliases::module_name_type_fwd::ModuleName;
27use crate::type_aliases::type_error_data::TypeErrorData;
28use crate::type_aliases::type_id::TypeId;
29use crate::type_aliases::type_pack_id::TypePackId;
30use luaur_ast::records::ast_expr::AstExpr;
31use luaur_ast::records::location::Location;
32use luaur_common::macros::luau_assert::LUAU_ASSERT;
33
34impl OverloadResolver {
35    pub fn report_errors(
36        &self,
37        errors: &mut ErrorVec,
38        fn_ty: TypeId,
39        fn_location: Location,
40        module_name: &ModuleName,
41        arg_pack: TypePackId,
42        arg_exprs: &[*mut AstExpr],
43        reason: &SubtypingReasoning,
44    ) {
45        let argument_index = get_argument_index(&reason.sub_path, fn_ty);
46
47        let mut arg_location: Location;
48        // If the Nth argument directly corresponds to a term in the AST, use its location.
49        if let Some(idx) = argument_index {
50            if idx < arg_exprs.len() {
51                arg_location = unsafe { (*arg_exprs[idx]).base.location };
52            } else if !arg_exprs.is_empty() {
53                // Else if any arguments were passed at all, use the location of the last one.
54                arg_location = unsafe { (*arg_exprs[arg_exprs.len() - 1]).base.location };
55            } else {
56                // If no arguments were present, just use the location of the whole function call.
57                arg_location = fn_location;
58            }
59        } else if !arg_exprs.is_empty() {
60            arg_location = unsafe { (*arg_exprs[arg_exprs.len() - 1]).base.location };
61        } else {
62            arg_location = fn_location;
63        }
64
65        let prospective_function = unsafe {
66            (*self.arena).add_type(FunctionType::function_type_new(
67                arg_pack,
68                (*self.builtin_types).anyTypePack,
69                None,
70                false,
71            ))
72        };
73
74        let failed_sub_pack: Option<TypePackId> = traverse_for_pack(
75            prospective_function,
76            &reason.super_path,
77            unsafe { &*self.builtin_types },
78            unsafe { &mut *self.arena },
79        );
80        let failed_super_pack: Option<TypePackId> = traverse_for_pack(
81            fn_ty,
82            &reason.sub_path,
83            unsafe { &*self.builtin_types },
84            unsafe { &mut *self.arena },
85        );
86
87        if let Some(fsp) = failed_super_pack {
88            if unsafe { !get_type_pack_id::<GenericTypePack>(fsp).is_null() } {
89                let given =
90                    failed_sub_pack.unwrap_or(unsafe { (*self.builtin_types).emptyTypePack });
91                self.maybe_emplace_error_error_vec_location_module_name_subtyping_reasoning_optional_type_pack_id_optional_type_pack_id(
92                    errors as *mut ErrorVec,
93                    arg_location,
94                    module_name,
95                    reason as *const SubtypingReasoning,
96                    failed_super_pack,
97                    Some(given),
98                );
99                return;
100            }
101        }
102
103        // If the mismatch is on the argument list itself, then the wrong number of parameters were passed.
104        if is_path_on_argument_list(&reason.sub_path) {
105            // If insufficiently many parameters are passed, we expect an empty
106            // subPath.
107            //
108            // If too many parameters are passed, we expect a slice subPath which
109            // points to the start of the unsatisfied arguments, and a superPath
110            // which points at the tail of the parameter list.
111            //
112            // Sometimes, the superPath includes generic substitutions.  We need to
113            // take this into account when computing the expected parameter count.
114
115            if failed_super_pack.is_none() {
116                errors.push(TypeError::type_error_location_module_name_type_error_data(
117                    fn_location,
118                    module_name.clone(),
119                    TypeErrorData::InternalError(InternalError::new(
120                        "Malformed SubtypingReasoning".to_string(),
121                    )),
122                ));
123                return;
124            }
125
126            let required_mapped_args = unsafe {
127                (*self.arena).add_type_pack_t(traverse_for_flattened_pack(
128                    fn_ty,
129                    &reason.sub_path,
130                    &*self.builtin_types,
131                    &mut *self.arena,
132                ))
133            };
134            let (params_head, _params_tail) = flatten_type_pack_id(required_mapped_args);
135            let (arg_head, arg_tail) = flatten_type_pack_id(arg_pack);
136
137            let arg_count = arg_head.len();
138            let (_min_params, opt_max_params) =
139                get_parameter_extents(TxnLog::empty(), required_mapped_args, false);
140
141            match should_suppress_errors_not_null_normalizer_type_pack_id(self.normalizer, arg_pack)
142                .error_suppression_value()
143            {
144                Value::Suppress => return,
145                Value::NormalizationFailed => {
146                    errors.push(TypeError::type_error_location_module_name_type_error_data(
147                        fn_location,
148                        module_name.clone(),
149                        TypeErrorData::NormalizationTooComplex(NormalizationTooComplex {
150                            _unused: None,
151                        }),
152                    ));
153                    return;
154                }
155                Value::DoNotSuppress => {}
156            }
157
158            // failedSuperPack is guaranteed Some here (checked above).
159            match should_suppress_errors_not_null_normalizer_type_pack_id(
160                self.normalizer,
161                required_mapped_args,
162            )
163            .error_suppression_value()
164            {
165                Value::Suppress => return,
166                Value::NormalizationFailed => {
167                    errors.push(TypeError::type_error_location_module_name_type_error_data(
168                        fn_location,
169                        module_name.clone(),
170                        TypeErrorData::NormalizationTooComplex(NormalizationTooComplex {
171                            _unused: None,
172                        }),
173                    ));
174                    return;
175                }
176                Value::DoNotSuppress => {}
177            }
178
179            let is_variadic_flag = match arg_tail {
180                Some(t) => is_variadic(t),
181                None => false,
182            };
183
184            if is_variadic_flag {
185                // Not actually a count mismatch!  This can happen if the
186                // required parameters are a generic pack that has not been
187                // satisfied.
188                let given =
189                    failed_sub_pack.unwrap_or(unsafe { (*self.builtin_types).emptyTypePack });
190                self.maybe_emplace_error_error_vec_location_module_name_subtyping_reasoning_optional_type_pack_id_optional_type_pack_id(
191                    errors as *mut ErrorVec,
192                    arg_location,
193                    module_name,
194                    reason as *const SubtypingReasoning,
195                    failed_super_pack,
196                    Some(given),
197                );
198            } else {
199                errors.push(TypeError::type_error_location_module_name_type_error_data(
200                    fn_location,
201                    module_name.clone(),
202                    TypeErrorData::CountMismatch(CountMismatch {
203                        expected: params_head.len(),
204                        maximum: opt_max_params,
205                        actual: arg_count,
206                        context: CountMismatchContext::Arg,
207                        is_variadic: is_variadic_flag,
208                        function: alloc::string::String::new(),
209                    }),
210                ));
211            }
212
213            return;
214        }
215
216        if let Some(idx) = argument_index {
217            // If the Nth argument directly corresponds to a term in the AST, use its location.
218            if idx < arg_exprs.len() {
219                arg_location = unsafe { (*arg_exprs[idx]).base.location };
220            } else if !arg_exprs.is_empty() {
221                // Else if any arguments were passed at all, use the location of the last one.
222                arg_location = unsafe { (*arg_exprs[arg_exprs.len() - 1]).base.location };
223            } else {
224                // If no arguments were present, just use the location of the whole function call.
225                arg_location = fn_location;
226            }
227
228            // The first path component should always be PackField::Arguments
229            LUAU_ASSERT!(reason.sub_path.components.len() > 1);
230            let mut super_path_tail = reason.super_path.clone();
231            super_path_tail.components.remove(0);
232
233            let failed_sub = traverse_pack_root(
234                arg_pack,
235                &super_path_tail,
236                unsafe { &*self.builtin_types },
237                unsafe { &mut *self.arena },
238            );
239            let failed_super = traverse_type_root(
240                fn_ty,
241                &reason.sub_path,
242                unsafe { &*self.builtin_types },
243                unsafe { &mut *self.arena },
244            );
245
246            self.maybe_emplace_error_error_vec_location_module_name_subtyping_reasoning_optional_type_or_pack_optional_type_or_pack(
247                errors as *mut ErrorVec,
248                arg_location,
249                module_name,
250                reason as *const SubtypingReasoning,
251                failed_super,
252                failed_sub,
253            );
254            return;
255        }
256
257        if let Some(fsp) = failed_sub_pack {
258            if failed_super_pack.is_none()
259                && unsafe { !get_type_pack_id::<GenericTypePack>(fsp).is_null() }
260            {
261                errors.push(TypeError::type_error_location_module_name_type_error_data(
262                    arg_location,
263                    module_name.clone(),
264                    TypeErrorData::TypePackMismatch(TypePackMismatch {
265                        wanted_tp: fsp,
266                        given_tp: unsafe { (*self.builtin_types).emptyTypePack },
267                        reason: alloc::string::String::new(),
268                    }),
269                ));
270            }
271        }
272
273        if let (Some(fsp), Some(fsup)) = (failed_sub_pack, failed_super_pack) {
274            // If a bug in type inference occurs, we may have a mismatch in the return packs.
275            // This happens when inference incorrectly leaves the result type of a function free.
276            // If this happens, we don't want to explode, so we'll use the function's location.
277            if arg_exprs.is_empty() {
278                arg_location = fn_location;
279            } else {
280                arg_location = unsafe { (*arg_exprs[arg_exprs.len() - 1]).base.location };
281            }
282
283            let error_suppression =
284                should_suppress_errors_not_null_normalizer_type_pack_id(self.normalizer, fsp)
285                    .or_else(&should_suppress_errors_not_null_normalizer_type_pack_id(
286                        self.normalizer,
287                        fsup,
288                    ));
289            if error_suppression.error_suppression_value() == Value::Suppress {
290                return;
291            }
292
293            match reason.variance {
294                SubtypingVariance::Covariant => {
295                    errors.push(TypeError::type_error_location_module_name_type_error_data(
296                        arg_location,
297                        module_name.clone(),
298                        TypeErrorData::TypePackMismatch(TypePackMismatch {
299                            wanted_tp: fsp,
300                            given_tp: fsup,
301                            reason: alloc::string::String::new(),
302                        }),
303                    ));
304                }
305                SubtypingVariance::Contravariant => {
306                    errors.push(TypeError::type_error_location_module_name_type_error_data(
307                        arg_location,
308                        module_name.clone(),
309                        TypeErrorData::TypePackMismatch(TypePackMismatch {
310                            wanted_tp: fsup,
311                            given_tp: fsp,
312                            reason: alloc::string::String::new(),
313                        }),
314                    ));
315                }
316                SubtypingVariance::Invariant => {
317                    errors.push(TypeError::type_error_location_module_name_type_error_data(
318                        arg_location,
319                        module_name.clone(),
320                        TypeErrorData::TypePackMismatch(TypePackMismatch {
321                            wanted_tp: fsp,
322                            given_tp: fsup,
323                            reason: alloc::string::String::new(),
324                        }),
325                    ));
326                }
327                _ => {
328                    LUAU_ASSERT!(false);
329                }
330            }
331        }
332    }
333}