checker, cgen: fix generic fn with array and fixed array arguments (#14385)

master
yuyi 2022-05-13 11:57:48 +08:00 committed by GitHub
parent d679146a80
commit 3c95504a35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 41 additions and 53 deletions

View File

@ -3864,11 +3864,9 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
mut typ := c.expr(node.left) mut typ := c.expr(node.left)
mut typ_sym := c.table.final_sym(typ) mut typ_sym := c.table.final_sym(typ)
node.left_type = typ node.left_type = typ
for {
match typ_sym.kind { match typ_sym.kind {
.map { .map {
node.is_map = true node.is_map = true
break
} }
.array { .array {
node.is_array = true node.is_array = true
@ -3876,28 +3874,15 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
c.error('custom error handling on range expressions for arrays is not supported yet.', c.error('custom error handling on range expressions for arrays is not supported yet.',
node.or_expr.pos) node.or_expr.pos)
} }
break
} }
.array_fixed { .array_fixed {
node.is_farray = true node.is_farray = true
break
} }
.any { .any {
gname := typ_sym.name
typ = c.unwrap_generic(typ) typ = c.unwrap_generic(typ)
node.left_type = typ
typ_sym = c.table.final_sym(typ) typ_sym = c.table.final_sym(typ)
if typ.is_ptr() {
continue
} else {
c.error('generic type $gname does not support indexing, pass an array, or a reference instead, e.g. []$gname or &$gname',
node.pos)
}
}
else {
break
}
} }
else {}
} }
if typ_sym.kind !in [.array, .array_fixed, .string, .map] && !typ.is_ptr() if typ_sym.kind !in [.array, .array_fixed, .string, .map] && !typ.is_ptr()
&& typ !in [ast.byteptr_type, ast.charptr_type] && !typ.has_flag(.variadic) { && typ !in [ast.byteptr_type, ast.charptr_type] && !typ.has_flag(.variadic) {

View File

@ -1,6 +0,0 @@
vlib/v/checker/tests/generic_param_used_as_an_array_err.vv:2:10: error: generic type T does not support indexing, pass an array, or a reference instead, e.g. []T or &T
1 | fn test<T>(arr T) {
2 | a := arr[1]
| ~~~
3 | println(a)
4 | }

View File

@ -1,12 +0,0 @@
fn test<T>(arr T) {
a := arr[1]
println(a)
}
fn main() {
a := [1, 2, 3]!
test(a)
b := ['a', 'b', 'c']!
test(b)
}

View File

@ -10,7 +10,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
if node.index is ast.RangeExpr { if node.index is ast.RangeExpr {
g.range_expr(node, node.index) g.range_expr(node, node.index)
} else { } else {
sym := g.table.final_sym(node.left_type) sym := g.table.final_sym(g.unwrap_generic(node.left_type))
if sym.kind == .array { if sym.kind == .array {
g.index_of_array(node, sym) g.index_of_array(node, sym)
} else if sym.kind == .array_fixed { } else if sym.kind == .array_fixed {

View File

@ -1,5 +1,5 @@
fn show_element<T>(arr &T) string { fn show_element<T>(arr T) string {
return unsafe { '${arr[1]}' } return '${arr[1]}'
} }
fn test_generic_with_fixed_array_type() { fn test_generic_with_fixed_array_type() {

View File

@ -0,0 +1,6 @@
1
2
3
4
5
6

View File

@ -0,0 +1,15 @@
fn main() {
mut a := [1, 2, 3]
mut b := [4, 5, 6]!
func(mut a)
func(mut b)
}
fn func<T>(mut t T) {
$if T is $Array {
for i in 0 .. t.len {
println(t[i])
}
}
}