Skip to content

Commit

Permalink
checker: check fixed array init with default expression (#19472)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 committed Sep 29, 2023
1 parent 24278d8 commit ae5b4bb
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 17 deletions.
22 changes: 12 additions & 10 deletions vlib/v/checker/containers.v
Expand Up @@ -62,15 +62,7 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
}
}
if node.has_default {
mut default_expr := node.default_expr
default_typ := c.check_expr_opt_call(default_expr, c.expr(mut default_expr))
node.default_type = default_typ
if !node.elem_type.has_flag(.option) && default_typ.has_flag(.option) {
c.error('cannot use unwrapped Option as initializer', default_expr.pos())
}
c.check_expected(default_typ, node.elem_type) or {
c.error(err.msg(), default_expr.pos())
}
c.check_array_init_default_expr(mut node)
}
if node.has_len {
len_typ := c.check_expr_opt_call(node.len_expr, c.expr(mut node.len_expr))
Expand Down Expand Up @@ -304,12 +296,22 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
node.typ = ast.new_type(idx)
}
if node.has_default {
node.default_type = c.expr(mut node.default_expr)
c.check_array_init_default_expr(mut node)
}
}
return node.typ
}

fn (mut c Checker) check_array_init_default_expr(mut node ast.ArrayInit) {
mut default_expr := node.default_expr
default_typ := c.check_expr_opt_call(default_expr, c.expr(mut default_expr))
node.default_type = default_typ
if !node.elem_type.has_flag(.option) && default_typ.has_flag(.option) {
c.error('cannot use unwrapped Option as initializer', default_expr.pos())
}
c.check_expected(default_typ, node.elem_type) or { c.error(err.msg(), default_expr.pos()) }
}

fn (mut c Checker) check_array_init_para_type(para string, mut expr ast.Expr, pos token.Pos) {
sym := c.table.sym(c.unwrap_generic(c.expr(mut expr)))
if sym.kind !in [.int, .int_literal] {
Expand Down
27 changes: 27 additions & 0 deletions vlib/v/checker/tests/fixed_array_init_with_default.out
@@ -0,0 +1,27 @@
vlib/v/checker/tests/fixed_array_init_with_default.vv:6:27: error: expected `string`, not `[]string`
4 |
5 | fn main() {
6 | _ := Foo{[2]string{init: ['a', 'b']}}
| ~~~~~~~~~~
7 | _ := Foo{[2]string{init: 2.2}}
8 | _ := Foo{[2]string{init: 22}}
vlib/v/checker/tests/fixed_array_init_with_default.vv:7:27: error: expected `string`, not `float literal`
5 | fn main() {
6 | _ := Foo{[2]string{init: ['a', 'b']}}
7 | _ := Foo{[2]string{init: 2.2}}
| ~~~
8 | _ := Foo{[2]string{init: 22}}
9 | _ := Foo{[2]string{init: true}}
vlib/v/checker/tests/fixed_array_init_with_default.vv:8:27: error: expected `string`, not `int literal`
6 | _ := Foo{[2]string{init: ['a', 'b']}}
7 | _ := Foo{[2]string{init: 2.2}}
8 | _ := Foo{[2]string{init: 22}}
| ~~
9 | _ := Foo{[2]string{init: true}}
10 | }
vlib/v/checker/tests/fixed_array_init_with_default.vv:9:27: error: expected `string`, not `bool`
7 | _ := Foo{[2]string{init: 2.2}}
8 | _ := Foo{[2]string{init: 22}}
9 | _ := Foo{[2]string{init: true}}
| ~~~~
10 | }
10 changes: 10 additions & 0 deletions vlib/v/checker/tests/fixed_array_init_with_default.vv
@@ -0,0 +1,10 @@
struct Foo {
stack_arr [2]string
}

fn main() {
_ := Foo{[2]string{init: ['a', 'b']}}
_ := Foo{[2]string{init: 2.2}}
_ := Foo{[2]string{init: 22}}
_ := Foo{[2]string{init: true}}
}
21 changes: 14 additions & 7 deletions vlib/v/checker/tests/option_fn_err.out
Expand Up @@ -3,21 +3,21 @@ vlib/v/checker/tests/option_fn_err.vv:34:16: error: cannot use `?int` as `int`,
33 | _ := bar(0)
34 | println(twice(bar(0)))
| ~~~~~~
35 |
35 |
36 | // anon fn
vlib/v/checker/tests/option_fn_err.vv:37:16: error: cannot use `?int` as `int`, it must be unwrapped first in argument 1 to `anon`
35 |
35 |
36 | // anon fn
37 | fn (_ int) {}(bar(0))
| ~~~~~~
38 |
38 |
39 | // assert
vlib/v/checker/tests/option_fn_err.vv:40:9: error: assert can be used only with `bool` expressions, but found `bool` instead
38 |
38 |
39 | // assert
40 | assert bar(true)
| ~~~~~~~~~
41 |
41 |
42 | // struct
vlib/v/checker/tests/option_fn_err.vv:45:3: error: cannot assign an Option value to a non-option struct field
43 | mut v := Data{
Expand All @@ -38,7 +38,7 @@ vlib/v/checker/tests/option_fn_err.vv:49:6: error: cannot use `?int` as `int`, i
48 | v.add(bar(0)) // call method
49 | v.f(bar(0)) // call fn field
| ~~~~~~
50 |
50 |
51 | // array
vlib/v/checker/tests/option_fn_err.vv:56:27: error: cannot use unwrapped Option as initializer
54 | // init
Expand All @@ -47,6 +47,13 @@ vlib/v/checker/tests/option_fn_err.vv:56:27: error: cannot use unwrapped Option
| ~~~~~~
57 | _ := [bar(0)]!
58 | _ := [1]int{init: bar(0)}
vlib/v/checker/tests/option_fn_err.vv:58:20: error: cannot use unwrapped Option as initializer
56 | _ := []int{len: 1, init: bar(0)}
57 | _ := [bar(0)]!
58 | _ := [1]int{init: bar(0)}
| ~~~~~~
59 | // index
60 | println(arr[bar(0)])
vlib/v/checker/tests/option_fn_err.vv:60:13: error: cannot use Option or Result as index (array type `[]int`)
58 | _ := [1]int{init: bar(0)}
59 | // index
Expand Down Expand Up @@ -101,5 +108,5 @@ vlib/v/checker/tests/option_fn_err.vv:69:18: error: type mismatch, `bar` must re
68 | println(arr.any(bar(true)))
69 | println(arr.all(bar(true)))
| ~~~~~~~~~
70 |
70 |
71 | match bar(0) {

0 comments on commit ae5b4bb

Please sign in to comment.