diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 3a187774ec..bff9c9f8f1 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -1863,6 +1863,62 @@ def Test_assign_lambda() v9.CheckDefAndScriptFailure(lines, 'E1051:') enddef +def Test_assign_funcref_args() + # unspecified arguments match everything, including varargs + var lines =<< trim END + vim9script + + var FuncUnknown: func: number + + FuncUnknown = (v): number => v + assert_equal(5, FuncUnknown(5)) + + FuncUnknown = (v1, v2): number => v1 + v2 + assert_equal(7, FuncUnknown(3, 4)) + + FuncUnknown = (...v1): number => v1[0] + v1[1] + len(v1) * 1000 + assert_equal(4007, FuncUnknown(3, 4, 5, 6)) + + FuncUnknown = (v: list): number => v[0] + v[1] + len(v) * 1000 + assert_equal(5009, FuncUnknown([4, 5, 6, 7, 8])) + END + v9.CheckScriptSuccess(lines) + + # varargs must match + lines =<< trim END + vim9script + var FuncAnyVA: func(...any): number + FuncAnyVA = (v): number => v + END + v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(...any): number but got func(any): number') + + # varargs must match + lines =<< trim END + vim9script + var FuncAnyVA: func(...any): number + FuncAnyVA = (v1, v2): number => v1 + v2 + END + v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(...any): number but got func(any, any): number') + + # varargs must match + lines =<< trim END + vim9script + var FuncAnyVA: func(...any): number + FuncAnyVA = (v1: list): number => 3 + END + v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(...any): number but got func(list): number') +enddef + +def Test_assign_funcref_arg_any() + var lines =<< trim END + vim9script + var FuncAnyVA: func(any): number + FuncAnyVA = (v): number => v + END + # TODO: Verify this should succeed. + v9.CheckScriptSuccess(lines) +enddef + def Test_heredoc() # simple heredoc var lines =<< trim END diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim index 8b08dc1b2d..01cf3e128f 100644 --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -6953,6 +6953,21 @@ def Test_extended_obj_method_type_check() endclass END v9.CheckSourceFailure(lines, 'E1383: Method "Doit": type mismatch, expected func(object): object but got func(object): object', 20) + + # check varargs type mismatch + lines =<< trim END + vim9script + + class B + def F(...xxx: list) + enddef + endclass + class C extends B + def F(xxx: list) + enddef + endclass + END + v9.CheckSourceFailure(lines, 'E1383: Method "F": type mismatch, expected func(...list) but got func(list)', 10) enddef " Test type checking for class variable in assignments @@ -7431,6 +7446,54 @@ def Test_funcref_argtype_returntype_check() v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object): object but got func(object): object', 1) enddef +def Test_funcref_argtype_invariance_check() + var lines =<< trim END + vim9script + + class A + endclass + class B extends A + endclass + class C extends B + endclass + + var Func: func(B): number + Func = (o: B): number => 3 + assert_equal(3, Func(B.new())) + END + v9.CheckSourceSuccess(lines) + + lines =<< trim END + vim9script + + class A + endclass + class B extends A + endclass + class C extends B + endclass + + var Func: func(B): number + Func = (o: A): number => 3 + END + v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object): number but got func(object): number', 11) + + lines =<< trim END + vim9script + + class A + endclass + class B extends A + endclass + class C extends B + endclass + + var Func: func(B): number + Func = (o: C): number => 3 + END + v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected func(object): number but got func(object): number', 11) +enddef + " Test for using an operator (e.g. +) with an assignment def Test_op_and_assignment() # Using += with a class variable diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 597a10c581..701a2f085d 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1995,7 +1995,7 @@ def Test_varargs_mismatch() var res = Map((v) => str2nr(v)) assert_equal(12, res) END - v9.CheckScriptSuccess(lines) + v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected func(...any): number but got func(any): number') enddef def Test_using_var_as_arg() diff --git a/src/version.c b/src/version.c index 0b1bf3138e..bad07e6446 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2043, /**/ 2042, /**/ diff --git a/src/vim9type.c b/src/vim9type.c index 00ee76b487..6a5848792b 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -884,6 +884,11 @@ check_type_maybe( else ret = MAYBE; } + if (ret != FAIL + && ((expected->tt_flags & TTFLAG_VARARGS) + != (actual->tt_flags & TTFLAG_VARARGS)) + && expected->tt_argcount != -1) + ret = FAIL; if (ret != FAIL && expected->tt_argcount != -1 && actual->tt_min_argcount != -1 && (actual->tt_argcount == -1