v2 / vlib / v / checker / containers.v
1194 lines · 1162 sloc · 40.28 KB · 8b5f74e6a7b52c1100cb52ef2832fd0c090fb407
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
3module checker
4
5import v.ast
6import v.token
7
8@[inline]
9fn array_init_result_type(node ast.ArrayInit) ast.Type {
10 return if node.alias_type != 0 && node.alias_type != ast.void_type {
11 node.alias_type
12 } else {
13 node.typ
14 }
15}
16
17fn (mut c Checker) set_expected_array_literal_type(mut expr ast.Expr, expected_type ast.Type) {
18 if mut expr is ast.ArrayInit {
19 if expr.typ != ast.void_type || expr.elem_type != ast.void_type {
20 return
21 }
22 expected_array_type := expected_type.clear_option_and_result()
23 if expected_array_type.has_flag(.generic)
24 || c.type_has_unresolved_generic_parts(expected_array_type) {
25 return
26 }
27 mut concrete_array_type := expected_array_type
28 expected_sym := c.table.sym(expected_array_type)
29 if expected_sym.info is ast.Alias {
30 concrete_array_type = expected_sym.info.parent_type.clear_option_and_result()
31 if c.table.final_sym(concrete_array_type).kind !in [.array, .array_fixed] {
32 return
33 }
34 expr.alias_type = expected_array_type
35 } else if c.table.final_sym(expected_array_type).kind !in [.array, .array_fixed] {
36 return
37 }
38 expected_elem_type := c.table.value_type(concrete_array_type)
39 if expected_elem_type == ast.void_type {
40 return
41 }
42 expected_elem_sym := c.table.final_sym(expected_elem_type)
43 if expected_elem_sym.kind in [.interface, .sum_type] {
44 return
45 }
46 expr.typ = concrete_array_type
47 expr.elem_type = expected_elem_type
48 }
49}
50
51fn is_inferred_fixed_array_size_expr(expr ast.Expr) bool {
52 return expr is ast.RangeExpr && !expr.has_low && !expr.has_high
53}
54
55fn is_array_init_type_expr_field(name string) bool {
56 return name in ['idx', 'typ', 'unaliased_typ', 'key_type', 'value_type', 'element_type',
57 'pointee_type', 'payload_type', 'variant_types', 'indirections']
58}
59
60fn (mut c Checker) fixed_array_contains_inferred_size(typ ast.Type) bool {
61 mut current_type := typ.clear_option_and_result()
62 for {
63 current_sym := c.table.sym(current_type)
64 if current_sym.kind != .array_fixed {
65 return false
66 }
67 current_info := current_sym.array_fixed_info()
68 if is_inferred_fixed_array_size_expr(current_info.size_expr) {
69 return true
70 }
71 current_type = current_info.elem_type.clear_option_and_result()
72 }
73 return false
74}
75
76fn (mut c Checker) resolve_fixed_array_literal_type(typ ast.Type, elem_type ast.Type, expr_count int) ast.Type {
77 raw_typ := typ.clear_option_and_result()
78 sym := c.table.sym(raw_typ)
79 if sym.kind != .array_fixed {
80 return typ
81 }
82 info := sym.array_fixed_info()
83 mut fixed_size := info.size
84 mut size_expr := info.size_expr
85 if is_inferred_fixed_array_size_expr(size_expr) {
86 fixed_size = expr_count
87 size_expr = ast.empty_expr
88 } else if fixed_size <= 0 {
89 mut mutable_size_expr := size_expr
90 resolved_typ := c.eval_array_fixed_sizes(mut mutable_size_expr, fixed_size, elem_type)
91 resolved_info := c.table.sym(resolved_typ).array_fixed_info()
92 fixed_size = resolved_info.size
93 size_expr = resolved_info.size_expr
94 }
95 if fixed_size <= 0 {
96 c.error('fixed size cannot be zero or negative (fixed_size: ${fixed_size})',
97 size_expr.pos())
98 return typ
99 }
100 idx := c.table.find_or_register_array_fixed(elem_type, fixed_size, size_expr, info.is_fn_ret)
101 mut resolved_typ := ast.new_type(idx)
102 if typ.has_flag(.generic) || elem_type.has_flag(.generic) {
103 resolved_typ = resolved_typ.set_flag(.generic)
104 }
105 if typ.has_flag(.option) {
106 resolved_typ = resolved_typ.set_flag(.option)
107 }
108 return resolved_typ
109}
110
111fn (mut c Checker) array_init_elem_type_from_expr(expr ast.Expr) ast.Type {
112 match expr {
113 ast.ParExpr {
114 return c.array_init_elem_type_from_expr(expr.expr)
115 }
116 ast.TypeNode {
117 return c.unwrap_generic(expr.typ)
118 }
119 ast.TypeOf {
120 return c.unwrap_generic(c.type_resolver.typeof_type(expr.expr, expr.typ))
121 }
122 ast.SelectorExpr {
123 if expr.is_field_typ {
124 return c.unwrap_generic(c.type_resolver.get_type(expr))
125 }
126 if expr.name_type != 0 && is_array_init_type_expr_field(expr.field_name) {
127 return c.unwrap_generic(c.type_resolver.typeof_field_type(expr.name_type,
128 expr.field_name))
129 }
130 if is_array_init_type_expr_field(expr.field_name) {
131 base_type := c.array_init_elem_type_from_expr(expr.expr)
132 if base_type != ast.void_type {
133 return c.unwrap_generic(c.type_resolver.typeof_field_type(base_type,
134 expr.field_name))
135 }
136 }
137 return ast.void_type
138 }
139 else {
140 return ast.void_type
141 }
142 }
143}
144
145fn (mut c Checker) resolve_array_init_elem_type_expr(mut node ast.ArrayInit) {
146 if node.elem_type_expr is ast.EmptyExpr {
147 return
148 }
149 old_expected_type := c.expected_type
150 c.expected_type = ast.void_type
151 c.expr(mut node.elem_type_expr)
152 c.expected_type = old_expected_type
153 resolved_elem_type := c.array_init_elem_type_from_expr(node.elem_type_expr)
154 if resolved_elem_type == ast.void_type {
155 c.error('array_init: invalid comptime type expression, expected a type field such as `typeof(expr).idx` or `T.typ`',
156 node.elem_type_pos)
157 return
158 }
159 if resolved_elem_type.has_flag(.result) {
160 c.error('arrays do not support storing Result values', node.elem_type_pos)
161 return
162 }
163 node.elem_type = resolved_elem_type
164 idx := c.table.find_or_register_array(resolved_elem_type)
165 node.typ = if resolved_elem_type.has_flag(.generic)
166 || c.type_has_unresolved_generic_parts(resolved_elem_type) {
167 ast.new_type(idx).set_flag(.generic)
168 } else {
169 ast.new_type(idx)
170 }
171 if node.is_option {
172 node.typ = node.typ.set_flag(.option)
173 }
174}
175
176fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
177 is_inferred_array_literal := node.exprs.len > 0 && !node.is_fixed && !node.has_cap
178 && !node.has_len && !node.has_init && node.elem_type_pos.pos == node.pos.pos
179 && node.generic_typ == 0 && node.generic_elem_type == 0
180 if c.has_active_generic_recheck_context() {
181 is_untyped_empty_array := node.exprs.len == 0 && !node.is_fixed && !node.has_cap
182 && !node.has_len && !node.has_init && node.elem_type_pos.pos == node.pos.pos
183 if node.generic_typ == 0 && node.typ != ast.void_type
184 && (node.typ.has_flag(.generic) || c.type_has_unresolved_generic_parts(node.typ)) {
185 node.generic_typ = node.typ
186 }
187 if node.generic_elem_type == 0 && node.elem_type != ast.void_type
188 && (node.elem_type.has_flag(.generic)
189 || c.type_has_unresolved_generic_parts(node.elem_type)) {
190 node.generic_elem_type = node.elem_type
191 }
192 if (node.typ == ast.void_type || is_untyped_empty_array) && c.expected_type != ast.void_type {
193 expected_array_typ := c.recheck_concrete_type(c.expected_type.clear_option_and_result())
194 expected_array_sym := c.table.final_sym(expected_array_typ)
195 match expected_array_sym.info {
196 ast.Array {
197 node.typ = expected_array_typ
198 node.elem_type = expected_array_sym.info.elem_type
199 }
200 ast.ArrayFixed {
201 node.typ = expected_array_typ
202 node.elem_type = expected_array_sym.info.elem_type
203 }
204 else {}
205 }
206 }
207 base_node_typ := if node.generic_typ != 0 { node.generic_typ } else { node.typ }
208 base_elem_type := if node.generic_elem_type != 0 {
209 node.generic_elem_type
210 } else {
211 node.elem_type
212 }
213 if base_node_typ != ast.void_type {
214 resolved_node_typ := c.recheck_concrete_type(base_node_typ)
215 if resolved_node_typ != 0 && resolved_node_typ != ast.void_type {
216 node.typ = resolved_node_typ
217 }
218 }
219 if base_elem_type != ast.void_type {
220 resolved_elem_type := c.recheck_concrete_type(base_elem_type)
221 if resolved_elem_type != 0 && resolved_elem_type != ast.void_type {
222 node.elem_type = resolved_elem_type
223 }
224 }
225 }
226 if c.has_active_generic_recheck_context() && node.exprs.len > 0 && !node.is_fixed {
227 node.expr_types = []
228 node.init_type = ast.void_type
229 node.has_callexpr = false
230 if node.typ == ast.void_type || node.elem_type == ast.void_type || is_inferred_array_literal
231 || node.typ.has_flag(.generic) || c.type_has_unresolved_generic_parts(node.typ)
232 || node.elem_type.has_flag(.generic)
233 || c.type_has_unresolved_generic_parts(node.elem_type) {
234 node.typ = ast.void_type
235 node.elem_type = ast.void_type
236 }
237 }
238 if node.typ == ast.void_type && node.elem_type_expr !is ast.EmptyExpr {
239 c.resolve_array_init_elem_type_expr(mut node)
240 }
241 mut elem_type := ast.void_type
242 unwrap_elem_type := c.unwrap_generic(node.elem_type)
243 if node.typ.has_flag(.generic) {
244 c.table.used_features.comptime_syms[c.unwrap_generic(node.typ)] = true
245 }
246 if c.pref.warn_about_allocs {
247 c.warn_alloc('array initialization', node.pos)
248 }
249 // `x := []string{}` (the type was set in the parser)
250 if node.typ != ast.void_type {
251 if node.elem_type != 0 {
252 elem_sym := c.table.sym(node.elem_type)
253 c.check_any_type(node.elem_type, elem_sym, node.pos)
254 if node.typ.has_flag(.option) && (node.has_cap || node.has_len) {
255 c.error('Option array `${elem_sym.name}` cannot have initializers', node.pos)
256 }
257 match elem_sym.info {
258 ast.Struct {
259 if elem_sym.info.generic_types.len > 0 && elem_sym.info.concrete_types.len == 0
260 && !node.elem_type.has_flag(.generic) {
261 if c.table.cur_concrete_types.len == 0 {
262 c.error('generic struct `${elem_sym.name}` must specify type parameter, e.g. ${elem_sym.name}[int]',
263 node.elem_type_pos)
264 } else {
265 c.error('generic struct `${elem_sym.name}` must specify type parameter, e.g. ${elem_sym.name}[T]',
266 node.elem_type_pos)
267 }
268 }
269 }
270 ast.Interface {
271 if elem_sym.info.generic_types.len > 0 && elem_sym.info.concrete_types.len == 0
272 && !node.elem_type.has_flag(.generic) {
273 if c.table.cur_concrete_types.len == 0 {
274 c.error('generic interface `${elem_sym.name}` must specify type parameter, e.g. ${elem_sym.name}[int]',
275 node.elem_type_pos)
276 } else {
277 c.error('generic interface `${elem_sym.name}` must specify type parameter, e.g. ${elem_sym.name}[T]',
278 node.elem_type_pos)
279 }
280 }
281 }
282 ast.SumType {
283 if elem_sym.info.generic_types.len > 0 && elem_sym.info.concrete_types.len == 0
284 && !node.elem_type.has_flag(.generic) {
285 if c.table.cur_concrete_types.len == 0 {
286 c.error('generic sumtype `${elem_sym.name}` must specify type parameter, e.g. ${elem_sym.name}[int]',
287 node.elem_type_pos)
288 } else {
289 c.error('generic sumtype `${elem_sym.name}` must specify type parameter, e.g. ${elem_sym.name}[T]',
290 node.elem_type_pos)
291 }
292 }
293 }
294 ast.Alias {
295 if elem_sym.name == 'byte' {
296 c.error('byte is deprecated, use u8 instead', node.elem_type_pos)
297 }
298 }
299 ast.Map {
300 c.markused_array_method(!c.is_builtin_mod, 'map')
301 }
302 else {}
303 }
304 }
305 if node.exprs.len == 0 {
306 if node.has_cap {
307 c.check_array_init_para_type('cap', mut node.cap_expr, node.pos)
308 }
309 if node.has_len {
310 c.check_array_init_para_type('len', mut node.len_expr, node.pos)
311 }
312 }
313 if node.has_init {
314 c.check_array_init_default_expr(mut node)
315 }
316 if node.has_len {
317 len_typ := c.check_expr_option_or_result_call(node.len_expr, c.expr(mut node.len_expr))
318 if len_typ.has_flag(.option) {
319 c.error('cannot use unwrapped Option as length', node.len_expr.pos())
320 }
321 // check &int{}, interface, sum_type initialized
322 if !node.has_init {
323 c.check_elements_initialized(unwrap_elem_type) or {
324 c.warn('${err.msg()}, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)',
325 node.pos)
326 }
327 }
328 }
329 if node.has_cap {
330 cap_typ := c.check_expr_option_or_result_call(node.cap_expr, c.expr(mut node.cap_expr))
331 if cap_typ.has_flag(.option) {
332 c.error('cannot use unwrapped Option as capacity', node.cap_expr.pos())
333 }
334 }
335 c.ensure_type_exists(node.elem_type, node.elem_type_pos)
336 if node.typ.has_flag(.generic) && c.table.cur_fn != unsafe { nil }
337 && c.table.cur_fn.generic_names.len == 0 {
338 c.error('generic struct cannot be used in non-generic function', node.pos)
339 }
340
341 // `&Struct{} check
342 if node.has_len {
343 c.check_elements_ref_fields_initialized(unwrap_elem_type, node.pos)
344 }
345 // T{0} initialization when T is an array
346 if node.is_fixed && node.has_val && node.expr_types.len == 0 {
347 if c.table.final_sym(node.elem_type).kind == .array_fixed {
348 elem_info := c.table.final_sym(node.elem_type).array_fixed_info()
349 if c.array_fixed_has_unresolved_size(elem_info)
350 && !c.fixed_array_contains_inferred_size(node.elem_type) {
351 node.elem_type = c.resolve_fixed_array_literal_type(node.elem_type,
352 elem_info.elem_type, 0)
353 }
354 }
355 mut expected_elem_type := node.elem_type
356 mut should_infer_fixed_elem_type :=
357 c.table.final_sym(expected_elem_type).kind == .array_fixed
358 && c.fixed_array_contains_inferred_size(expected_elem_type)
359 for i, mut expr in node.exprs {
360 old_expected_type := c.expected_type
361 if should_infer_fixed_elem_type && i == 0 {
362 c.expected_type = ast.void_type
363 } else {
364 c.expected_type = expected_elem_type
365 }
366 mut typ := c.check_expr_option_or_result_call(expr, c.expr(mut expr))
367 c.expected_type = old_expected_type
368 if expr is ast.CallExpr {
369 ret_sym := c.table.sym(typ)
370 if ret_sym.kind == .array_fixed {
371 typ = c.cast_fixed_array_ret(typ, ret_sym)
372 }
373 node.has_callexpr = true
374 }
375 if should_infer_fixed_elem_type && i == 0
376 && c.table.final_sym(typ).kind == .array_fixed {
377 expected_elem_type = typ
378 node.elem_type = typ
379 should_infer_fixed_elem_type = false
380 }
381 c.check_expected(typ, expected_elem_type) or {
382 c.error('invalid array element: ${err.msg()}', expr.pos())
383 }
384 node.expr_types << typ
385 }
386 node.typ = c.resolve_fixed_array_literal_type(node.typ, node.elem_type, node.exprs.len)
387 resolved_info := c.table.sym(node.typ.clear_option_and_result()).array_fixed_info()
388 if resolved_info.size != node.exprs.len {
389 c.error('fixed array expects ${resolved_info.size} value(s), but got ${node.exprs.len}',
390 node.pos)
391 }
392 } else if !node.is_fixed && node.expr_types.len == 0 {
393 for mut expr in node.exprs {
394 typ := c.expr(mut expr)
395 c.check_expected(typ, node.elem_type) or {
396 c.error('invalid array element: ${err.msg()}', expr.pos())
397 }
398 node.expr_types << typ
399 }
400 }
401 // Resolve generic array type to concrete when inside generic function
402 if node.typ.has_flag(.generic) && c.table.cur_fn != unsafe { nil } {
403 resolved := c.recheck_concrete_type(node.typ)
404 if resolved != node.typ && !resolved.has_flag(.generic) {
405 return if node.alias_type != ast.void_type { node.alias_type } else { resolved }
406 }
407 }
408 return array_init_result_type(node)
409 }
410
411 if node.is_fixed {
412 c.ensure_type_exists(node.elem_type, node.elem_type_pos)
413 if !c.is_builtin_mod {
414 c.check_elements_initialized(unwrap_elem_type) or {
415 c.warn('fixed ${err.msg()} (unless inside `unsafe`)', node.pos)
416 }
417 }
418 c.check_elements_ref_fields_initialized(unwrap_elem_type, node.pos)
419 }
420 // `a = []`
421 if node.exprs.len == 0 {
422 // `a := fn_returning_opt_array() or { [] }`
423 if c.expected_type == ast.void_type {
424 if c.expected_or_type != ast.void_type {
425 c.expected_type = c.expected_or_type
426 } else if c.expected_expr_type != ast.void_type {
427 c.expected_type = c.expected_expr_type
428 }
429 }
430 mut type_sym := c.table.sym(c.expected_type)
431 if type_sym.kind != .array || type_sym.array_info().elem_type == ast.void_type {
432 c.error('array_init: no type specified (maybe: `[]Type{}` instead of `[]`)', node.pos)
433 return ast.void_type
434 }
435 array_info := type_sym.array_info()
436 node.elem_type = array_info.elem_type
437 // clear option flag in case of: `fn opt_arr() ?[]int { return [] }`
438 return if c.expected_type.has_flag(.shared_f) {
439 c.expected_type.clear_flag(.shared_f).deref()
440 } else {
441 c.expected_type
442 }.clear_option_and_result()
443 }
444 // `[1,2,3]`
445 if node.exprs.len > 0 && node.elem_type == ast.void_type {
446 mut expected_value_type := ast.void_type
447 mut expecting_interface_array := false
448 mut expecting_sumtype_array := false
449 mut is_first_elem_ptr := false
450 if c.expected_type != 0 {
451 expected_value_type = c.table.value_type(c.expected_type)
452 expected_value_sym := c.table.sym(expected_value_type)
453 if expected_value_sym.kind == .interface {
454 // array of interfaces? (`[dog, cat]`) Save the interface type (`Animal`)
455 expecting_interface_array = true
456 } else if expected_value_sym.kind == .sum_type {
457 expecting_sumtype_array = true
458 }
459 }
460 for i, mut expr in node.exprs {
461 mut typ := ast.void_type
462 expr_pos := expr.pos()
463 is_array_init := expr is ast.ArrayInit
464 if is_array_init {
465 old_expected_type := c.expected_type
466 c.expected_type = c.table.value_type(c.expected_type)
467 mut expr_copy := expr
468 typ = c.check_expr_option_or_result_call(expr_copy, c.expr(mut expr_copy))
469 expr = expr_copy
470 c.expected_type = old_expected_type
471 } else {
472 // [none]
473 if c.expected_type == ast.none_type && expr is ast.None {
474 c.error('invalid expression `none`, it is not an array of Option type',
475 expr_pos)
476 continue
477 }
478 typ = c.check_expr_option_or_result_call(expr, c.expr(mut expr))
479 sym := c.table.sym(expected_value_type)
480 if sym.kind == .interface {
481 c.type_implements(typ, expected_value_type, expr.pos())
482 }
483 }
484 if expr is ast.CallExpr {
485 ret_sym := c.table.sym(typ)
486 if ret_sym.kind == .array_fixed {
487 typ = c.cast_fixed_array_ret(typ, ret_sym)
488 }
489 node.has_callexpr = true
490 }
491 if typ == ast.void_type {
492 c.error('invalid void array element type', expr.pos())
493 }
494 node.expr_types << typ
495 // the first element's type
496 if expecting_interface_array {
497 if i == 0 {
498 elem_type = expected_value_type
499 c.expected_type = elem_type
500 c.type_implements(typ, elem_type, expr.pos())
501 }
502 if !typ.is_any_kind_of_pointer() && !c.inside_unsafe {
503 typ_sym := c.table.sym(typ)
504 if typ_sym.kind != .interface {
505 c.mark_as_referenced(mut &node.exprs[i], true)
506 }
507 }
508 continue
509 } else if expecting_sumtype_array {
510 if i == 0 {
511 if c.table.is_sumtype_or_in_variant(expected_value_type, ast.mktyp(typ)) {
512 elem_type = expected_value_type
513 } else {
514 if expr.is_auto_deref_var() {
515 elem_type = ast.mktyp(typ.deref())
516 } else {
517 elem_type = ast.mktyp(typ)
518 }
519 }
520 c.expected_type = elem_type
521 }
522 continue
523 }
524 // the first element's type
525 if i == 0 {
526 if expr.is_auto_deref_var() {
527 elem_type = ast.mktyp(typ.deref())
528 } else {
529 elem_type = ast.mktyp(typ)
530 }
531 if typ.is_ptr() && c.in_for_count == 0 {
532 is_first_elem_ptr = true
533 }
534 c.expected_type = elem_type
535 continue
536 } else {
537 if !typ.is_any_kind_of_pointer() && !typ.is_int() && is_first_elem_ptr {
538 c.error('cannot have non-pointer of type `${c.table.type_to_str(typ)}` in a pointer array of type `${c.table.type_to_str(elem_type)}`',
539 expr.pos())
540 }
541 }
542 if expr !is ast.TypeNode {
543 if c.table.type_kind(elem_type) == .interface {
544 if c.type_implements(typ, elem_type, expr.pos()) {
545 continue
546 }
547 }
548 c.check_expected(typ, elem_type) or {
549 c.error('invalid array element: ${err.msg()}', expr.pos())
550 }
551 if !elem_type.has_flag(.option)
552 && (typ.has_flag(.option) || typ.idx() == ast.none_type_idx) {
553 typ_str, elem_type_str := c.get_string_names_of(typ, elem_type)
554 if typ.idx() == ast.none_type_idx {
555 c.error('cannot use `${typ_str}` as `${elem_type_str}`', expr.pos())
556 } else {
557 c.error('cannot use `${typ_str}` as `${elem_type_str}`, it must be unwrapped first',
558 expr.pos())
559 }
560 } else if elem_type.has_flag(.option) && !typ.has_flag(.option)
561 && typ.idx() != ast.none_type_idx && !expr.is_pure_literal() {
562 typ_str, elem_type_str := c.get_string_names_of(typ, elem_type)
563 c.error('cannot use `${typ_str}` as `${elem_type_str}`', expr.pos())
564 }
565 }
566 }
567 if node.is_fixed {
568 idx := c.table.find_or_register_array_fixed(elem_type, node.exprs.len, ast.empty_expr,
569 false)
570 if elem_type.has_flag(.generic) {
571 node.typ = ast.new_type(idx).set_flag(.generic)
572 } else {
573 node.typ = ast.new_type(idx)
574 }
575 } else {
576 idx := c.table.find_or_register_array(elem_type)
577 if elem_type.has_flag(.generic) {
578 node.typ = ast.new_type(idx).set_flag(.generic)
579 } else {
580 node.typ = ast.new_type(idx)
581 }
582 }
583 node.elem_type = elem_type
584 } else if node.is_fixed && node.exprs.len == 1 && node.elem_type != ast.void_type {
585 // `[50]u8`
586 sym := c.table.sym(node.typ)
587 if sym.info !is ast.ArrayFixed
588 || c.array_fixed_has_unresolved_size(sym.info as ast.ArrayFixed) {
589 mut size_expr := node.exprs[0]
590 node.typ = c.eval_array_fixed_sizes(mut size_expr, 0, node.elem_type)
591 if node.is_option {
592 node.typ = node.typ.set_flag(.option)
593 }
594 node.elem_type = (c.table.sym(node.typ).info as ast.ArrayFixed).elem_type
595 }
596 if node.has_init {
597 c.check_array_init_default_expr(mut node)
598 }
599 }
600 return array_init_result_type(node)
601}
602
603fn (mut c Checker) check_array_init_default_expr(mut node ast.ArrayInit) {
604 mut init_expr := node.init_expr
605 mut expected_elem_type := node.elem_type
606 if node.elem_type.has_flag(.generic) && c.table.cur_fn != unsafe { nil } {
607 generic_names := c.effective_fn_generic_names(c.table.cur_fn)
608 if generic_names.len > 0 && c.table.cur_concrete_types.len == generic_names.len {
609 expected_elem_type = c.table.unwrap_generic_type(node.elem_type, generic_names,
610 c.table.cur_concrete_types)
611 }
612 }
613 c.expected_type = expected_elem_type
614 init_typ := c.check_expr_option_or_result_call(init_expr, c.expr(mut init_expr))
615 node.init_type = init_typ
616 if !expected_elem_type.has_flag(.option) && init_typ.has_flag(.option) {
617 c.error('cannot use unwrapped Option as initializer', init_expr.pos())
618 }
619 if expected_elem_type.is_number() && init_typ.is_number() {
620 return
621 }
622 if c.table.type_kind(expected_elem_type) == .interface {
623 if c.type_implements(init_typ, expected_elem_type, init_expr.pos()) {
624 return
625 }
626 }
627 c.check_expected(init_typ, expected_elem_type) or { c.error(err.msg(), init_expr.pos()) }
628}
629
630fn (mut c Checker) check_array_init_para_type(para string, mut expr ast.Expr, pos token.Pos) {
631 sym := c.table.final_sym(c.unwrap_generic(c.expr(mut expr)))
632 $if new_int ? && x64 {
633 if sym.kind !in [.int, .int_literal, .i64, .i32, .i16, .i8] {
634 c.error('array ${para} needs to be an int/i64/i32/i16/i8', pos)
635 }
636 } $else {
637 if sym.kind !in [.int, .int_literal, .i32, .i16, .i8] {
638 c.error('array ${para} needs to be an int/i32/i16/i8', pos)
639 }
640 }
641 if expr is ast.IntegerLiteral {
642 lit := expr as ast.IntegerLiteral
643 if lit.val.int() < 0 {
644 c.error('array ${para} can not be negative', lit.pos)
645 }
646 }
647}
648
649// When the fixed array has multiple dimensions, it needs to be evaluated recursively.
650// `[const]int`, `[const][3]int`, `[3][const]int`, `[const + 1][3][const]int`...
651fn (mut c Checker) eval_array_fixed_sizes(mut size_expr ast.Expr, size int, elem_type ast.Type) ast.Type {
652 elem_sym := c.table.sym(elem_type)
653 elem_info := elem_sym.info
654
655 new_elem_typ := if elem_sym.kind == .array_fixed {
656 mut info := elem_info as ast.ArrayFixed
657 mut elem_size_expr := unsafe { info.size_expr }
658 c.eval_array_fixed_sizes(mut elem_size_expr, info.size, info.elem_type)
659 } else {
660 elem_type
661 }
662
663 mut fixed_size := i64(size)
664 if fixed_size <= 0 {
665 c.expr(mut size_expr)
666 match mut size_expr {
667 ast.IntegerLiteral {
668 fixed_size = size_expr.val.int()
669 }
670 ast.ComptimeCall {
671 if size_expr.kind == .d {
672 size_expr.resolve_compile_value(c.pref.compile_values) or {
673 c.error(err.msg(), size_expr.pos)
674 }
675 if size_expr.result_type != ast.i64_type {
676 c.error('value from \$d() can only be positive integers when used as fixed size',
677 size_expr.pos)
678 }
679 fixed_size = size_expr.compile_value.int()
680 } else {
681 c.error('only \$d() can be used for fixed size arrays', size_expr.pos)
682 }
683 }
684 ast.CastExpr {
685 if !size_expr.typ.is_pure_int() {
686 c.error('only integer types are allowed', size_expr.pos)
687 }
688 match mut size_expr.expr {
689 ast.IntegerLiteral {
690 fixed_size = size_expr.expr.val.int()
691 }
692 ast.FloatLiteral {
693 fixed_size = int(size_expr.expr.val.f64())
694 }
695 ast.EnumVal {
696 if val := c.table.find_enum_field_val(size_expr.expr.enum_name,
697 size_expr.expr.val)
698 {
699 fixed_size = val
700 }
701 }
702 else {}
703 }
704 }
705 ast.EnumVal {
706 c.error('${size_expr.enum_name}.${size_expr.val} has to be casted to integer to be used as size',
707 size_expr.pos)
708 }
709 ast.Ident {
710 if mut size_expr.obj is ast.ConstField {
711 if mut size_expr.obj.expr is ast.EnumVal {
712 c.error('${size_expr.obj.expr.enum_name}.${size_expr.obj.expr.val} has to be casted to integer to be used as size',
713 size_expr.pos)
714 }
715 if mut size_expr.obj.expr is ast.CastExpr {
716 if !size_expr.obj.expr.typ.is_pure_int() {
717 c.error('only integer types are allowed', size_expr.pos)
718 }
719 if size_expr.obj.expr.expr is ast.IntegerLiteral {
720 if comptime_value := c.eval_comptime_const_expr(size_expr.obj.expr.expr,
721 0)
722 {
723 fixed_size = comptime_value.i64() or { fixed_size }
724 }
725 }
726 if size_expr.obj.expr.expr is ast.InfixExpr {
727 if comptime_value := c.eval_comptime_const_expr(size_expr.obj.expr.expr,
728 0)
729 {
730 fixed_size = comptime_value.i64() or { fixed_size }
731 }
732 }
733 }
734 if comptime_value := c.eval_comptime_const_expr(size_expr.obj.expr, 0) {
735 fixed_size = comptime_value.i64() or { fixed_size }
736 }
737 } else {
738 c.error('non-constant array bound `${size_expr.name}`', size_expr.pos)
739 }
740 }
741 ast.InfixExpr {
742 if comptime_value := c.eval_comptime_const_expr(size_expr, 0) {
743 fixed_size = comptime_value.i64() or { fixed_size }
744 }
745 }
746 else {
747 c.error('fixed array size cannot use non-constant value', size_expr.pos())
748 }
749 }
750
751 if fixed_size <= 0 {
752 c.error('fixed size cannot be zero or negative (fixed_size: ${fixed_size})',
753 size_expr.pos())
754 }
755 }
756
757 idx := c.table.find_or_register_array_fixed(new_elem_typ, int(fixed_size), size_expr, false)
758 return if elem_type.has_flag(.generic) {
759 ast.new_type(idx).set_flag(.generic)
760 } else {
761 ast.new_type(idx)
762 }
763}
764
765fn (mut c Checker) array_fixed_has_unresolved_size(info &ast.ArrayFixed) bool {
766 if info.size <= 0 {
767 return true
768 }
769 mut elem_type := info.elem_type
770 mut elem_sym := c.table.sym(elem_type)
771 for {
772 if mut elem_sym.info is ast.ArrayFixed {
773 if elem_sym.info.size <= 0 {
774 return true
775 }
776 elem_type = elem_sym.info.elem_type
777 elem_sym = c.table.sym(elem_type)
778 } else {
779 break
780 }
781 }
782 return false
783}
784
785fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
786 if c.table.cur_fn != unsafe { nil } && c.table.cur_concrete_types.len > 0 && node.typ != 0
787 && c.expected_type != ast.void_type {
788 expected_map_type := c.expected_type.clear_option_and_result()
789 if c.table.sym(expected_map_type).kind == .map && node.typ != expected_map_type
790 && !expected_map_type.has_flag(.generic) {
791 node.typ = expected_map_type
792 node.key_type = 0
793 node.value_type = 0
794 }
795 }
796 // `map = {}`
797 if node.keys.len == 0 && node.vals.len == 0 && !node.has_update_expr && node.typ == 0 {
798 sym := c.table.sym(c.expected_type)
799 if sym.kind == .map {
800 info := sym.map_info()
801 node.typ = c.expected_type.clear_option_and_result()
802 node.key_type = info.key_type
803 node.value_type = info.value_type
804 return node.typ
805 } else if sym.info is ast.Struct {
806 msg := if sym.info.is_anon {
807 '`{}` cannot be used to initialize anonymous structs. Use `struct{}` instead.'
808 } else {
809 '`{}` can not be used for initialising empty structs any more. Use `${c.table.type_to_str(c.expected_type)}{}` instead.'
810 }
811 c.error(msg, node.pos)
812 if sym.info.is_anon {
813 return c.expected_type
814 }
815 } else {
816 c.error('invalid empty map initialisation syntax, use e.g. map[string]int{} instead',
817 node.pos)
818 }
819 return ast.void_type
820 }
821 // `x := map[string]string` - set in parser
822 if node.typ != 0 {
823 info := c.table.sym(node.typ).map_info()
824 start_errors := c.nr_errors
825 if node.typ.has_flag(.generic) {
826 c.table.used_features.comptime_syms[c.unwrap_generic(node.typ)] = true
827 }
828 if info.value_type != 0 {
829 if info.value_type.has_flag(.result) {
830 c.error('cannot use Result type as map value type', node.pos)
831 }
832 val_sym := c.table.sym(info.value_type)
833 if val_sym.kind == .struct {
834 val_info := val_sym.info as ast.Struct
835 if val_info.generic_types.len > 0 && val_info.concrete_types.len == 0
836 && !info.value_type.has_flag(.generic) {
837 if c.table.cur_concrete_types.len == 0 {
838 c.error('generic struct `${val_sym.name}` must specify type parameter, e.g. ${val_sym.name}[int]',
839 node.pos)
840 } else {
841 c.error('generic struct `${val_sym.name}` must specify type parameter, e.g. ${val_sym.name}[T]',
842 node.pos)
843 }
844 }
845 } else if val_sym.info is ast.FnType {
846 for param in val_sym.info.func.params {
847 if param.typ.has_flag(.result) {
848 c.error('result type arguments are not supported', node.pos)
849 }
850 }
851 }
852 }
853 c.ensure_type_exists(info.key_type, node.pos)
854 c.ensure_type_exists(info.value_type, node.pos)
855 node.key_type = info.key_type
856 node.value_type = info.value_type
857 if (c.table.sym(info.key_type).language == .v && info.key_type == ast.any_type)
858 || (c.table.sym(info.value_type).language == .v && info.value_type == ast.any_type) {
859 c.note('the `any` type is deprecated and will be removed soon - either use an empty interface, or a sum type',
860 node.pos)
861 c.error('cannot use type `any` here', node.pos)
862 }
863 needs_explicit_key_check := c.expected_type == ast.void_type
864 || c.expected_type.clear_option_and_result() != node.typ
865 if needs_explicit_key_check && c.nr_errors == start_errors && info.key_type != ast.void_type
866 && !info.key_type.has_flag(.generic) && !c.table.supports_map_key_type(info.key_type) {
867 c.error('map key type `${c.table.sym(info.key_type).name}` not supported', node.pos)
868 }
869 return node.typ
870 }
871
872 if (node.keys.len > 0 && node.vals.len > 0) || node.has_update_expr {
873 mut map_type := ast.void_type
874 start_errors := c.nr_errors
875 use_expected_type := c.expected_type != ast.void_type && !c.inside_const
876 && c.table.sym(c.expected_type).kind == .map && !(c.inside_fn_arg
877 && c.expected_type.has_flag(.generic))
878 if use_expected_type {
879 map_type = c.expected_type
880 }
881 if node.has_update_expr {
882 update_type := c.expr(mut node.update_expr)
883 if map_type != ast.void_type {
884 if update_type != map_type {
885 msg := c.expected_msg(update_type, map_type)
886 c.error('invalid map update: ${msg}', node.update_expr_pos)
887 }
888 } else if c.table.sym(update_type).kind != .map {
889 c.error('invalid map update: non-map type', node.update_expr_pos)
890 } else {
891 map_type = update_type
892 }
893 }
894
895 mut map_key_type := ast.void_type
896 mut map_val_type := ast.void_type
897 if map_type != ast.void_type {
898 sym := c.table.sym(map_type)
899 info := sym.map_info()
900 map_key_type = info.key_type
901 map_val_type = info.value_type
902 } else if node.keys.len > 0 {
903 // `{'age': 20}`
904 mut key_ := node.keys[0]
905 map_key_type = ast.mktyp(c.expr(mut key_))
906 if node.keys[0].is_auto_deref_var() {
907 map_key_type = map_key_type.deref()
908 }
909 mut val_ := node.vals[0]
910 map_val_type = ast.mktyp(c.expr(mut val_))
911 if node.vals[0].is_auto_deref_var() {
912 map_val_type = map_val_type.deref()
913 }
914 node.val_types << map_val_type
915 if node.keys.len == 1 && map_val_type == ast.none_type {
916 c.error('map value cannot be only `none`', node.vals[0].pos())
917 }
918 c.check_expr_option_or_result_call(key_, map_key_type)
919 c.check_expr_option_or_result_call(val_, map_val_type)
920 }
921 map_key_type = c.unwrap_generic(map_key_type)
922 map_val_type = c.unwrap_generic(map_val_type)
923 if c.nr_errors == start_errors && map_key_type != ast.void_type
924 && !map_key_type.has_flag(.generic) && !c.table.supports_map_key_type(map_key_type) {
925 c.error('map key type `${c.table.sym(map_key_type).name}` not supported', node.pos)
926 }
927
928 node.typ = ast.new_type(c.table.find_or_register_map(map_key_type, map_val_type))
929 node.key_type = map_key_type
930 node.value_type = map_val_type
931
932 map_value_sym := c.table.sym(map_val_type)
933 expecting_interface_map := map_value_sym.kind == .interface
934 mut same_key_type := true
935 for i, mut key in node.keys {
936 if i == 0 && map_type == ast.void_type {
937 continue // skip first key/value if we processed them above
938 }
939 mut val := node.vals[i]
940 c.expected_type = map_key_type
941 key_type := c.expr(mut key)
942 c.expected_type = map_val_type
943 c.set_expected_array_literal_type(mut val, map_val_type)
944 val_type := c.expr(mut val)
945 node.val_types << val_type
946 val_type_sym := c.table.sym(val_type)
947 c.check_expr_option_or_result_call(key, key_type)
948 c.check_expr_option_or_result_call(val, val_type)
949 if !c.check_types(key_type, map_key_type)
950 || (i == 0 && key_type.is_number() && map_key_type.is_number()
951 && map_key_type != ast.mktyp(key_type)) {
952 msg := c.expected_msg(key_type, map_key_type)
953 c.error('invalid map key: ${msg}', key.pos())
954 same_key_type = false
955 }
956 if expecting_interface_map {
957 if val_type == map_val_type {
958 continue
959 }
960 if val_type_sym.kind == .struct
961 && c.type_implements(val_type, map_val_type, val.pos()) {
962 node.vals[i] = ast.CastExpr{
963 expr: val
964 typname: c.table.get_type_name(map_val_type)
965 typ: map_val_type
966 expr_type: val_type
967 pos: val.pos()
968 }
969 continue
970 } else {
971 msg := c.expected_msg(val_type, map_val_type)
972 c.error('invalid map value: ${msg}', val.pos())
973 }
974 }
975 if val_type == ast.none_type && map_val_type.has_flag(.option) {
976 continue
977 }
978 if !c.check_types(val_type, map_val_type)
979 || map_val_type.has_flag(.option) != val_type.has_flag(.option)
980 || (i == 0 && val_type.is_number() && map_val_type.is_number()
981 && map_val_type != ast.mktyp(val_type)) {
982 msg := c.expected_msg(val_type, map_val_type)
983 c.error('invalid map value: ${msg}', val.pos())
984 }
985 }
986 if same_key_type {
987 for i in 1 .. node.keys.len {
988 c.check_dup_keys(node, i)
989 }
990 }
991 }
992 return node.typ
993}
994
995// check the element, and its children for ref uninitialized fields
996fn (mut c Checker) check_elements_ref_fields_initialized(typ ast.Type, pos &token.Pos) {
997 if typ == 0 || c.inside_const {
998 return
999 }
1000 sym := c.table.sym(typ)
1001 mut checked_types := []ast.Type{}
1002 c.do_check_elements_ref_fields_initialized(sym, mut checked_types, pos)
1003}
1004
1005// Recursively check the element, and its children for ref uninitialized fields
1006fn (mut c Checker) do_check_elements_ref_fields_initialized(sym &ast.TypeSymbol, mut checked_types []ast.Type,
1007 pos &token.Pos) {
1008 if sym.info is ast.Struct {
1009 linked_name := sym.name
1010 // For now, let's call this method and give a notice instead of an error.
1011 // After some time, we remove the check_ref_fields_initialized_note() method and
1012 // simply call check_ref_fields_initialized()
1013 c.check_ref_fields_initialized_note(sym, mut checked_types, linked_name, pos)
1014 return
1015 }
1016 match sym.info {
1017 ast.Array {
1018 elem_type := sym.info.elem_type
1019 if elem_type in checked_types {
1020 return
1021 }
1022 checked_types << elem_type
1023 elem_sym := c.table.sym(elem_type)
1024 c.do_check_elements_ref_fields_initialized(elem_sym, mut checked_types, pos)
1025 }
1026 ast.ArrayFixed {
1027 elem_type := sym.info.elem_type
1028 if elem_type in checked_types {
1029 return
1030 }
1031 checked_types << elem_type
1032 elem_sym := c.table.sym(elem_type)
1033 c.do_check_elements_ref_fields_initialized(elem_sym, mut checked_types, pos)
1034 }
1035 ast.Map {
1036 key_type := sym.info.key_type
1037 if key_type in checked_types {
1038 return
1039 }
1040 checked_types << key_type
1041 key_sym := c.table.sym(key_type)
1042 c.do_check_elements_ref_fields_initialized(key_sym, mut checked_types, pos)
1043 value_type := sym.info.value_type
1044 if value_type in checked_types {
1045 return
1046 }
1047 checked_types << value_type
1048 value_sym := c.table.sym(value_type)
1049 c.do_check_elements_ref_fields_initialized(value_sym, mut checked_types, pos)
1050 }
1051 ast.Alias {
1052 parent_type := sym.info.parent_type
1053 if parent_type in checked_types {
1054 return
1055 }
1056 checked_types << parent_type
1057 parent_sym := c.table.sym(parent_type)
1058 c.do_check_elements_ref_fields_initialized(parent_sym, mut checked_types, pos)
1059 }
1060 else {}
1061 }
1062}
1063
1064const err_ref_uninitialized = error('arrays of references need to be initialized right away')
1065const err_interface_uninitialized = error('arrays of interfaces need to be initialized right away')
1066const err_sumtype_uninitialized = error('arrays of sumtypes need to be initialized right away')
1067
1068// check the element, and its children for `ref/interface/sumtype` initialized
1069fn (mut c Checker) check_elements_initialized(typ ast.Type) ! {
1070 if typ == 0 || c.inside_unsafe {
1071 return
1072 }
1073 if typ.is_any_kind_of_pointer() {
1074 if !c.pref.translated && !c.file.is_translated {
1075 return err_ref_uninitialized
1076 } else {
1077 return
1078 }
1079 }
1080 sym := c.table.sym(typ)
1081 if sym.kind == .interface {
1082 return err_interface_uninitialized
1083 } else if sym.kind == .sum_type {
1084 return err_sumtype_uninitialized
1085 }
1086
1087 match sym.info {
1088 ast.Array {
1089 elem_type := sym.info.elem_type
1090 return c.check_elements_initialized(elem_type)
1091 }
1092 ast.ArrayFixed {
1093 elem_type := sym.info.elem_type
1094 if !c.is_builtin_mod {
1095 return c.check_elements_initialized(elem_type)
1096 }
1097 }
1098 ast.Map {
1099 value_type := sym.info.value_type
1100 if !c.is_builtin_mod {
1101 return c.check_elements_initialized(value_type)
1102 }
1103 }
1104 ast.Alias {
1105 parent_type := sym.info.parent_type
1106 return c.check_elements_initialized(parent_type)
1107 }
1108 else {}
1109 }
1110}
1111
1112fn (mut c Checker) check_append(mut node ast.InfixExpr, left_type ast.Type, right_type ast.Type,
1113 right_final_sym ast.TypeSymbol) ast.Type {
1114 if !node.is_stmt {
1115 c.error('array append cannot be used in an expression', node.pos)
1116 }
1117 mut right_sym := c.table.sym(right_type)
1118 mut left_sym := c.table.sym(left_type)
1119 if left_type.has_flag(.option) && node.left is ast.Ident && node.left.or_expr.kind == .absent {
1120 c.check_option_infix_expr(mut node, left_type, right_type, left_sym, right_sym)
1121 }
1122 right_pos := node.right.pos()
1123 // `array << elm`
1124 c.check_expr_option_or_result_call(node.right, right_type)
1125 node.auto_locked, _ = c.fail_if_immutable(mut node.left)
1126 left_value_type := c.table.value_type(c.unwrap_generic(left_type))
1127 left_value_sym := c.table.sym(c.unwrap_generic(left_value_type))
1128 if !left_value_type.has_flag(.option) && right_type.has_flag(.option) {
1129 c.error('unwrapped Option cannot be used in an infix expression', node.pos)
1130 }
1131
1132 right := node.right
1133 if right is ast.PrefixExpr && right.op == .amp {
1134 mut expr2 := right.right
1135 if mut expr2 is ast.Ident && !node.left.is_blank_ident() && expr2.obj is ast.ConstField {
1136 c.error('cannot have mutable reference to const `${expr2.name}`', expr2.pos)
1137 }
1138 }
1139 if left_value_sym.kind == .interface {
1140 if right is ast.ArrayInit && right.is_fixed {
1141 c.error('cannot append `${right_sym.name}` to `${left_sym.name}`', right_pos)
1142 return ast.void_type
1143 }
1144 right_is_interface_value := c.table.does_type_implement_interface(c.unwrap_generic(right_type),
1145 left_value_type)
1146 if right_is_interface_value {
1147 if !right_type.is_any_kind_of_pointer() && !c.inside_unsafe
1148 && right_sym.kind != .interface {
1149 c.mark_as_referenced(mut &node.right, true)
1150 }
1151 } else if right_final_sym.kind == .array {
1152 // []Animal << []Cat
1153 c.type_implements(c.table.value_type(right_type), left_value_type, right_pos)
1154 } else {
1155 // []Animal << Cat
1156 if c.type_implements(right_type, left_value_type, right_pos) {
1157 if !right_type.is_any_kind_of_pointer() && !c.inside_unsafe
1158 && right_sym.kind != .interface {
1159 c.mark_as_referenced(mut &node.right, true)
1160 }
1161 }
1162 }
1163 return ast.void_type
1164 } else if left_value_sym.kind == .sum_type {
1165 base_right_type := c.unwrap_generic(right_type)
1166 if c.check_types(base_right_type, left_value_type) {
1167 return ast.void_type
1168 }
1169 if right_sym.kind == .array {
1170 right_value_type := c.table.value_type(base_right_type)
1171 if c.check_types(right_value_type, left_value_type) {
1172 return ast.void_type
1173 }
1174 }
1175 c.error('cannot append `${right_sym.name}` to `${left_sym.name}`', right_pos)
1176 return ast.void_type
1177 }
1178 // []T << T or []T << []T
1179 unwrapped_right_type := c.unwrap_generic(right_type)
1180 if c.check_types(unwrapped_right_type, left_value_type) {
1181 // []&T << T is wrong: we check for that, !(T.is_ptr()) && ?(&T).is_ptr()
1182 if !(!unwrapped_right_type.is_ptr() && left_value_type.is_ptr()
1183 && left_value_type.share() == .mut_t) {
1184 return ast.void_type
1185 }
1186 } else if c.check_types(unwrapped_right_type, c.unwrap_generic(left_type)) {
1187 return ast.void_type
1188 }
1189 if left_value_type.has_flag(.option) && right_type == ast.none_type {
1190 return ast.void_type
1191 }
1192 c.error('cannot append `${right_sym.name}` to `${left_sym.name}`', right_pos)
1193 return ast.void_type
1194}
1195