From d349c1d86d4df58aef86505354673c3243e7b07c Mon Sep 17 00:00:00 2001 From: yuyi Date: Fri, 17 Mar 2023 03:19:03 +0800 Subject: [PATCH] checker: check generic fn call argument type mismatch (#17680) --- vlib/v/checker/fn.v | 3 ++- .../tests/generic_fn_call_arg_mismatch_err.out | 7 +++++++ .../tests/generic_fn_call_arg_mismatch_err.vv | 12 ++++++++++++ vlib/v/token/keywords_matcher_trie.v | 2 +- vlib/x/json2/encoder.v | 4 ++-- 5 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 vlib/v/checker/tests/generic_fn_call_arg_mismatch_err.out create mode 100644 vlib/v/checker/tests/generic_fn_call_arg_mismatch_err.vv diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index d6180bcfb9..138464b5c1 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1792,7 +1792,8 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type { c.error('literal argument cannot be passed as reference parameter `${c.table.type_to_str(param.typ)}`', arg.pos) } - c.check_expected_call_arg(got_arg_typ, exp_arg_typ, node.language, arg) or { + c.check_expected_call_arg(c.unwrap_generic(got_arg_typ), exp_arg_typ, node.language, + arg) or { // str method, allow type with str method if fn arg is string // Passing an int or a string array produces a c error here // Deleting this condition results in propper V error messages diff --git a/vlib/v/checker/tests/generic_fn_call_arg_mismatch_err.out b/vlib/v/checker/tests/generic_fn_call_arg_mismatch_err.out new file mode 100644 index 0000000000..c92a7a333a --- /dev/null +++ b/vlib/v/checker/tests/generic_fn_call_arg_mismatch_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/generic_fn_call_arg_mismatch_err.vv:7:17: error: cannot use `int` as `string` in argument 1 to `strings.Builder.write_string` + 5 | var := T{} + 6 | ptr := &var + 7 | b.write_string(*ptr) + | ~~~~ + 8 | } + 9 | diff --git a/vlib/v/checker/tests/generic_fn_call_arg_mismatch_err.vv b/vlib/v/checker/tests/generic_fn_call_arg_mismatch_err.vv new file mode 100644 index 0000000000..8e8deffa9a --- /dev/null +++ b/vlib/v/checker/tests/generic_fn_call_arg_mismatch_err.vv @@ -0,0 +1,12 @@ +import strings + +fn my_fn[T]() { + mut b := strings.new_builder(16) + var := T{} + ptr := &var + b.write_string(*ptr) +} + +fn main() { + my_fn[int]() +} diff --git a/vlib/v/token/keywords_matcher_trie.v b/vlib/v/token/keywords_matcher_trie.v index eee07a37f6..517a823944 100644 --- a/vlib/v/token/keywords_matcher_trie.v +++ b/vlib/v/token/keywords_matcher_trie.v @@ -70,7 +70,7 @@ pub fn new_keywords_matcher_trie[T](kw_map map[string]T) KeywordsMatcherTrie { km.nodes << &TrieNode(0) } for k, v in kw_map { - km.add_word(k, v) + km.add_word(k, int(v)) } // dump(km.min_len) // dump(km.max_len) diff --git a/vlib/x/json2/encoder.v b/vlib/x/json2/encoder.v index 0eff6a24d8..82de823f5c 100644 --- a/vlib/x/json2/encoder.v +++ b/vlib/x/json2/encoder.v @@ -130,14 +130,14 @@ fn (e &Encoder) encode_value_with_level[T](val T, level int, mut wr io.Writer) ! e.encode_any(val, level, mut wr)! } $else $if T is []Any { e.encode_any(val, level, mut wr)! - } $else $if T in [Null, bool, $Float, $Int] { - e.encode_any(val, level, mut wr)! } $else $if T is Encodable { wr.write(val.json_str().bytes())! } $else $if T is $Struct { e.encode_struct(val, level, mut wr)! } $else $if T is $Enum { e.encode_any(Any(int(val)), level, mut wr)! + } $else $if T in [Null, bool, $Float, $Int] { + e.encode_any(val, level, mut wr)! } $else { // dump(val.str()) return error('cannot encode value with ${typeof(val).name} type')