aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-07-13 13:34:21 +0100
committergingerBill <bill@gingerbill.org>2019-07-13 13:34:21 +0100
commit56d365a4e70076320386bb2f1f401cc8949c568f (patch)
tree37febb1bff6a2dd61c3d9513e0f212343b6729d9 /src
parent308300c1fc9c7cbee18f51790df46eeb06964aff (diff)
Improve type inference for procedure group parameters
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp67
1 files changed, 66 insertions, 1 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index b34b12b11..b97627b18 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -5121,7 +5121,72 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
return data;
}
- check_unpack_arguments(c, nullptr, -1, &operands, ce->args, false, false);
+ Entity **lhs = nullptr;
+ isize lhs_count = -1;
+
+ {
+ // NOTE(bill, 2019-07-13): This code is used to improve the type inference for procedure groups
+ // where the same positional parameter has the same type value (and ellipsis)
+ bool proc_arg_count_all_equal = true;
+ isize proc_arg_count = -1;
+ for_array(i, procs) {
+ Entity *p = procs[i];
+ Type *pt = base_type(p->type);
+ if (pt != nullptr && is_type_proc(pt)) {
+ if (proc_arg_count < 0) {
+ proc_arg_count = pt->Proc.param_count;
+ } else {
+ if (proc_arg_count != pt->Proc.param_count) {
+ proc_arg_count_all_equal = false;
+ break;
+ }
+ }
+ }
+ }
+
+
+ if (proc_arg_count >= 0 && proc_arg_count_all_equal) {
+ lhs_count = proc_arg_count;
+ if (lhs_count > 0) {
+ lhs = gb_alloc_array(heap_allocator(), Entity *, lhs_count);
+ for (isize param_index = 0; param_index < lhs_count; param_index++) {
+ Entity *e = nullptr;
+ for_array(j, procs) {
+ Entity *p = procs[j];
+ Type *pt = base_type(p->type);
+ if (pt != nullptr && is_type_proc(pt)) {
+ if (e == nullptr) {
+ e = pt->Proc.params->Tuple.variables[param_index];
+ } else {
+ Entity *f = pt->Proc.params->Tuple.variables[param_index];
+ if (e == f) {
+ continue;
+ }
+ if (are_types_identical(e->type, f->type)) {
+ bool ee = (e->flags & EntityFlag_Ellipsis) != 0;
+ bool fe = (f->flags & EntityFlag_Ellipsis) != 0;
+ if (ee == fe) {
+ continue;
+ }
+ }
+ // NOTE(bill): Entities are not close enough to be used
+ e = nullptr;
+ break;
+ }
+ }
+ }
+ lhs[param_index] = e;
+ }
+ }
+ }
+ }
+
+
+ check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, false, false);
+
+ if (lhs != nullptr) {
+ gb_free(heap_allocator(), lhs);
+ }
ValidIndexAndScore *valids = gb_alloc_array(heap_allocator(), ValidIndexAndScore, procs.count);
isize valid_count = 0;