From 78bcda14c4a0efc4a9d8c7713a7b9c34154164a4 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 13 Oct 2020 13:15:25 +0100 Subject: [PATCH] checker: infer T from parameter of type `[]T` (#6611) --- vlib/v/checker/check_types.v | 17 ++++++++++++++--- vlib/v/tests/generic_fn_infer_modifier_test.v | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 vlib/v/tests/generic_fn_infer_modifier_test.v diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 8dbf5ad84b..7bc6896f87 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -376,15 +376,26 @@ pub fn (c &Checker) check_sumtype_compatibility(a, b table.Type) bool { pub fn (mut c Checker) infer_fn_types(f table.Fn, mut call_expr ast.CallExpr) { gt_name := 'T' mut typ := table.void_type - for i, arg in f.params { - if arg.type_source_name == gt_name { - typ = call_expr.args[i].typ + for i, param in f.params { + arg := call_expr.args[i] + if param.type_source_name == gt_name { + typ = arg.typ + break + } + arg_sym := c.table.get_type_symbol(arg.typ) + if arg_sym.kind == .array && param.type_source_name == '[]$gt_name' { + info := arg_sym.info as table.Array + typ = info.elem_type break } } if typ == table.void_type { c.error('could not infer generic type `$gt_name` in call to `$f.name`', call_expr.pos) } else { + if c.pref.is_verbose { + s := c.table.type_to_str(typ) + println('inferred `$f.name<$s>`') + } c.table.register_fn_gen_type(f.name, typ) call_expr.generic_type = typ } diff --git a/vlib/v/tests/generic_fn_infer_modifier_test.v b/vlib/v/tests/generic_fn_infer_modifier_test.v new file mode 100644 index 0000000000..7e813b5b0f --- /dev/null +++ b/vlib/v/tests/generic_fn_infer_modifier_test.v @@ -0,0 +1,16 @@ +fn f_array(a []T) T { + return a[0] +} + +fn g_array(mut a []T) { + a[0] = a[1] +} + +fn test_array() { + mut a := [7, 8] + r := f_array(a) + assert r == 7 + + g_array(mut a) + assert a[0] == 8 +}