v4 / vlib / v / tests / generics / structured_generic_receiver_declaration_test.v
305 lines · 268 sloc · 8.84 KB · a8cc0bb64eb2e3d48acfa0409c1e95b2226c8e5c
Raw
1struct ReceiverPatternExpect[T] {
2 value T
3}
4
5struct MixedReceiverPatternBox[T, U] {
6 direct T
7 items U
8}
9
10type IntListExpect = ReceiverPatternExpect[[]int]
11type StringIntMapExpect = ReceiverPatternExpect[map[string]int]
12type MixedIntStringListBox = MixedReceiverPatternBox[int, []string]
13
14fn (e ReceiverPatternExpect[T]) broad_receiver_returns_value() T {
15 return e.value
16}
17
18fn (e ReceiverPatternExpect[[]int]) concrete_array_receiver_returns_len() int {
19 return e.value.len
20}
21
22fn (e ReceiverPatternExpect[[]int]) same_name_prefers_concrete_receiver() string {
23 return 'concrete'
24}
25
26fn (e ReceiverPatternExpect[[]int]) same_name_with_method_generic_prefers_concrete_receiver[U](extra U) string {
27 return 'concrete'
28}
29
30fn (e ReceiverPatternExpect[[]T]) dynamic_array_receiver_pattern_returns_first_or_value(value T) T {
31 if e.value.len == 0 {
32 return value
33 }
34 return e.value[0]
35}
36
37fn (e ReceiverPatternExpect[[]T]) same_name_prefers_concrete_receiver() string {
38 return 'pattern'
39}
40
41fn (e ReceiverPatternExpect[[]T]) same_name_with_method_generic_prefers_concrete_receiver[U](extra U) string {
42 return 'pattern'
43}
44
45fn (e ReceiverPatternExpect[[]T]) dynamic_array_receiver_pattern_pairs_with_method_generic[U](value T,
46 extra U) (T, U) {
47 if e.value.len == 0 {
48 return value, extra
49 }
50 return e.value[0], extra
51}
52
53fn (e ReceiverPatternExpect[map[K]V]) map_receiver_pattern_returns_existing_or_default(key K,
54 value V) V {
55 if key in e.value {
56 return e.value[key]
57 }
58 return value
59}
60
61fn (e ReceiverPatternExpect[map[K]V]) map_receiver_pattern_pairs_with_method_generic[U](key K,
62 value V, extra U) (V, U) {
63 if key in e.value {
64 return e.value[key], extra
65 }
66 return value, extra
67}
68
69fn (e ReceiverPatternExpect[map[K]V]) same_name_map_exact_prefers_concrete[U](extra U) string {
70 _ = extra
71 return 'pattern'
72}
73
74fn (e ReceiverPatternExpect[map[string]int]) same_name_map_exact_prefers_concrete[U](extra U) string {
75 _ = extra
76 return 'concrete'
77}
78
79fn (e ReceiverPatternExpect[map[K]V]) same_name_map_method() string {
80 return 'pattern'
81}
82
83fn (e ReceiverPatternExpect[map[string]int]) same_name_map_method() string {
84 return 'concrete'
85}
86
87fn (b MixedReceiverPatternBox[T, []U]) mixed_receiver_pattern_values_with_method_generic[V](fallback U,
88 marker V) (T, U, V) {
89 if b.items.len == 0 {
90 return b.direct, fallback, marker
91 }
92 return b.direct, b.items[0], marker
93}
94
95fn (b MixedReceiverPatternBox[int, []string]) same_name_with_method_generic_prefers_concrete_mixed_receiver[V](marker V) string {
96 return 'concrete'
97}
98
99fn (b MixedReceiverPatternBox[T, []U]) same_name_with_method_generic_prefers_concrete_mixed_receiver[V](marker V) string {
100 return 'pattern'
101}
102
103fn test_existing_generic_receiver_declarations_still_work() {
104 assert ReceiverPatternExpect[int]{
105 value: 7
106 }.broad_receiver_returns_value() == 7
107 assert ReceiverPatternExpect[[]int]{
108 value: [1, 2, 3]
109 }.concrete_array_receiver_returns_len() == 3
110}
111
112fn test_concrete_receiver_method_takes_precedence_over_structured_pattern() {
113 assert ReceiverPatternExpect[[]int]{
114 value: [1, 2, 3]
115 }.same_name_prefers_concrete_receiver() == 'concrete'
116 assert ReceiverPatternExpect[[]string]{
117 value: ['alpha']
118 }.same_name_prefers_concrete_receiver() == 'pattern'
119}
120
121fn test_concrete_receiver_method_with_method_generic_takes_precedence_over_structured_pattern() {
122 assert ReceiverPatternExpect[[]int]{
123 value: [1, 2, 3]
124 }.same_name_with_method_generic_prefers_concrete_receiver('extra') == 'concrete'
125 assert ReceiverPatternExpect[[]int]{
126 value: [1]
127 }.same_name_with_method_generic_prefers_concrete_receiver[string]('extra') == 'concrete'
128 assert ReceiverPatternExpect[[]string]{
129 value: ['alpha']
130 }.same_name_with_method_generic_prefers_concrete_receiver('extra') == 'pattern'
131}
132
133fn test_structured_generic_receiver_patterns_can_be_declared() {
134 assert true
135}
136
137fn test_dynamic_array_receiver_pattern_binds_element_type() {
138 assert ReceiverPatternExpect[[]int]{
139 value: [1, 2, 3]
140 }.dynamic_array_receiver_pattern_returns_first_or_value(9) == 1
141 assert ReceiverPatternExpect[[]string]{
142 value: ['alpha', 'beta']
143 }.dynamic_array_receiver_pattern_returns_first_or_value('fallback') == 'alpha'
144}
145
146fn test_dynamic_array_receiver_pattern_binds_nested_element_type() {
147 assert ReceiverPatternExpect[[][]int]{
148 value: [[1, 2], [3, 4]]
149 }.dynamic_array_receiver_pattern_returns_first_or_value([9, 10]) == [1, 2]
150 assert ReceiverPatternExpect[[]map[string]int]{
151 value: [
152 {
153 'one': 1
154 },
155 ]
156 }.dynamic_array_receiver_pattern_returns_first_or_value({
157 'zero': 0
158 })['one'] == 1
159}
160
161fn test_dynamic_array_receiver_pattern_method_generic_is_inferred() {
162 value, extra := ReceiverPatternExpect[[]int]{
163 value: [1, 2, 3]
164 }.dynamic_array_receiver_pattern_pairs_with_method_generic(9, 'extra')
165 assert value == 1
166 assert extra == 'extra'
167 explicit_value, explicit_extra := ReceiverPatternExpect[[]int]{
168 value: [1, 2, 3]
169 }.dynamic_array_receiver_pattern_pairs_with_method_generic[string](9, 'explicit')
170 assert explicit_value == 1
171 assert explicit_extra == 'explicit'
172}
173
174fn test_map_receiver_pattern_binds_key_and_value_types() {
175 assert ReceiverPatternExpect[map[string]int]{
176 value: {
177 'one': 1
178 }
179 }.map_receiver_pattern_returns_existing_or_default('one', 0) == 1
180 assert ReceiverPatternExpect[map[int]string]{
181 value: {
182 2: 'two'
183 }
184 }.map_receiver_pattern_returns_existing_or_default(3, 'fallback') == 'fallback'
185}
186
187fn test_map_receiver_pattern_method_generic_can_be_explicit() {
188 value, extra := ReceiverPatternExpect[map[string]int]{
189 value: {
190 'one': 1
191 }
192 }.map_receiver_pattern_pairs_with_method_generic[string]('missing', 7, 'extra')
193 assert value == 7
194 assert extra == 'extra'
195}
196
197fn test_alias_to_array_receiver_pattern_binds_element_type() {
198 assert IntListExpect{
199 value: [1, 2, 3]
200 }.dynamic_array_receiver_pattern_returns_first_or_value(9) == 1
201 value, extra := IntListExpect{
202 value: [1, 2, 3]
203 }.dynamic_array_receiver_pattern_pairs_with_method_generic[string](9, 'alias')
204 assert value == 1
205 assert extra == 'alias'
206 inferred_value, inferred_extra := IntListExpect{
207 value: [1, 2, 3]
208 }.dynamic_array_receiver_pattern_pairs_with_method_generic(9, 'inferred')
209 assert inferred_value == 1
210 assert inferred_extra == 'inferred'
211}
212
213fn test_alias_to_map_receiver_pattern_binds_key_and_value_types() {
214 assert StringIntMapExpect{
215 value: {
216 'one': 1
217 }
218 }.map_receiver_pattern_returns_existing_or_default('one', 0) == 1
219 value, extra := StringIntMapExpect{
220 value: {
221 'one': 1
222 }
223 }.map_receiver_pattern_pairs_with_method_generic[bool]('missing', 7, true)
224 assert value == 7
225 assert extra
226}
227
228fn test_alias_to_map_exact_generic_method_takes_precedence_over_structured_pattern() {
229 assert StringIntMapExpect{
230 value: {
231 'one': 1
232 }
233 }.same_name_map_exact_prefers_concrete('alias') == 'concrete'
234}
235
236fn test_alias_to_map_exact_method_takes_precedence_over_structured_pattern() {
237 assert StringIntMapExpect{
238 value: {
239 'one': 1
240 }
241 }.same_name_map_method() == 'concrete'
242}
243
244fn test_alias_receiver_exact_method_takes_precedence_over_structured_pattern() {
245 assert IntListExpect{
246 value: [1, 2, 3]
247 }.same_name_prefers_concrete_receiver() == 'concrete'
248 assert IntListExpect{
249 value: [1]
250 }.same_name_with_method_generic_prefers_concrete_receiver[string]('extra') == 'concrete'
251}
252
253fn test_mixed_direct_and_structured_receiver_pattern_method_generic() {
254 direct, item, marker := MixedReceiverPatternBox[int, []string]{
255 direct: 7
256 items: ['alpha']
257 }.mixed_receiver_pattern_values_with_method_generic[bool]('fallback', true)
258 assert direct == 7
259 assert item == 'alpha'
260 assert marker
261 inferred_direct, inferred_item, inferred_marker := MixedReceiverPatternBox[int, []string]{
262 direct: 9
263 items: []string{}
264 }.mixed_receiver_pattern_values_with_method_generic('fallback', 1.5)
265 assert inferred_direct == 9
266 assert inferred_item == 'fallback'
267 assert inferred_marker == 1.5
268}
269
270fn test_alias_to_mixed_receiver_pattern_binds_direct_and_structured_slots() {
271 direct, item, marker := MixedIntStringListBox{
272 direct: 7
273 items: ['alpha']
274 }.mixed_receiver_pattern_values_with_method_generic[bool]('fallback', true)
275 assert direct == 7
276 assert item == 'alpha'
277 assert marker
278 assert MixedIntStringListBox{
279 direct: 1
280 items: ['alpha']
281 }.same_name_with_method_generic_prefers_concrete_mixed_receiver[bool](true) == 'concrete'
282}
283
284fn test_exact_mixed_receiver_method_with_method_generic_takes_precedence_over_structured_pattern() {
285 assert MixedReceiverPatternBox[int, []string]{
286 direct: 1
287 items: ['alpha']
288 }.same_name_with_method_generic_prefers_concrete_mixed_receiver[bool](true) == 'concrete'
289 assert MixedReceiverPatternBox[int, []bool]{
290 direct: 1
291 items: [true]
292 }.same_name_with_method_generic_prefers_concrete_mixed_receiver[string]('marker') == 'pattern'
293}
294
295fn test_map_receiver_pattern_binds_nested_value_type() {
296 assert ReceiverPatternExpect[map[string]map[string]int]{
297 value: {
298 'outer': {
299 'inner': 7
300 }
301 }
302 }.map_receiver_pattern_returns_existing_or_default('outer', {
303 'default': 0
304 })['inner'] == 7
305}
306