diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 9d4188ea3f..0b2e6481d2 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -5149,13 +5149,13 @@ pub fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) table.Type { return right_type } -fn (mut c Checker) check_index(typ_sym &table.TypeSymbol, index ast.Expr, index_type table.Type, pos token.Position) { +fn (mut c Checker) check_index(typ_sym &table.TypeSymbol, index ast.Expr, index_type table.Type, pos token.Position, range_index bool) { index_type_sym := c.table.get_type_symbol(index_type) // println('index expr left=$typ_sym.name $node.pos.line_nr') // if typ_sym.kind == .array && (!(table.type_idx(index_type) in table.number_type_idxs) && // index_type_sym.kind != .enum_) { if typ_sym.kind in [.array, .array_fixed, .string, .ustring] { - if !(index_type.is_number() || index_type_sym.kind == .enum_) { + if !(index_type.is_int() || index_type_sym.kind == .enum_) { type_str := if typ_sym.kind in [.string, .ustring] { 'non-integer string index `$index_type_sym.name`' } else { @@ -5164,8 +5164,14 @@ fn (mut c Checker) check_index(typ_sym &table.TypeSymbol, index ast.Expr, index_ c.error('$type_str', pos) } if index is ast.IntegerLiteral { - if index.val.starts_with('-') { - c.error('invalid index `$index.val` (index must be non-negative)', index.pos) + if index.val[0] == `-` { + c.error('negative index `$index.val`', index.pos) + } else if typ_sym.kind == .array_fixed { + i := index.val.int() + info := typ_sym.info as table.ArrayFixed + if (!range_index && i >= info.size) || (range_index && i > info.size) { + c.error('index out of range (index: $i, len: $info.size)', index.pos) + } } } if index_type.has_flag(.optional) { @@ -5220,11 +5226,11 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type { if mut node.index is ast.RangeExpr { // [1..2] if node.index.has_low { index_type := c.expr(node.index.low) - c.check_index(typ_sym, node.index.low, index_type, node.pos) + c.check_index(typ_sym, node.index.low, index_type, node.pos, true) } if node.index.has_high { index_type := c.expr(node.index.high) - c.check_index(typ_sym, node.index.high, index_type, node.pos) + c.check_index(typ_sym, node.index.high, index_type, node.pos, true) } // array[1..2] => array // fixed_array[1..2] => array @@ -5244,7 +5250,7 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type { c.error('invalid key: $err', node.pos) } } else { - c.check_index(typ_sym, node.index, index_type, node.pos) + c.check_index(typ_sym, node.index, index_type, node.pos, false) } value_type := c.table.value_type(typ) if value_type != table.void_type { diff --git a/vlib/v/checker/tests/array_index.out b/vlib/v/checker/tests/array_index.out new file mode 100644 index 0000000000..d2e679552c --- /dev/null +++ b/vlib/v/checker/tests/array_index.out @@ -0,0 +1,34 @@ +vlib/v/checker/tests/array_index.vv:3:7: error: non-integer index `float literal` (array type `[2]int`) + 1 | fn fixed() { + 2 | a := [1,2]! + 3 | _ = a[0.2] + | ~~~~~ + 4 | _ = a[1] // OK + 5 | _ = a[-1] +vlib/v/checker/tests/array_index.vv:5:8: error: negative index `-1` + 3 | _ = a[0.2] + 4 | _ = a[1] // OK + 5 | _ = a[-1] + | ~~ + 6 | _ = a[2] + 7 | _ = a[1..2] // OK +vlib/v/checker/tests/array_index.vv:6:8: error: index out of range (index: 2, len: 2) + 4 | _ = a[1] // OK + 5 | _ = a[-1] + 6 | _ = a[2] + | ^ + 7 | _ = a[1..2] // OK + 8 | _ = a[2..2] // empty, OK +vlib/v/checker/tests/array_index.vv:9:11: error: index out of range (index: 3, len: 2) + 7 | _ = a[1..2] // OK + 8 | _ = a[2..2] // empty, OK + 9 | _ = a[1..3] + | ^ + 10 | _ = a[3..3] + 11 | } +vlib/v/checker/tests/array_index.vv:10:8: error: index out of range (index: 3, len: 2) + 8 | _ = a[2..2] // empty, OK + 9 | _ = a[1..3] + 10 | _ = a[3..3] + | ^ + 11 | } diff --git a/vlib/v/checker/tests/array_index.vv b/vlib/v/checker/tests/array_index.vv new file mode 100644 index 0000000000..74200ff54d --- /dev/null +++ b/vlib/v/checker/tests/array_index.vv @@ -0,0 +1,11 @@ +fn fixed() { + a := [1,2]! + _ = a[0.2] + _ = a[1] // OK + _ = a[-1] + _ = a[2] + _ = a[1..2] // OK + _ = a[2..2] // empty, OK + _ = a[1..3] + _ = a[3..3] +} diff --git a/vlib/v/checker/tests/index_expr.out b/vlib/v/checker/tests/index_expr.out index e6594088c0..90aa0a21ea 100644 --- a/vlib/v/checker/tests/index_expr.out +++ b/vlib/v/checker/tests/index_expr.out @@ -3,16 +3,16 @@ vlib/v/checker/tests/index_expr.vv:3:7: error: type `int` does not support index 2 | v := 4 3 | _ = v[0] | ~~~ - 4 | + 4 | 5 | a := [2] vlib/v/checker/tests/index_expr.vv:6:7: error: non-integer index `[]int` (array type `[]int`) - 4 | + 4 | 5 | a := [2] 6 | _ = a[a] | ~~~ 7 | _ = a[-1] 8 | } -vlib/v/checker/tests/index_expr.vv:7:8: error: invalid index `-1` (index must be non-negative) +vlib/v/checker/tests/index_expr.vv:7:8: error: negative index `-1` 5 | a := [2] 6 | _ = a[a] 7 | _ = a[-1] @@ -31,10 +31,10 @@ vlib/v/checker/tests/index_expr.vv:13:7: error: type `int` does not support inde 12 | _ = v[1..] 13 | _ = v[..1] | ~~~~~ - 14 | + 14 | 15 | a := [2] vlib/v/checker/tests/index_expr.vv:16:7: error: non-integer index `[]int` (array type `[]int`) - 14 | + 14 | 15 | a := [2] 16 | _ = a[a..] | ~~~~~ @@ -47,21 +47,21 @@ vlib/v/checker/tests/index_expr.vv:17:7: error: non-integer index `[]int` (array | ~~~~~ 18 | _ = a[-1..] 19 | _ = a[..-1] -vlib/v/checker/tests/index_expr.vv:18:8: error: invalid index `-1` (index must be non-negative) +vlib/v/checker/tests/index_expr.vv:18:8: error: negative index `-1` 16 | _ = a[a..] 17 | _ = a[..a] 18 | _ = a[-1..] | ~~ 19 | _ = a[..-1] 20 | _ = a[-1..-2] -vlib/v/checker/tests/index_expr.vv:19:10: error: invalid index `-1` (index must be non-negative) +vlib/v/checker/tests/index_expr.vv:19:10: error: negative index `-1` 17 | _ = a[..a] 18 | _ = a[-1..] 19 | _ = a[..-1] | ~~ 20 | _ = a[-1..-2] 21 | } -vlib/v/checker/tests/index_expr.vv:20:8: error: invalid index `-1` (index must be non-negative) +vlib/v/checker/tests/index_expr.vv:20:8: error: negative index `-1` 18 | _ = a[-1..] 19 | _ = a[..-1] 20 | _ = a[-1..-2]