Skip to content

Commit 403ca2f

Browse files
committed
Improve type inferencing of literals when calling proc groups
1 parent 935d965 commit 403ca2f

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

src/check_expr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6977,6 +6977,10 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
69776977
array_unordered_remove(&procs, proc_index);
69786978
continue;
69796979
}
6980+
if (!pt->Proc.variadic && max_arg_count != ISIZE_MAX && param_count < max_arg_count) {
6981+
array_unordered_remove(&procs, proc_index);
6982+
continue;
6983+
}
69806984
proc_index++;
69816985
}
69826986
}
@@ -7014,6 +7018,8 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
70147018
{
70157019
// NOTE(bill, 2019-07-13): This code is used to improve the type inference for procedure groups
70167020
// where the same positional parameter has the same type value (and ellipsis)
7021+
7022+
//TODO: get rid of proc_arg_count. make lhs as long as longest proc with most params. watch out for null safety
70177023
isize proc_arg_count = -1;
70187024
for (Entity *p : procs) {
70197025
Type *pt = base_type(p->type);
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#+feature dynamic-literals
2+
3+
package test_internal
4+
5+
import "core:testing"
6+
7+
@test
8+
test_type_inference_on_literals_for_various_parameters_combinations :: proc(t: ^testing.T) {
9+
Bit_Set :: bit_set[enum{A, B, C}]
10+
group :: proc{proc_0, proc_1, proc_2, proc_3, proc_4, proc_5}
11+
proc_0 :: proc() -> int { return 0 }
12+
proc_1 :: proc(Bit_Set) -> int { return 1 }
13+
proc_2 :: proc(int, Bit_Set) -> int { return 2 }
14+
proc_3 :: proc(f32, Bit_Set) -> int { return 3 }
15+
proc_4 :: proc(int, int, Bit_Set) -> int { return 4 }
16+
proc_5 :: proc(Bit_Set, int, int, int) -> int { return 5 }
17+
18+
testing.expect_value(t, group({.A}), 1)
19+
testing.expect_value(t, group(9, {.A}), 2)
20+
testing.expect_value(t, group(3.14, {.A}), 3)
21+
testing.expect_value(t, group(9, 9, {.A}), 4)
22+
testing.expect_value(t, group({.A}, 9, 9, 9), 5)
23+
}
24+
25+
@test
26+
test_type_inference_on_literals_with_default_args :: proc(t: ^testing.T) {
27+
{
28+
Bit_Set :: bit_set[enum{A, B, C}]
29+
proc_nil :: proc() { }
30+
proc_default_arg :: proc(a: Bit_Set={.A}) -> Bit_Set { return a }
31+
group :: proc{proc_nil, proc_default_arg}
32+
33+
testing.expect_value(t, group(Bit_Set{.A}), Bit_Set{.A})
34+
testing.expect_value(t, group({.A}), Bit_Set{.A})
35+
}
36+
{
37+
Bit_Set :: bit_set[enum{A, B, C}]
38+
proc_1 :: proc(a: Bit_Set={.A}) -> int { return 1 }
39+
proc_2 :: proc(a: Bit_Set={.B}, b: Bit_Set={.C}) -> int { return 2 }
40+
group :: proc{proc_1, proc_2}
41+
42+
testing.expect_value(t, group(), 2)
43+
testing.expect_value(t, group(Bit_Set{.A}), 2)
44+
testing.expect_value(t, group({.A}), 2)
45+
testing.expect_value(t, group({.B}, {.C}), 2)
46+
}
47+
}
48+
49+
@test
50+
test_type_inference_on_literals_for_various_types :: proc(t: ^testing.T) {
51+
proc_nil :: proc() { }
52+
53+
proc_array :: proc(a: [3]f32) -> [3]f32 { return a }
54+
group_array :: proc{proc_nil, proc_array}
55+
testing.expect_value(t, group_array([3]f32{1.1, 2.2, 3.3}), [3]f32{1.1, 2.2, 3.3})
56+
testing.expect_value(t, group_array({1.1, 2.2, 3.3}), [3]f32{1.1, 2.2, 3.3})
57+
testing.expect_value(t, group_array({0=1.1, 1=2.2, 2=3.3}), [3]f32{1.1, 2.2, 3.3})
58+
testing.expect_value(t, group_array({}), [3]f32{})
59+
60+
proc_slice_u8 :: proc(a: []u8) -> []u8 { return a }
61+
group_slice_u8 :: proc{proc_nil, proc_slice_u8}
62+
testing.expect_value(t, len(group_slice_u8([]u8{1, 2, 3})), 3)
63+
testing.expect_value(t, len(group_slice_u8({1, 2, 3})), 3)
64+
testing.expect_value(t, len(group_slice_u8({0=1, 1=2, 2=3})), 3)
65+
testing.expect_value(t, len(group_slice_u8({})), 0)
66+
testing.expect_value(t, group_slice_u8(nil) == nil, true)
67+
68+
proc_dynamic_array :: proc(a: [dynamic]u8) -> [dynamic]u8 { return a }
69+
group_dynamic_array :: proc{proc_nil, proc_dynamic_array}
70+
testing.expect_value(t, len(group_dynamic_array([dynamic]u8{1, 2, 3})), 3)
71+
testing.expect_value(t, len(group_dynamic_array({1, 2, 3})), 3)
72+
testing.expect_value(t, len(group_dynamic_array({0=1, 1=2, 2=3})), 3)
73+
testing.expect_value(t, len(group_dynamic_array({})), 0)
74+
testing.expect_value(t, group_dynamic_array(nil) == nil, true)
75+
76+
Enum :: enum{A, B, C}
77+
proc_enum :: proc(a: Enum) -> Enum { return a }
78+
group_enum :: proc{proc_nil, proc_enum}
79+
testing.expect_value(t, group_enum(Enum.A), Enum.A)
80+
testing.expect_value(t, group_enum(.A), Enum.A)
81+
82+
proc_enumerated_array :: proc(a: [Enum]u8) -> [Enum]u8 { return a }
83+
group_enumerated_array :: proc{proc_nil, proc_enumerated_array}
84+
testing.expect_value(t, group_enumerated_array([Enum]u8{.A=1, .B=2, .C=3}), [Enum]u8{.A=1, .B=2, .C=3})
85+
testing.expect_value(t, group_enumerated_array({.A=1, .B=2, .C=3}), [Enum]u8{.A=1, .B=2, .C=3})
86+
87+
Bit_Set :: bit_set[enum{A, B, C}]
88+
proc_bit_set :: proc(a: Bit_Set) -> Bit_Set { return a }
89+
group_bit_set :: proc{proc_nil, proc_bit_set}
90+
testing.expect_value(t, group_bit_set(Bit_Set{.A}), Bit_Set{.A})
91+
testing.expect_value(t, group_bit_set({.A}), Bit_Set{.A})
92+
testing.expect_value(t, group_bit_set({}), Bit_Set{})
93+
94+
Struct :: struct{a: int, b: int, c: int}
95+
proc_struct :: proc(a: Struct) -> Struct { return a }
96+
group_struct :: proc{proc_nil, proc_struct}
97+
testing.expect_value(t, group_struct(Struct{a = 9}), Struct{a = 9})
98+
testing.expect_value(t, group_struct({a = 9}), Struct{a = 9})
99+
testing.expect_value(t, group_struct({}), Struct{})
100+
101+
Raw_Union :: struct #raw_union{int_: int, f32_: f32}
102+
proc_raw_union :: proc(a: Raw_Union) -> Raw_Union { return a }
103+
group_raw_union :: proc{proc_nil, proc_raw_union}
104+
testing.expect_value(t, group_raw_union(Raw_Union{int_ = 9}).int_, 9)
105+
testing.expect_value(t, group_raw_union({int_ = 9}).int_, 9)
106+
testing.expect_value(t, group_raw_union({}).int_, 0)
107+
108+
Union :: union{int, f32}
109+
proc_union :: proc(a: Union) -> Union { return a }
110+
group_union :: proc{proc_nil, proc_union}
111+
testing.expect_value(t, group_union(int(9)).(int), 9)
112+
testing.expect_value(t, group_union({}).(int), 0)
113+
114+
proc_map :: proc(a: map[u8]u8) -> map[u8]u8 { return a }
115+
group_map :: proc{proc_nil, proc_map}
116+
testing.expect_value(t, len(group_map(map[u8]u8{1=1, 2=2})), 2)
117+
testing.expect_value(t, len(group_map({1=1, 2=2})), 2)
118+
testing.expect_value(t, len(group_map({})), 0)
119+
testing.expect_value(t, group_map(nil) == nil, true)
120+
121+
Bit_Field :: bit_field u16 {a: u8|4, b: u8|4, c: u8|4}
122+
proc_bit_field :: proc(a: Bit_Field) -> Bit_Field { return a }
123+
group_bit_field :: proc{proc_nil, proc_bit_field}
124+
testing.expect_value(t, group_bit_field(Bit_Field{a = 1}), Bit_Field{a = 1})
125+
testing.expect_value(t, group_bit_field({a = 1}), Bit_Field{a = 1})
126+
testing.expect_value(t, group_bit_field({}), Bit_Field{})
127+
128+
SOA_Array :: #soa[2]struct{int, int}
129+
proc_soa_array :: proc(a: SOA_Array) -> SOA_Array { return a }
130+
group_soa_array :: proc{proc_nil, proc_soa_array}
131+
testing.expect_value(t, len(group_soa_array(SOA_Array{{}, {}})), 2)
132+
testing.expect_value(t, len(group_soa_array({struct{int, int}{1, 2}, struct{int, int}{1, 2}})), 1)
133+
testing.expect_value(t, len(group_soa_array({})), 0)
134+
testing.expect_value(t, len(soa_zip(a=[]int{1, 2}, b=[]int{3, 4})), 2)
135+
136+
proc_matrix :: proc(a: matrix[2,2]f32) -> matrix[2,2]f32 { return a }
137+
group_matrix :: proc{proc_nil, proc_matrix}
138+
testing.expect_value(t, group_matrix(matrix[2,2]f32{1, 2, 3, 4}), matrix[2,2]f32{1, 2, 3, 4})
139+
testing.expect_value(t, group_matrix(1), (matrix[2,2]f32)(1))
140+
testing.expect_value(t, group_matrix({1, 2, 3, 4}), matrix[2,2]f32{1, 2, 3, 4})
141+
testing.expect_value(t, group_matrix({}), matrix[2,2]f32{})
142+
}

0 commit comments

Comments
 (0)