Skip to content

Commit

Permalink
ast: fix dimension mismatch check for fn/method mut array args (fix #…
Browse files Browse the repository at this point in the history
  • Loading branch information
shove70 committed Dec 15, 2023
1 parent c5a6aeb commit 715a0a6
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 39 deletions.
39 changes: 15 additions & 24 deletions vlib/v/ast/table.v
Expand Up @@ -1569,14 +1569,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
}
match mut sym.info {
Array {
mut elem_type := sym.info.elem_type
mut elem_sym := t.sym(elem_type)
mut dims := 1
for mut elem_sym.info is Array {
elem_type = elem_sym.info.elem_type
elem_sym = t.sym(elem_type)
dims++
}
dims, elem_type := t.get_array_dims(sym.info)
if typ := t.resolve_generic_to_concrete(elem_type, generic_names, concrete_types) {
idx := t.find_or_register_array_with_dims(typ, dims)
if typ.has_flag(.generic) {
Expand Down Expand Up @@ -1782,14 +1775,7 @@ pub fn (mut t Table) generic_type_names(generic_type Type) []string {
}
match mut sym.info {
Array {
mut elem_type := sym.info.elem_type
mut elem_sym := t.sym(elem_type)
mut dims := 1
for mut elem_sym.info is Array {
elem_type = elem_sym.info.elem_type
elem_sym = t.sym(elem_type)
dims++
}
_, elem_type := t.get_array_dims(sym.info)
names << t.generic_type_names(elem_type)
}
ArrayFixed {
Expand Down Expand Up @@ -1847,14 +1833,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
ts := t.sym(typ)
match ts.info {
Array {
mut elem_type := ts.info.elem_type
mut elem_sym := t.sym(elem_type)
mut dims := 1
for mut elem_sym.info is Array {
elem_type = elem_sym.info.elem_type
elem_sym = t.sym(elem_type)
dims++
}
dims, elem_type := t.get_array_dims(ts.info)
unwrap_typ := t.unwrap_generic_type(elem_type, generic_names, concrete_types)
idx := t.find_or_register_array_with_dims(unwrap_typ, dims)
return new_type(idx).derive_add_muls(typ).clear_flag(.generic)
Expand Down Expand Up @@ -2549,3 +2528,15 @@ pub fn (t &Table) dependent_names_in_stmt(stmt Stmt) []string {
}
return names
}

pub fn (t &Table) get_array_dims(arr Array) (int, Type) {
mut dims := 1
mut elem_type := arr.elem_type
mut elem_sym := t.sym(elem_type)
for mut elem_sym.info is Array {
dims++
elem_type = elem_sym.info.elem_type
elem_sym = t.sym(elem_type)
}
return dims, elem_type
}
24 changes: 19 additions & 5 deletions vlib/v/ast/types.v
Expand Up @@ -1535,18 +1535,32 @@ pub fn (t &Table) fn_signature_using_aliases(func &Fn, import_aliases map[string
}

// symbol_name_except_generic return the name of the complete qualified name of the type,
// but without the generic parts. For example:
// but without the generic parts. The potential `[]`, `&[][]` etc prefixes are kept. For example:
// `main.Abc[int]` -> `main.Abc`
// `main.Abc<T>[int]` -> `main.Abc<T>`
// `[]main.Abc<T>[int]` -> `[]main.Abc<T>`
// `&[][]main.Abc<T>[int]` -> `&[][]main.Abc<T>`
pub fn (t &TypeSymbol) symbol_name_except_generic() string {
// &[]main.Abc[int], [][]main.Abc[int]...
mut prefix := ''
mut name := t.name
for i, ch in t.name {
if ch in [`&`, `[`, `]`] {
continue
}
if i > 0 {
prefix = t.name[..i]
name = t.name[i..]
}
break
}
// main.Abc[int]
mut embed_name := t.name
// remove generic part from name
// main.Abc[int] => main.Abc
if embed_name.contains('[') {
embed_name = embed_name.all_before('[')
if name.contains('[') {
name = name.all_before('[')
}
return embed_name
return prefix + name
}

// embed_name return the pure name of the complete qualified name of the type,
Expand Down
19 changes: 13 additions & 6 deletions vlib/v/checker/tests/fn_call_arg_array_mismatch_err.out
@@ -1,7 +1,14 @@
vlib/v/checker/tests/fn_call_arg_array_mismatch_err.vv:9:36: error: cannot use `string` as `array` in argument 2 to `os.write_file_array`
7 |
8 | fn main() {
9 | os.write_file_array(service_path, service_file) or {
vlib/v/checker/tests/fn_call_arg_array_mismatch_err.vv:7:36: error: cannot use `string` as `array` in argument 2 to `os.write_file_array`
5 |
6 | fn main() {
7 | os.write_file_array(service_path, service_file) or {
| ~~~~~~~~~~~~
10 | eprintln('Error: write file service')
11 | exit(1)
8 | eprintln('Error: write file service')
9 | exit(1)
vlib/v/checker/tests/fn_call_arg_array_mismatch_err.vv:16:10: error: cannot use `&[]int` as `&[][]int` in argument 1 to `bar`
14 | // dimension checking error when mut array is passed multiple times as args
15 | fn foo(mut arr []int) {
16 | bar(mut arr)
| ~~~
17 | }
18 |
20 changes: 16 additions & 4 deletions vlib/v/checker/tests/fn_call_arg_array_mismatch_err.vv
@@ -1,13 +1,25 @@
import os

const (
service_file = '[Unit]'
service_path = 'dockerman.service'
)
const service_file = '[Unit]'
const service_path = 'dockerman.service'

fn main() {
os.write_file_array(service_path, service_file) or {
eprintln('Error: write file service')
exit(1)
}
}

// for issue 20172
// dimension checking error when mut array is passed multiple times as args
fn foo(mut arr []int) {
bar(mut arr)
}

fn bar(mut arr [][]int) {
}

fn baz() {
mut arr := [1, 2, 3]
foo(mut arr)
}

0 comments on commit 715a0a6

Please sign in to comment.