checker: check generics variadic arg mismatch (#9700)
parent
21e52ee003
commit
c3ccb58450
|
@ -970,14 +970,14 @@ pub fn (mut t Table) resolve_generic_by_names(generic_type Type, generic_names [
|
||||||
}
|
}
|
||||||
if typ := t.resolve_generic_by_names(elem_type, generic_names, generic_types) {
|
if typ := t.resolve_generic_by_names(elem_type, generic_names, generic_types) {
|
||||||
idx := t.find_or_register_array_with_dims(typ, dims)
|
idx := t.find_or_register_array_with_dims(typ, dims)
|
||||||
array_typ := new_type(idx)
|
array_typ := new_type(idx).derive(generic_type).clear_flag(.generic)
|
||||||
return array_typ
|
return array_typ
|
||||||
}
|
}
|
||||||
} else if sym.kind == .chan {
|
} else if sym.kind == .chan {
|
||||||
info := sym.info as Chan
|
info := sym.info as Chan
|
||||||
if typ := t.resolve_generic_by_names(info.elem_type, generic_names, generic_types) {
|
if typ := t.resolve_generic_by_names(info.elem_type, generic_names, generic_types) {
|
||||||
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
|
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
|
||||||
chan_typ := new_type(idx)
|
chan_typ := new_type(idx).derive(generic_type).clear_flag(.generic)
|
||||||
return chan_typ
|
return chan_typ
|
||||||
}
|
}
|
||||||
} else if mut sym.info is MultiReturn {
|
} else if mut sym.info is MultiReturn {
|
||||||
|
@ -993,7 +993,7 @@ pub fn (mut t Table) resolve_generic_by_names(generic_type Type, generic_names [
|
||||||
}
|
}
|
||||||
if type_changed {
|
if type_changed {
|
||||||
idx := t.find_or_register_multi_return(types)
|
idx := t.find_or_register_multi_return(types)
|
||||||
typ := new_type(idx)
|
typ := new_type(idx).derive(generic_type).clear_flag(.generic)
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
} else if mut sym.info is Map {
|
} else if mut sym.info is Map {
|
||||||
|
@ -1010,7 +1010,7 @@ pub fn (mut t Table) resolve_generic_by_names(generic_type Type, generic_names [
|
||||||
}
|
}
|
||||||
if type_changed {
|
if type_changed {
|
||||||
idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type)
|
idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type)
|
||||||
return new_type(idx)
|
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
|
@ -1041,13 +1041,13 @@ pub fn (mut t Table) resolve_generic_by_types(generic_type Type, from_types []Ty
|
||||||
}
|
}
|
||||||
if typ := t.resolve_generic_by_types(elem_type, from_types, to_types) {
|
if typ := t.resolve_generic_by_types(elem_type, from_types, to_types) {
|
||||||
idx := t.find_or_register_array_with_dims(typ, dims)
|
idx := t.find_or_register_array_with_dims(typ, dims)
|
||||||
return new_type(idx)
|
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
} else if sym.kind == .chan {
|
} else if sym.kind == .chan {
|
||||||
info := sym.info as Chan
|
info := sym.info as Chan
|
||||||
if typ := t.resolve_generic_by_types(info.elem_type, from_types, to_types) {
|
if typ := t.resolve_generic_by_types(info.elem_type, from_types, to_types) {
|
||||||
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
|
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
|
||||||
return new_type(idx)
|
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
} else if mut sym.info is MultiReturn {
|
} else if mut sym.info is MultiReturn {
|
||||||
mut types := []Type{}
|
mut types := []Type{}
|
||||||
|
@ -1062,7 +1062,7 @@ pub fn (mut t Table) resolve_generic_by_types(generic_type Type, from_types []Ty
|
||||||
}
|
}
|
||||||
if type_changed {
|
if type_changed {
|
||||||
idx := t.find_or_register_multi_return(types)
|
idx := t.find_or_register_multi_return(types)
|
||||||
return new_type(idx)
|
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
} else if mut sym.info is Map {
|
} else if mut sym.info is Map {
|
||||||
mut type_changed := false
|
mut type_changed := false
|
||||||
|
@ -1078,7 +1078,7 @@ pub fn (mut t Table) resolve_generic_by_types(generic_type Type, from_types []Ty
|
||||||
}
|
}
|
||||||
if type_changed {
|
if type_changed {
|
||||||
idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type)
|
idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type)
|
||||||
return new_type(idx)
|
return new_type(idx).derive(generic_type).clear_flag(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
|
|
|
@ -2207,26 +2207,7 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if func.generic_names.len > 0 {
|
if func.generic_names.len > 0 {
|
||||||
if param.typ.has_flag(.generic)
|
continue
|
||||||
&& func.generic_names.len == call_expr.generic_types.len {
|
|
||||||
if unwrap_typ := c.table.resolve_generic_by_names(param.typ, func.generic_names,
|
|
||||||
call_expr.generic_types)
|
|
||||||
{
|
|
||||||
if (unwrap_typ.idx() == typ.idx())
|
|
||||||
|| (unwrap_typ.is_int() && typ.is_int())
|
|
||||||
|| (unwrap_typ.is_float() && typ.is_float()) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
expected_sym := c.table.get_type_symbol(unwrap_typ)
|
|
||||||
got_sym := c.table.get_type_symbol(typ)
|
|
||||||
c.error('argument ${i + 1} got `$got_sym.name`, expected `$expected_sym.name`',
|
|
||||||
call_arg.pos)
|
|
||||||
} else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c.error('$err.msg in argument ${i + 1} to `$fn_name`', call_arg.pos)
|
c.error('$err.msg in argument ${i + 1} to `$fn_name`', call_arg.pos)
|
||||||
}
|
}
|
||||||
|
@ -2243,6 +2224,27 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type {
|
||||||
// no type arguments given in call, attempt implicit instantiation
|
// no type arguments given in call, attempt implicit instantiation
|
||||||
c.infer_fn_types(func, mut call_expr)
|
c.infer_fn_types(func, mut call_expr)
|
||||||
}
|
}
|
||||||
|
if func.generic_names.len > 0 {
|
||||||
|
for i, call_arg in call_expr.args {
|
||||||
|
param := if func.is_variadic && i >= func.params.len - 1 {
|
||||||
|
func.params[func.params.len - 1]
|
||||||
|
} else {
|
||||||
|
func.params[i]
|
||||||
|
}
|
||||||
|
c.expected_type = param.typ
|
||||||
|
typ := c.check_expr_opt_call(call_arg.expr, c.expr(call_arg.expr))
|
||||||
|
|
||||||
|
if param.typ.has_flag(.generic) && func.generic_names.len == call_expr.generic_types.len {
|
||||||
|
if unwrap_typ := c.table.resolve_generic_by_names(param.typ, func.generic_names,
|
||||||
|
call_expr.generic_types)
|
||||||
|
{
|
||||||
|
c.check_expected_call_arg(typ, unwrap_typ, call_expr.language) or {
|
||||||
|
c.error('$err.msg in argument ${i + 1} to `$fn_name`', call_arg.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if call_expr.generic_types.len > 0 && func.return_type != 0 {
|
if call_expr.generic_types.len > 0 && func.return_type != 0 {
|
||||||
if typ := c.table.resolve_generic_by_names(func.return_type, func.generic_names,
|
if typ := c.table.resolve_generic_by_names(func.return_type, func.generic_names,
|
||||||
call_expr.generic_types)
|
call_expr.generic_types)
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
vlib/v/checker/tests/generics_fn_called_arg_mismatch.vv:6:15: error: argument 1 got `int literal`, expected `bool`
|
vlib/v/checker/tests/generics_fn_called_arg_mismatch.vv:6:15: error: cannot use `int literal` as `bool` in argument 1 to `foo`
|
||||||
4 |
|
4 |
|
||||||
5 | fn main() {
|
5 | fn main() {
|
||||||
6 | foo<bool>(1)
|
6 | foo<bool>(1)
|
||||||
| ^
|
| ^
|
||||||
7 | foo<bool>(2.2)
|
7 | foo<bool>(2.2)
|
||||||
8 | foo<string>(true)
|
8 | foo<string>(true)
|
||||||
vlib/v/checker/tests/generics_fn_called_arg_mismatch.vv:7:15: error: argument 1 got `float literal`, expected `bool`
|
vlib/v/checker/tests/generics_fn_called_arg_mismatch.vv:7:15: error: cannot use `float literal` as `bool` in argument 1 to `foo`
|
||||||
5 | fn main() {
|
5 | fn main() {
|
||||||
6 | foo<bool>(1)
|
6 | foo<bool>(1)
|
||||||
7 | foo<bool>(2.2)
|
7 | foo<bool>(2.2)
|
||||||
| ~~~
|
| ~~~
|
||||||
8 | foo<string>(true)
|
8 | foo<string>(true)
|
||||||
9 | foo<int>('aaa')
|
9 | foo<int>('aaa')
|
||||||
vlib/v/checker/tests/generics_fn_called_arg_mismatch.vv:8:17: error: argument 1 got `bool`, expected `string`
|
vlib/v/checker/tests/generics_fn_called_arg_mismatch.vv:8:17: error: cannot use `bool` as `string` in argument 1 to `foo`
|
||||||
6 | foo<bool>(1)
|
6 | foo<bool>(1)
|
||||||
7 | foo<bool>(2.2)
|
7 | foo<bool>(2.2)
|
||||||
8 | foo<string>(true)
|
8 | foo<string>(true)
|
||||||
| ~~~~
|
| ~~~~
|
||||||
9 | foo<int>('aaa')
|
9 | foo<int>('aaa')
|
||||||
10 | }
|
10 | }
|
||||||
vlib/v/checker/tests/generics_fn_called_arg_mismatch.vv:9:14: error: argument 1 got `string`, expected `int`
|
vlib/v/checker/tests/generics_fn_called_arg_mismatch.vv:9:14: error: cannot use `string` as `int` in argument 1 to `foo`
|
||||||
7 | foo<bool>(2.2)
|
7 | foo<bool>(2.2)
|
||||||
8 | foo<string>(true)
|
8 | foo<string>(true)
|
||||||
9 | foo<int>('aaa')
|
9 | foo<int>('aaa')
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
vlib/v/checker/tests/generics_fn_called_variadic_arg_mismatch.vv:12:11: error: cannot use `[]int` as `int` in argument 1 to `max`
|
||||||
|
10 |
|
||||||
|
11 | fn main() {
|
||||||
|
12 | a := max([1, 2, 3, 4])
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
13 | println(a)
|
||||||
|
14 |
|
||||||
|
vlib/v/checker/tests/generics_fn_called_variadic_arg_mismatch.vv:15:16: error: cannot use `[]int` as `int` in argument 1 to `max`
|
||||||
|
13 | println(a)
|
||||||
|
14 |
|
||||||
|
15 | b := max<int>([1, 2, 3, 4])
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
16 | println(b)
|
||||||
|
17 | }
|
|
@ -0,0 +1,17 @@
|
||||||
|
fn max<T>(a ...T) T {
|
||||||
|
mut max := a[0]
|
||||||
|
for item in a[1..] {
|
||||||
|
if max < item {
|
||||||
|
max = item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
a := max([1, 2, 3, 4])
|
||||||
|
println(a)
|
||||||
|
|
||||||
|
b := max<int>([1, 2, 3, 4])
|
||||||
|
println(b)
|
||||||
|
}
|
Loading…
Reference in New Issue