From 329a6c974ebf762fddee0fa856e9d0da7fc3b326 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sun, 6 Jun 2021 06:11:08 +0800 Subject: [PATCH] table, checker, cgen: implement generic fn infering fixed array (#10352) --- vlib/v/ast/table.v | 8 +++++ vlib/v/checker/check_types.v | 17 +++++++++++ vlib/v/gen/c/cgen.v | 2 +- .../tests/generic_fn_infer_fixed_array_test.v | 30 +++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/generic_fn_infer_fixed_array_test.v diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index f8da55a370..3220949ce0 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -1144,6 +1144,14 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name idx := t.find_or_register_array_with_dims(typ, dims) return new_type(idx).derive(generic_type).clear_flag(.generic) } + } else if sym.kind == .array_fixed { + info := sym.info as ArrayFixed + if typ := t.resolve_generic_to_concrete(info.elem_type, generic_names, concrete_types, + is_inst) + { + idx := t.find_or_register_array_fixed(typ, info.size, None{}) + return new_type(idx).derive(generic_type).clear_flag(.generic) + } } else if mut sym.info is Chan { if typ := t.resolve_generic_to_concrete(sym.info.elem_type, generic_names, concrete_types, is_inst) diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 063e83e6d8..1c8874f486 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -568,6 +568,23 @@ pub fn (mut c Checker) infer_fn_generic_types(f ast.Fn, mut call_expr ast.CallEx break } } + } else if arg_sym.kind == .array_fixed && param_type_sym.kind == .array_fixed { + mut arg_elem_info := arg_sym.info as ast.ArrayFixed + mut param_elem_info := param_type_sym.info as ast.ArrayFixed + mut arg_elem_sym := c.table.get_type_symbol(arg_elem_info.elem_type) + mut param_elem_sym := c.table.get_type_symbol(param_elem_info.elem_type) + for { + if arg_elem_sym.kind == .array_fixed && param_elem_sym.kind == .array_fixed + && param_elem_sym.name !in c.table.cur_fn.generic_names { + arg_elem_info = arg_elem_sym.info as ast.ArrayFixed + arg_elem_sym = c.table.get_type_symbol(arg_elem_info.elem_type) + param_elem_info = param_elem_sym.info as ast.ArrayFixed + param_elem_sym = c.table.get_type_symbol(param_elem_info.elem_type) + } else { + to_set = arg_elem_info.elem_type + break + } + } } else if param.typ.has_flag(.variadic) { to_set = c.table.mktyp(arg.typ) } else if arg_sym.kind == .struct_ && param.typ.has_flag(.generic) { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index e4b95b87b0..ca08a14d98 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5734,7 +5734,7 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) { } ast.ArrayFixed { elem_sym := g.table.get_type_symbol(typ.info.elem_type) - if !elem_sym.is_builtin() { + if !elem_sym.is_builtin() && !typ.info.elem_type.has_flag(.generic) { // .array_fixed { styp := typ.cname // array_fixed_char_300 => char x[300] diff --git a/vlib/v/tests/generic_fn_infer_fixed_array_test.v b/vlib/v/tests/generic_fn_infer_fixed_array_test.v new file mode 100644 index 0000000000..3174b105da --- /dev/null +++ b/vlib/v/tests/generic_fn_infer_fixed_array_test.v @@ -0,0 +1,30 @@ +fn get_element(arr [3]T) string { + return '${arr[1]}' +} + +fn test_generic_fn_infer_fixed_array() { + a := [1, 2, 3]! + mut ret := get_element(a) + println(ret) + assert ret == '2' + + b := ['a', 'b', 'c']! + ret = get_element(b) + println(ret) + assert ret == 'b' + + c := [1.1, 2.2, 3.3]! + ret = get_element(c) + println(ret) + assert ret == '2.2' + + d := [`a`, `b`, `c`]! + ret = get_element(d) + println(ret) + assert ret == 'b' + + e := [true, false, true]! + ret = get_element(e) + println(ret) + assert ret == 'false' +}