Patch 8.2.0820
Problem:    Vim9: function type isn't set until compiled.
Solution:   Set function type early.
Files:      src/vim9compile.c, src/proto/vim9compile.pro, src/userfunc.c,
            src/testdir/test_vim9_func.vim


*** ../vim-8.2.0819/src/vim9compile.c   2020-05-24 23:00:06.444196001 +0200
--- src/vim9compile.c   2020-05-24 23:37:21.634564583 +0200
***************
*** 6763,6816 ****
            ufunc->uf_flags |= FC_CLOSURE;
      }
  
-     {
-       int varargs = ufunc->uf_va_name != NULL;
-       int argcount = ufunc->uf_args.ga_len;
- 
-       // Create a type for the function, with the return type and any
-       // argument types.
-       // A vararg is included in uf_args.ga_len but not in uf_arg_types.
-       // The type is included in "tt_args".
-       if (argcount > 0 || varargs)
-       {
-           ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
-                                              argcount, &ufunc->uf_type_list);
-           // Add argument types to the function type.
-           if (func_type_add_arg_types(ufunc->uf_func_type,
-                                       argcount + varargs,
-                                       &ufunc->uf_type_list) == FAIL)
-           {
-               ret = FAIL;
-               goto erret;
-           }
-           ufunc->uf_func_type->tt_argcount = argcount + varargs;
-           ufunc->uf_func_type->tt_min_argcount =
-                                         argcount - ufunc->uf_def_args.ga_len;
-           if (ufunc->uf_arg_types == NULL)
-           {
-               int i;
- 
-               // lambda does not have argument types.
-               for (i = 0; i < argcount; ++i)
-                   ufunc->uf_func_type->tt_args[i] = &t_any;
-           }
-           else
-               mch_memmove(ufunc->uf_func_type->tt_args,
-                            ufunc->uf_arg_types, sizeof(type_T *) * argcount);
-           if (varargs)
-           {
-               ufunc->uf_func_type->tt_args[argcount] =
-                       ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
-               ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
-           }
-       }
-       else
-           // No arguments, can use a predefined type.
-           ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
-                                              argcount, &ufunc->uf_type_list);
- 
-     }
- 
      ret = OK;
  
  erret:
--- 6763,6768 ----
***************
*** 6847,6852 ****
--- 6799,6851 ----
      return ret;
  }
  
+     void
+ set_function_type(ufunc_T *ufunc)
+ {
+     int varargs = ufunc->uf_va_name != NULL;
+     int argcount = ufunc->uf_args.ga_len;
+ 
+     // Create a type for the function, with the return type and any
+     // argument types.
+     // A vararg is included in uf_args.ga_len but not in uf_arg_types.
+     // The type is included in "tt_args".
+     if (argcount > 0 || varargs)
+     {
+       ufunc->uf_func_type = alloc_func_type(ufunc->uf_ret_type,
+                                          argcount, &ufunc->uf_type_list);
+       // Add argument types to the function type.
+       if (func_type_add_arg_types(ufunc->uf_func_type,
+                                   argcount + varargs,
+                                   &ufunc->uf_type_list) == FAIL)
+           return;
+       ufunc->uf_func_type->tt_argcount = argcount + varargs;
+       ufunc->uf_func_type->tt_min_argcount =
+                                     argcount - ufunc->uf_def_args.ga_len;
+       if (ufunc->uf_arg_types == NULL)
+       {
+           int i;
+ 
+           // lambda does not have argument types.
+           for (i = 0; i < argcount; ++i)
+               ufunc->uf_func_type->tt_args[i] = &t_any;
+       }
+       else
+           mch_memmove(ufunc->uf_func_type->tt_args,
+                        ufunc->uf_arg_types, sizeof(type_T *) * argcount);
+       if (varargs)
+       {
+           ufunc->uf_func_type->tt_args[argcount] =
+                   ufunc->uf_va_type == NULL ? &t_any : ufunc->uf_va_type;
+           ufunc->uf_func_type->tt_flags = TTFLAG_VARARGS;
+       }
+     }
+     else
+       // No arguments, can use a predefined type.
+       ufunc->uf_func_type = get_func_type(ufunc->uf_ret_type,
+                                          argcount, &ufunc->uf_type_list);
+ }
+ 
+ 
  /*
   * Delete an instruction, free what it contains.
   */
*** ../vim-8.2.0819/src/proto/vim9compile.pro   2020-05-24 23:00:06.444196001 
+0200
--- src/proto/vim9compile.pro   2020-05-24 23:37:23.174560943 +0200
***************
*** 10,15 ****
--- 10,16 ----
  int assignment_len(char_u *p, int *heredoc);
  int check_vim9_unlet(char_u *name);
  int compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T 
*outer_cctx);
+ void set_function_type(ufunc_T *ufunc);
  void delete_instr(isn_T *isn);
  void delete_def_function(ufunc_T *ufunc);
  void free_def_functions(void);
*** ../vim-8.2.0819/src/userfunc.c      2020-05-24 23:00:06.440196016 +0200
--- src/userfunc.c      2020-05-24 23:38:22.242420368 +0200
***************
*** 3284,3289 ****
--- 3284,3292 ----
        is_export = FALSE;
      }
  
+     if (eap->cmdidx == CMD_def)
+       set_function_type(fp);
+ 
      goto ret_free;
  
  erret:
*** ../vim-8.2.0819/src/testdir/test_vim9_func.vim      2020-05-24 
23:00:06.444196001 +0200
--- src/testdir/test_vim9_func.vim      2020-05-24 23:39:07.442311631 +0200
***************
*** 560,567 ****
    RefVoid = FuncNoArgNoRet
    RefVoid = FuncOneArgNoRet
    CheckDefFailure(['let RefVoid: func: void', 'RefVoid = 
FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): 
number')
! "  TODO: these should fail
! "  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = 
FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): 
string')
  
    let RefAny: func(): any
    RefAny = FuncNoArgRetNumber
--- 560,566 ----
    RefVoid = FuncNoArgNoRet
    RefVoid = FuncOneArgNoRet
    CheckDefFailure(['let RefVoid: func: void', 'RefVoid = 
FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): 
number')
!   CheckDefFailure(['let RefVoid: func: void', 'RefVoid = 
FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): 
string')
  
    let RefAny: func(): any
    RefAny = FuncNoArgRetNumber
***************
*** 573,580 ****
    RefNr = FuncNoArgRetNumber
    RefNr = FuncOneArgRetNumber
    CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 
'E1013: type mismatch, expected func(): number but got func()')
! "  TODO: should fail
! "  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 
'E1013: type mismatch, expected func(): number but got func(): string')
  
    let RefStr: func: string
    RefStr = FuncNoArgRetString
--- 572,578 ----
    RefNr = FuncNoArgRetNumber
    RefNr = FuncOneArgRetNumber
    CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 
'E1013: type mismatch, expected func(): number but got func()')
!   CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 
'E1013: type mismatch, expected func(): number but got func(): string')
  
    let RefStr: func: string
    RefStr = FuncNoArgRetString
***************
*** 589,598 ****
    CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: 
type mismatch, expected func() but got func(): number')
    CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: 
type mismatch, expected func() but got func(number)')
    CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: 
type mismatch, expected func() but got func(number): number')
! "  TODO: these don't fail
! "  CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 
'E1013: type mismatch, expected func(bool) but got func(bool, number)')
! "  CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 
'E1013: type mismatch, expected func(?bool) but got func(bool, number)')
! "  CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 
'E1013: type mismatch, expected func(...bool) but got func(bool, number)')
  
    call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
    call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
--- 587,595 ----
    CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: 
type mismatch, expected func() but got func(): number')
    CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: 
type mismatch, expected func() but got func(number)')
    CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: 
type mismatch, expected func() but got func(number): number')
!   CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: 
type mismatch, expected func(bool) but got func(bool, number)')
!   CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 
'E1013: type mismatch, expected func(?bool) but got func(bool, number)')
!   CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 
'E1013: type mismatch, expected func(...bool) but got func(bool, number)')
  
    call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
    call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
*** ../vim-8.2.0819/src/version.c       2020-05-24 23:14:20.053504523 +0200
--- src/version.c       2020-05-24 23:37:05.554602524 +0200
***************
*** 748,749 ****
--- 748,751 ----
  {   /* Add new patch number below this line */
+ /**/
+     820,
  /**/

-- 
If Apple would build a car...
... it would be powered by the sun, be reliable, five times
as fast and twice as easy to drive; but would only run on
five percent of the roads.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202005242145.04OLjsII151409%40masaka.moolenaar.net.

Raspunde prin e-mail lui