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

yuyi 2022-05-13 11:57:48 +08:00 committed by Jef Roosens
parent 54bbc00493
commit 870ed86afc
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
7 changed files with 41 additions and 53 deletions

View File

@ -3864,40 +3864,25 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
mut typ := c.expr(node.left)
mut typ_sym := c.table.final_sym(typ)
node.left_type = typ
for {
match typ_sym.kind {
.map {
node.is_map = true
break
}
.array {
node.is_array = true
if node.or_expr.kind != .absent && node.index is ast.RangeExpr {
c.error('custom error handling on range expressions for arrays is not supported yet.',
node.or_expr.pos)
}
break
}
.array_fixed {
node.is_farray = true
break
}
.any {
gname := typ_sym.name
typ = c.unwrap_generic(typ)
node.left_type = 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
match typ_sym.kind {
.map {
node.is_map = true
}
.array {
node.is_array = true
if node.or_expr.kind != .absent && node.index is ast.RangeExpr {
c.error('custom error handling on range expressions for arrays is not supported yet.',
node.or_expr.pos)
}
}
.array_fixed {
node.is_farray = true
}
.any {
typ = c.unwrap_generic(typ)
typ_sym = c.table.final_sym(typ)
}
else {}
}
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) {

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 {
g.range_expr(node, node.index)
} else {
sym := g.table.final_sym(node.left_type)
sym := g.table.final_sym(g.unwrap_generic(node.left_type))
if sym.kind == .array {
g.index_of_array(node, sym)
} else if sym.kind == .array_fixed {

View File

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