checker: disallow array append in an expression (#9265)

pull/9269/head
Nick Treleaven 2021-03-12 15:09:01 +00:00 committed by GitHub
parent dbbf96702b
commit 9db8a61b92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 36 additions and 13 deletions

View File

@ -581,6 +581,7 @@ pub struct InfixExpr {
pub: pub:
op token.Kind op token.Kind
pos token.Position pos token.Position
is_stmt bool
pub mut: pub mut:
left Expr left Expr
right Expr right Expr

View File

@ -155,7 +155,7 @@ fn (mut c Checker) check_shift(left_type table.Type, right_type table.Type, left
// allow `bool << 2` in translated C code // allow `bool << 2` in translated C code
return table.int_type return table.int_type
} }
c.error('invalid operation: shift of type `$sym.name`', left_pos) c.error('invalid operation: shift on type `$sym.name`', left_pos)
return table.void_type return table.void_type
} else if !right_type.is_int() { } else if !right_type.is_int() {
c.error('cannot shift non-integer type `${c.table.get_type_symbol(right_type).name}` into type `${c.table.get_type_symbol(left_type).name}`', c.error('cannot shift non-integer type `${c.table.get_type_symbol(right_type).name}` into type `${c.table.get_type_symbol(left_type).name}`',

View File

@ -875,6 +875,9 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
} }
.left_shift { .left_shift {
if left_final.kind == .array { if left_final.kind == .array {
if !infix_expr.is_stmt {
c.error('array append cannot be used in an expression', infix_expr.pos)
}
// `array << elm` // `array << elm`
infix_expr.auto_locked, _ = c.fail_if_immutable(infix_expr.left) infix_expr.auto_locked, _ = c.fail_if_immutable(infix_expr.left)
left_value_type := c.table.value_type(left_type) left_value_type := c.table.value_type(left_type)

View File

@ -0,0 +1,20 @@
vlib/v/checker/tests/append_err.vv:3:7: error: cannot append `string` to `[]int`
1 | fn main() {
2 | mut l := []int{}
3 | l << 'test'
| ~~~~~~
4 |
5 | _ = l << 3
vlib/v/checker/tests/append_err.vv:5:8: error: array append cannot be used in an expression
3 | l << 'test'
4 |
5 | _ = l << 3
| ~~
6 | _ = (l << 3).len
7 | }
vlib/v/checker/tests/append_err.vv:6:9: error: array append cannot be used in an expression
4 |
5 | _ = l << 3
6 | _ = (l << 3).len
| ~~
7 | }

View File

@ -1,4 +1,7 @@
fn main() { fn main() {
mut l := []int{} mut l := []int{}
l << 'test' l << 'test'
_ = l << 3
_ = (l << 3).len
} }

View File

@ -1,7 +1,7 @@
vlib/v/checker/tests/array_literal_modify_err.vv:2:14: error: array literal can not be modified vlib/v/checker/tests/array_literal_modify_err.vv:2:24: error: array append cannot be used in an expression
1 | fn main() { 1 | fn main() {
2 | mut nums := [1, 2, 3] << 4 2 | mut nums := [1, 2, 3] << 4
| ~~~~~~~~~ | ~~
3 | println(nums) 3 | println(nums)
4 | } 4 | }
vlib/v/checker/tests/array_literal_modify_err.vv:3:2: error: `println` can not print void expressions vlib/v/checker/tests/array_literal_modify_err.vv:3:2: error: `println` can not print void expressions

View File

@ -1,6 +0,0 @@
vlib/v/checker/tests/left_shift_err.vv:3:7: error: cannot append `string` to `[]int`
1 | fn main() {
2 | mut l := []int{}
3 | l << 'test'
| ~~~~~~
4 | }

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/rshift_op_wrong_left_type_err.vv:2:10: error: invalid operation: shift of type `float literal` vlib/v/checker/tests/rshift_op_wrong_left_type_err.vv:2:10: error: invalid operation: shift on type `float literal`
1 | fn main() { 1 | fn main() {
2 | println(0.5 >> 1) 2 | println(0.5 >> 1)
| ~~~ | ~~~

View File

@ -1,4 +1,4 @@
vlib/v/checker/tests/shift_op_wrong_left_type_err.vv:2:10: error: invalid operation: shift of type `float literal` vlib/v/checker/tests/shift_op_wrong_left_type_err.vv:2:10: error: invalid operation: shift on type `float literal`
1 | fn main() { 1 | fn main() {
2 | println(0.5 << 1) 2 | println(0.5 << 1)
| ~~~ | ~~~

View File

@ -377,6 +377,7 @@ pub fn (mut p Parser) expr_with_left(left ast.Expr, precedence int, is_stmt_iden
right: right right: right
op: tok.kind op: tok.kind
pos: pos pos: pos
is_stmt: true
} }
} else if p.tok.kind.is_infix() { } else if p.tok.kind.is_infix() {
if p.tok.kind.is_prefix() && p.tok.line_nr != p.prev_tok.line_nr { if p.tok.kind.is_prefix() && p.tok.line_nr != p.prev_tok.line_nr {
@ -473,6 +474,7 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
right: right right: right
op: op op: op
pos: pos pos: pos
is_stmt: p.is_stmt_ident
or_block: ast.OrExpr{ or_block: ast.OrExpr{
stmts: or_stmts stmts: or_stmts
kind: or_kind kind: or_kind