Patch 8.2.0488
Problem:    Vim9: Compiling can break when using a lambda inside :def.
Solution:   Do not keep a pointer to the dfunc_T for longer time.
Files:      src/vim9compile.c, src/vim9.h


*** ../vim-8.2.0487/src/vim9compile.c   2020-03-31 23:13:05.758568664 +0200
--- src/vim9compile.c   2020-03-31 23:28:43.711140249 +0200
***************
*** 5029,5039 ****
   * Adds the function to "def_functions".
   * When "set_return_type" is set then set ufunc->uf_ret_type to the type of 
the
   * return statement (used for lambda).
   */
      void
  compile_def_function(ufunc_T *ufunc, int set_return_type)
  {
-     dfunc_T   *dfunc;
      char_u    *line = NULL;
      char_u    *p;
      exarg_T   ea;
--- 5029,5040 ----
   * Adds the function to "def_functions".
   * When "set_return_type" is set then set ufunc->uf_ret_type to the type of 
the
   * return statement (used for lambda).
+  * This can be used recursively through compile_lambda(), which may reallocate
+  * "def_functions".
   */
      void
  compile_def_function(ufunc_T *ufunc, int set_return_type)
  {
      char_u    *line = NULL;
      char_u    *p;
      exarg_T   ea;
***************
*** 5046,5070 ****
      sctx_T    save_current_sctx = current_sctx;
      int               emsg_before = called_emsg;
  
-     if (ufunc->uf_dfunc_idx >= 0)
      {
!       // Redefining a function that was compiled before.
!       dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
  
!       // Free old instructions.
!       delete_def_function_contents(dfunc);
!     }
!     else
!     {
!       // Add the function to "def_functions".
!       if (ga_grow(&def_functions, 1) == FAIL)
!           return;
!       dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
!       vim_memset(dfunc, 0, sizeof(dfunc_T));
!       dfunc->df_idx = def_functions.ga_len;
!       ufunc->uf_dfunc_idx = dfunc->df_idx;
!       dfunc->df_ufunc = ufunc;
!       ++def_functions.ga_len;
      }
  
      vim_memset(&cctx, 0, sizeof(cctx));
--- 5047,5075 ----
      sctx_T    save_current_sctx = current_sctx;
      int               emsg_before = called_emsg;
  
      {
!       dfunc_T *dfunc;  // may be invalidated by compile_lambda()
  
!       if (ufunc->uf_dfunc_idx >= 0)
!       {
!           // Redefining a function that was compiled before.
!           dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
! 
!           // Free old instructions.
!           delete_def_function_contents(dfunc);
!       }
!       else
!       {
!           // Add the function to "def_functions".
!           if (ga_grow(&def_functions, 1) == FAIL)
!               return;
!           dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
!           vim_memset(dfunc, 0, sizeof(dfunc_T));
!           dfunc->df_idx = def_functions.ga_len;
!           ufunc->uf_dfunc_idx = dfunc->df_idx;
!           dfunc->df_ufunc = ufunc;
!           ++def_functions.ga_len;
!       }
      }
  
      vim_memset(&cctx, 0, sizeof(cctx));
***************
*** 5414,5423 ****
        generate_instr(&cctx, ISN_RETURN);
      }
  
!     dfunc->df_deleted = FALSE;
!     dfunc->df_instr = instr->ga_data;
!     dfunc->df_instr_count = instr->ga_len;
!     dfunc->df_varcount = cctx.ctx_max_local;
  
      ret = OK;
  
--- 5419,5432 ----
        generate_instr(&cctx, ISN_RETURN);
      }
  
!     {
!       dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
!                                                        + ufunc->uf_dfunc_idx;
!       dfunc->df_deleted = FALSE;
!       dfunc->df_instr = instr->ga_data;
!       dfunc->df_instr_count = instr->ga_len;
!       dfunc->df_varcount = cctx.ctx_max_local;
!     }
  
      ret = OK;
  
***************
*** 5425,5430 ****
--- 5434,5441 ----
      if (ret == FAIL)
      {
        int idx;
+       dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
+                                                        + ufunc->uf_dfunc_idx;
  
        for (idx = 0; idx < instr->ga_len; ++idx)
            delete_instr(((isn_T *)instr->ga_data) + idx);
*** ../vim-8.2.0487/src/vim9.h  2020-03-31 23:13:05.758568664 +0200
--- src/vim9.h  2020-03-31 23:29:10.395041154 +0200
***************
*** 257,263 ****
  // Functions defined with :def are stored in this growarray.
  // They are never removed, so that they can be found by index.
  // Deleted functions have the df_deleted flag set.
! garray_T def_functions = {0, 0, sizeof(dfunc_T), 200, NULL};
  #else
  extern garray_T def_functions;
  #endif
--- 257,263 ----
  // Functions defined with :def are stored in this growarray.
  // They are never removed, so that they can be found by index.
  // Deleted functions have the df_deleted flag set.
! garray_T def_functions = {0, 0, sizeof(dfunc_T), 50, NULL};
  #else
  extern garray_T def_functions;
  #endif
*** ../vim-8.2.0487/src/version.c       2020-03-31 23:13:05.762568650 +0200
--- src/version.c       2020-03-31 23:30:53.690659160 +0200
***************
*** 740,741 ****
--- 740,743 ----
  {   /* Add new patch number below this line */
+ /**/
+     488,
  /**/

-- 
If "R" is Reverse, how come "D" is FORWARD?

 /// 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/202003312133.02VLX0eo026363%40masaka.moolenaar.net.

Raspunde prin e-mail lui