mirror of
https://github.com/vlang/v.git
synced 2025-09-14 09:56:16 -04:00
checker: fix and cleanup uninitialized checks for array initialisers with len:
(fix #20272) (#20279)
This commit is contained in:
parent
5b96d8d179
commit
2dce525d90
@ -7,6 +7,7 @@ import v.token
|
||||
|
||||
fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||
mut elem_type := ast.void_type
|
||||
unwrap_elem_type := c.unwrap_generic(node.elem_type)
|
||||
// `x := []string{}` (the type was set in the parser)
|
||||
if node.typ != ast.void_type {
|
||||
if node.elem_type != 0 {
|
||||
@ -76,14 +77,13 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||
if len_typ.has_flag(.option) {
|
||||
c.error('cannot use unwrapped Option as length', node.len_expr.pos())
|
||||
}
|
||||
if node.has_len && !node.has_init {
|
||||
elem_type_sym := c.table.sym(node.elem_type)
|
||||
if elem_type_sym.kind == .interface_ {
|
||||
c.error('cannot instantiate an array of interfaces without also giving a default `init:` value',
|
||||
node.len_expr.pos())
|
||||
// check &int{}, interface, sum_type initialized
|
||||
if !node.has_init {
|
||||
c.check_elements_initialized(unwrap_elem_type) or {
|
||||
c.warn('${err.msg()}, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)',
|
||||
node.pos)
|
||||
}
|
||||
}
|
||||
c.ensure_sumtype_array_has_default_value(node)
|
||||
}
|
||||
if node.has_cap {
|
||||
cap_typ := c.check_expr_opt_call(node.cap_expr, c.expr(mut node.cap_expr))
|
||||
@ -97,26 +97,21 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||
c.error('generic struct cannot be used in non-generic function', node.pos)
|
||||
}
|
||||
|
||||
// `&int{}` check
|
||||
if node.has_len && !c.check_elements_ref_containers_initialized(node.elem_type) {
|
||||
c.warn('arrays of references need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`)',
|
||||
node.pos)
|
||||
}
|
||||
// `&Struct{} check
|
||||
if node.has_len {
|
||||
c.check_elements_ref_fields_initialized(node.elem_type, node.pos)
|
||||
c.check_elements_ref_fields_initialized(unwrap_elem_type, node.pos)
|
||||
}
|
||||
return node.typ
|
||||
}
|
||||
|
||||
if node.is_fixed {
|
||||
c.ensure_sumtype_array_has_default_value(node)
|
||||
c.ensure_type_exists(node.elem_type, node.elem_type_pos)
|
||||
if !c.is_builtin_mod && !c.check_elements_ref_containers_initialized(node.elem_type) {
|
||||
c.warn('fixed arrays of references need to be initialized right away (unless inside `unsafe`)',
|
||||
node.pos)
|
||||
if !c.is_builtin_mod {
|
||||
c.check_elements_initialized(unwrap_elem_type) or {
|
||||
c.warn('fixed ${err.msg()} (unless inside `unsafe`)', node.pos)
|
||||
}
|
||||
}
|
||||
c.check_elements_ref_fields_initialized(node.elem_type, node.pos)
|
||||
c.check_elements_ref_fields_initialized(unwrap_elem_type, node.pos)
|
||||
}
|
||||
// `a = []`
|
||||
if node.exprs.len == 0 {
|
||||
@ -351,13 +346,6 @@ fn (mut c Checker) check_array_init_para_type(para string, mut expr ast.Expr, po
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) ensure_sumtype_array_has_default_value(node ast.ArrayInit) {
|
||||
sym := c.table.sym(node.elem_type)
|
||||
if sym.kind == .sum_type && !node.has_init {
|
||||
c.error('cannot initialize sum type array without default value', node.pos)
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
||||
// `map = {}`
|
||||
if node.keys.len == 0 && node.vals.len == 0 && node.typ == 0 {
|
||||
@ -574,42 +562,46 @@ fn (mut c Checker) do_check_elements_ref_fields_initialized(sym &ast.TypeSymbol,
|
||||
}
|
||||
}
|
||||
|
||||
// check the element, and its children for ref uninitialized containers
|
||||
fn (mut c Checker) check_elements_ref_containers_initialized(typ ast.Type) bool {
|
||||
const err_ref_uninitialized = error('arrays of references need to be initialized right away')
|
||||
const err_interface_uninitialized = error('arrays of interfaces need to be initialized right away')
|
||||
const err_sumtype_uninitialized = error('arrays of sumtypes need to be initialized right away')
|
||||
|
||||
// check the element, and its children for `ref/interface/sumtype` initialized
|
||||
fn (mut c Checker) check_elements_initialized(typ ast.Type) ! {
|
||||
if typ == 0 || c.inside_unsafe {
|
||||
return true
|
||||
return
|
||||
}
|
||||
if typ.is_any_kind_of_pointer() {
|
||||
return false
|
||||
return checker.err_ref_uninitialized
|
||||
}
|
||||
sym := c.table.sym(typ)
|
||||
if sym.kind == .interface_ {
|
||||
return checker.err_interface_uninitialized
|
||||
} else if sym.kind == .sum_type {
|
||||
return checker.err_sumtype_uninitialized
|
||||
}
|
||||
|
||||
match sym.info {
|
||||
ast.Array {
|
||||
elem_type := sym.info.elem_type
|
||||
if elem_type.is_any_kind_of_pointer() {
|
||||
return false
|
||||
}
|
||||
return c.check_elements_ref_containers_initialized(elem_type)
|
||||
return c.check_elements_initialized(elem_type)
|
||||
}
|
||||
ast.ArrayFixed {
|
||||
elem_type := sym.info.elem_type
|
||||
if elem_type.is_any_kind_of_pointer() && !c.is_builtin_mod {
|
||||
return false
|
||||
if !c.is_builtin_mod {
|
||||
return c.check_elements_initialized(elem_type)
|
||||
}
|
||||
return c.check_elements_ref_containers_initialized(elem_type)
|
||||
}
|
||||
ast.Map {
|
||||
value_type := sym.info.value_type
|
||||
if value_type.is_any_kind_of_pointer() && !c.is_builtin_mod {
|
||||
return false
|
||||
if !c.is_builtin_mod {
|
||||
return c.check_elements_initialized(value_type)
|
||||
}
|
||||
return c.check_elements_ref_containers_initialized(value_type)
|
||||
}
|
||||
ast.Alias {
|
||||
parent_type := sym.info.parent_type
|
||||
return c.check_elements_ref_containers_initialized(parent_type)
|
||||
return c.check_elements_initialized(parent_type)
|
||||
}
|
||||
else {}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
vlib/v/checker/tests/array_init_sum_type_without_init_value_and_len_err.vv:4:7: error: cannot initialize sum type array without default value
|
||||
2 |
|
||||
3 | fn main() {
|
||||
4 | a := []Foo{len: 10}
|
||||
| ~~~~~~
|
||||
5 | println(a)
|
||||
6 |
|
||||
vlib/v/checker/tests/array_init_sum_type_without_init_value_and_len_err.vv:7:13: error: cannot initialize sum type array without default value
|
||||
5 | println(a)
|
||||
6 |
|
||||
7 | fixed_a := [10]Foo{}
|
||||
| ~~~~~~~~~
|
||||
8 | println(fixed_a)
|
||||
9 | }
|
@ -1,9 +0,0 @@
|
||||
type Foo = int | string
|
||||
|
||||
fn main() {
|
||||
a := []Foo{len: 10}
|
||||
println(a)
|
||||
|
||||
fixed_a := [10]Foo{}
|
||||
println(fixed_a)
|
||||
}
|
70
vlib/v/checker/tests/array_init_without_init_value_err.out
Normal file
70
vlib/v/checker/tests/array_init_without_init_value_err.out
Normal file
@ -0,0 +1,70 @@
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:5:7: warning: arrays of sumtypes need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)
|
||||
3 |
|
||||
4 | fn main_sum_type() {
|
||||
5 | a := []Foo{len: 10}
|
||||
| ~~~~~~
|
||||
6 | println(a)
|
||||
7 | fixed_a := [10]Foo{}
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:7:13: warning: fixed arrays of sumtypes need to be initialized right away (unless inside `unsafe`)
|
||||
5 | a := []Foo{len: 10}
|
||||
6 | println(a)
|
||||
7 | fixed_a := [10]Foo{}
|
||||
| ~~~~~~~~~
|
||||
8 | println(fixed_a)
|
||||
9 | }
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:20:11: warning: arrays of references need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)
|
||||
18 | // test references uninitialized.
|
||||
19 | fn main_ref() {
|
||||
20 | println(*[]&int{len: 1}[0])
|
||||
| ~~~~~~~
|
||||
21 | println([1]&int{})
|
||||
22 | _ = [][1]&int{len: 1}[0][0]
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:21:10: warning: fixed arrays of references need to be initialized right away (unless inside `unsafe`)
|
||||
19 | fn main_ref() {
|
||||
20 | println(*[]&int{len: 1}[0])
|
||||
21 | println([1]&int{})
|
||||
| ~~~~~~~~~
|
||||
22 | _ = [][1]&int{len: 1}[0][0]
|
||||
23 | _ = []map[int]&int{len: 1}
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:22:6: warning: arrays of references need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)
|
||||
20 | println(*[]&int{len: 1}[0])
|
||||
21 | println([1]&int{})
|
||||
22 | _ = [][1]&int{len: 1}[0][0]
|
||||
| ~~~~~~~~~~
|
||||
23 | _ = []map[int]&int{len: 1}
|
||||
24 | }
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:23:6: warning: arrays of references need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)
|
||||
21 | println([1]&int{})
|
||||
22 | _ = [][1]&int{len: 1}[0][0]
|
||||
23 | _ = []map[int]&int{len: 1}
|
||||
| ~~~~~~~~~~~~~~~
|
||||
24 | }
|
||||
25 |
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:40:22: warning: arrays of interfaces need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)
|
||||
38 |
|
||||
39 | fn main_interface() {
|
||||
40 | mut parsed_lines := []MObject{len: 9}
|
||||
| ~~~~~~~~~~
|
||||
41 | println(parsed_lines)
|
||||
42 | }
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:12:7: warning: arrays of sumtypes need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)
|
||||
10 |
|
||||
11 | fn main_sum_type_2[T]() {
|
||||
12 | a := []T{len: 10}
|
||||
| ~~~~
|
||||
13 | println(a)
|
||||
14 | fixed_a := [10]T{}
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:14:13: warning: fixed arrays of sumtypes need to be initialized right away (unless inside `unsafe`)
|
||||
12 | a := []T{len: 10}
|
||||
13 | println(a)
|
||||
14 | fixed_a := [10]T{}
|
||||
| ~~~~~~~
|
||||
15 | println(fixed_a)
|
||||
16 | }
|
||||
vlib/v/checker/tests/array_init_without_init_value_err.vv:45:22: warning: arrays of interfaces need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)
|
||||
43 |
|
||||
44 | fn main_interface_2[T]() {
|
||||
45 | mut parsed_lines := []T{len: 9}
|
||||
| ~~~~
|
||||
46 | println(parsed_lines)
|
||||
47 | }
|
57
vlib/v/checker/tests/array_init_without_init_value_err.vv
Normal file
57
vlib/v/checker/tests/array_init_without_init_value_err.vv
Normal file
@ -0,0 +1,57 @@
|
||||
// test sum_types uninitialized.
|
||||
type Foo = int | string
|
||||
|
||||
fn main_sum_type() {
|
||||
a := []Foo{len: 10}
|
||||
println(a)
|
||||
fixed_a := [10]Foo{}
|
||||
println(fixed_a)
|
||||
}
|
||||
|
||||
fn main_sum_type_2[T]() {
|
||||
a := []T{len: 10}
|
||||
println(a)
|
||||
fixed_a := [10]T{}
|
||||
println(fixed_a)
|
||||
}
|
||||
|
||||
// test references uninitialized.
|
||||
fn main_ref() {
|
||||
println(*[]&int{len: 1}[0])
|
||||
println([1]&int{})
|
||||
_ = [][1]&int{len: 1}[0][0]
|
||||
_ = []map[int]&int{len: 1}
|
||||
}
|
||||
|
||||
// test interfaces uninitialized.
|
||||
interface MObject {
|
||||
give_string() string
|
||||
}
|
||||
|
||||
struct LeStruct {
|
||||
le_string string
|
||||
}
|
||||
|
||||
fn (a LeStruct) give_string() string {
|
||||
return 'V'
|
||||
}
|
||||
|
||||
fn main_interface() {
|
||||
mut parsed_lines := []MObject{len: 9}
|
||||
println(parsed_lines)
|
||||
}
|
||||
|
||||
fn main_interface_2[T]() {
|
||||
mut parsed_lines := []T{len: 9}
|
||||
println(parsed_lines)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
main_sum_type()
|
||||
main_sum_type_2[Foo]()
|
||||
|
||||
main_ref()
|
||||
|
||||
main_interface()
|
||||
main_interface_2[MObject]()
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
vlib/v/checker/tests/array_of_interfaces_with_len_without_init.vv:14:37: error: cannot instantiate an array of interfaces without also giving a default `init:` value
|
||||
12 |
|
||||
13 | fn main() {
|
||||
14 | mut parsed_lines := []MObject{len: 9}
|
||||
| ^
|
||||
15 | println(parsed_lines)
|
||||
16 | }
|
@ -1,16 +0,0 @@
|
||||
interface MObject {
|
||||
give_string() string
|
||||
}
|
||||
|
||||
struct LeStruct {
|
||||
le_string string
|
||||
}
|
||||
|
||||
fn (a LeStruct) give_string() string {
|
||||
return 'V'
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut parsed_lines := []MObject{len: 9}
|
||||
println(parsed_lines)
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
vlib/v/checker/tests/ptr_array_init.vv:2:11: warning: arrays of references need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`)
|
||||
1 | fn main() {
|
||||
2 | println(*[]&int{len: 1}[0])
|
||||
| ~~~~~~~
|
||||
3 | println([1]&int{})
|
||||
4 | _ = [][1]&int{len: 1}[0][0]
|
||||
vlib/v/checker/tests/ptr_array_init.vv:3:10: warning: fixed arrays of references need to be initialized right away (unless inside `unsafe`)
|
||||
1 | fn main() {
|
||||
2 | println(*[]&int{len: 1}[0])
|
||||
3 | println([1]&int{})
|
||||
| ~~~~~~~~~
|
||||
4 | _ = [][1]&int{len: 1}[0][0]
|
||||
5 | _ = []map[int]&int{len: 1}
|
||||
vlib/v/checker/tests/ptr_array_init.vv:4:6: warning: arrays of references need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`)
|
||||
2 | println(*[]&int{len: 1}[0])
|
||||
3 | println([1]&int{})
|
||||
4 | _ = [][1]&int{len: 1}[0][0]
|
||||
| ~~~~~~~~~~
|
||||
5 | _ = []map[int]&int{len: 1}
|
||||
6 | }
|
||||
vlib/v/checker/tests/ptr_array_init.vv:5:6: warning: arrays of references need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`)
|
||||
3 | println([1]&int{})
|
||||
4 | _ = [][1]&int{len: 1}[0][0]
|
||||
5 | _ = []map[int]&int{len: 1}
|
||||
| ~~~~~~~~~~~~~~~
|
||||
6 | }
|
||||
|
@ -1,6 +0,0 @@
|
||||
fn main() {
|
||||
println(*[]&int{len: 1}[0])
|
||||
println([1]&int{})
|
||||
_ = [][1]&int{len: 1}[0][0]
|
||||
_ = []map[int]&int{len: 1}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/shared_element_lock.vv:43:11: warning: arrays of references need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`)
|
||||
vlib/v/checker/tests/shared_element_lock.vv:43:11: warning: arrays of references need to be initialized right away, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)
|
||||
41 | shared g := Pro{}
|
||||
42 | g.pers.age = 42
|
||||
43 | mut h := []shared Pro{len: 3}
|
||||
|
Loading…
x
Reference in New Issue
Block a user