mirror of
https://github.com/vlang/v.git
synced 2025-09-15 10:27:19 -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 {
|
fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||||
mut elem_type := ast.void_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)
|
// `x := []string{}` (the type was set in the parser)
|
||||||
if node.typ != ast.void_type {
|
if node.typ != ast.void_type {
|
||||||
if node.elem_type != 0 {
|
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) {
|
if len_typ.has_flag(.option) {
|
||||||
c.error('cannot use unwrapped Option as length', node.len_expr.pos())
|
c.error('cannot use unwrapped Option as length', node.len_expr.pos())
|
||||||
}
|
}
|
||||||
if node.has_len && !node.has_init {
|
// check &int{}, interface, sum_type initialized
|
||||||
elem_type_sym := c.table.sym(node.elem_type)
|
if !node.has_init {
|
||||||
if elem_type_sym.kind == .interface_ {
|
c.check_elements_initialized(unwrap_elem_type) or {
|
||||||
c.error('cannot instantiate an array of interfaces without also giving a default `init:` value',
|
c.warn('${err.msg()}, therefore `len:` cannot be used (unless inside `unsafe`, or if you also use `init:`)',
|
||||||
node.len_expr.pos())
|
node.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.ensure_sumtype_array_has_default_value(node)
|
|
||||||
}
|
}
|
||||||
if node.has_cap {
|
if node.has_cap {
|
||||||
cap_typ := c.check_expr_opt_call(node.cap_expr, c.expr(mut node.cap_expr))
|
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)
|
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
|
// `&Struct{} check
|
||||||
if node.has_len {
|
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
|
return node.typ
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.is_fixed {
|
if node.is_fixed {
|
||||||
c.ensure_sumtype_array_has_default_value(node)
|
|
||||||
c.ensure_type_exists(node.elem_type, node.elem_type_pos)
|
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) {
|
if !c.is_builtin_mod {
|
||||||
c.warn('fixed arrays of references need to be initialized right away (unless inside `unsafe`)',
|
c.check_elements_initialized(unwrap_elem_type) or {
|
||||||
node.pos)
|
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 = []`
|
// `a = []`
|
||||||
if node.exprs.len == 0 {
|
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 {
|
fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
||||||
// `map = {}`
|
// `map = {}`
|
||||||
if node.keys.len == 0 && node.vals.len == 0 && node.typ == 0 {
|
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
|
const err_ref_uninitialized = error('arrays of references need to be initialized right away')
|
||||||
fn (mut c Checker) check_elements_ref_containers_initialized(typ ast.Type) bool {
|
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 {
|
if typ == 0 || c.inside_unsafe {
|
||||||
return true
|
return
|
||||||
}
|
}
|
||||||
if typ.is_any_kind_of_pointer() {
|
if typ.is_any_kind_of_pointer() {
|
||||||
return false
|
return checker.err_ref_uninitialized
|
||||||
}
|
}
|
||||||
sym := c.table.sym(typ)
|
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 {
|
match sym.info {
|
||||||
ast.Array {
|
ast.Array {
|
||||||
elem_type := sym.info.elem_type
|
elem_type := sym.info.elem_type
|
||||||
if elem_type.is_any_kind_of_pointer() {
|
return c.check_elements_initialized(elem_type)
|
||||||
return false
|
|
||||||
}
|
|
||||||
return c.check_elements_ref_containers_initialized(elem_type)
|
|
||||||
}
|
}
|
||||||
ast.ArrayFixed {
|
ast.ArrayFixed {
|
||||||
elem_type := sym.info.elem_type
|
elem_type := sym.info.elem_type
|
||||||
if elem_type.is_any_kind_of_pointer() && !c.is_builtin_mod {
|
if !c.is_builtin_mod {
|
||||||
return false
|
return c.check_elements_initialized(elem_type)
|
||||||
}
|
}
|
||||||
return c.check_elements_ref_containers_initialized(elem_type)
|
|
||||||
}
|
}
|
||||||
ast.Map {
|
ast.Map {
|
||||||
value_type := sym.info.value_type
|
value_type := sym.info.value_type
|
||||||
if value_type.is_any_kind_of_pointer() && !c.is_builtin_mod {
|
if !c.is_builtin_mod {
|
||||||
return false
|
return c.check_elements_initialized(value_type)
|
||||||
}
|
}
|
||||||
return c.check_elements_ref_containers_initialized(value_type)
|
|
||||||
}
|
}
|
||||||
ast.Alias {
|
ast.Alias {
|
||||||
parent_type := sym.info.parent_type
|
parent_type := sym.info.parent_type
|
||||||
return c.check_elements_ref_containers_initialized(parent_type)
|
return c.check_elements_initialized(parent_type)
|
||||||
}
|
}
|
||||||
else {}
|
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{}
|
41 | shared g := Pro{}
|
||||||
42 | g.pers.age = 42
|
42 | g.pers.age = 42
|
||||||
43 | mut h := []shared Pro{len: 3}
|
43 | mut h := []shared Pro{len: 3}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user