From ef7454b5e28b87b1efe7be46c468960bd759c136 Mon Sep 17 00:00:00 2001 From: spaceface Date: Sat, 8 May 2021 21:26:13 +0200 Subject: [PATCH] checker: fix calling functions with variadic interface parameters (#10052) --- vlib/v/checker/checker.v | 13 +++++++++++-- vlib/v/tests/interface_variadic_test.v | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 6024f27eb59f69..c54c5a7d2730ce 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1854,7 +1854,12 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type { c.error('when forwarding a variadic variable, it must be the final argument', arg.pos) } - if exp_arg_sym.kind == .interface_ { + mut final_arg_sym := exp_arg_sym + if method.is_variadic && exp_arg_sym.info is ast.Array { + final_arg_sym = c.table.get_type_symbol(exp_arg_sym.array_info().elem_type) + } + // Handle expected interface + if final_arg_sym.kind == .interface_ { c.type_implements(got_arg_typ, exp_arg_typ, arg.expr.position()) continue } @@ -2436,8 +2441,12 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type { c.fail_if_unreadable(call_arg.expr, typ, 'argument') } } + mut final_arg_sym := arg_typ_sym + if func.is_variadic && arg_typ_sym.info is ast.Array { + final_arg_sym = c.table.get_type_symbol(arg_typ_sym.array_info().elem_type) + } // Handle expected interface - if arg_typ_sym.kind == .interface_ { + if final_arg_sym.kind == .interface_ { c.type_implements(typ, param.typ, call_arg.expr.position()) continue } diff --git a/vlib/v/tests/interface_variadic_test.v b/vlib/v/tests/interface_variadic_test.v index e49b6ba5cf4105..020af540e1df54 100644 --- a/vlib/v/tests/interface_variadic_test.v +++ b/vlib/v/tests/interface_variadic_test.v @@ -23,3 +23,20 @@ fn test_variadic_multiple_args() { assert a[0].method(0.0, 1.0) == '[0, 1]' } + +interface Animal {} + +struct Cat {} + +struct Dog {} + +fn test_variadic_interface_fn_arg() { + c := Cat{} + d := Dog{} + check_animals(c, d) +} + +fn check_animals(animals ...Animal) { + assert animals[0] is Cat + assert animals[1] is Dog +}