Patch 8.2.3788
Problem:    Lambda for option that is a function may be garbage collected.
Solution:   Set a reference in the funcref. (Yegappan Lakshmanan,
            closes #9330)
Files:      src/eval.c, src/evalbuffer.c, src/evalvars.c, src/gui_xim.c,
            src/insexpand.c, src/ops.c, src/proto/eval.pro,
            src/proto/gui_xim.pro, src/proto/insexpand.pro, src/proto/ops.pro,
            src/proto/tag.pro, src/quickfix.c, src/tag.c,
            src/testdir/test_iminsert.vim, src/testdir/test_ins_complete.vim,
            src/testdir/test_normal.vim, src/testdir/test_quickfix.vim,
            src/testdir/test_tagfunc.vim


*** ../vim-8.2.3787/src/eval.c  2021-12-11 16:13:32.227721221 +0000
--- src/eval.c  2021-12-12 16:20:28.785487698 +0000
***************
*** 4516,4521 ****
--- 4516,4533 ----
      // callbacks in buffers
      abort = abort || set_ref_in_buffers(copyID);
  
+     // 'completefunc', 'omnifunc' and 'thesaurusfunc' callbacks
+     abort = abort || set_ref_in_insexpand_funcs(copyID);
+ 
+     // 'operatorfunc' callback
+     abort = abort || set_ref_in_opfunc(copyID);
+ 
+     // 'tagfunc' callback
+     abort = abort || set_ref_in_tagfunc(copyID);
+ 
+     // 'imactivatefunc' and 'imstatusfunc' callbacks
+     abort = abort || set_ref_in_im_funcs(copyID);
+ 
  #ifdef FEAT_LUA
      abort = abort || set_ref_in_lua(copyID);
  #endif
***************
*** 4744,4749 ****
--- 4756,4777 ----
  }
  
  /*
+  * Mark the partial in callback 'cb' with "copyID".
+  */
+     int
+ set_ref_in_callback(callback_T *cb, int copyID)
+ {
+     typval_T tv;
+ 
+     if (cb->cb_name == NULL || *cb->cb_name == NUL || cb->cb_partial == NULL)
+       return FALSE;
+ 
+     tv.v_type = VAR_PARTIAL;
+     tv.vval.v_partial = cb->cb_partial;
+     return set_ref_in_item(&tv, copyID, NULL, NULL);
+ }
+ 
+ /*
   * Mark all lists and dicts referenced through typval "tv" with "copyID".
   * "list_stack" is used to add lists to be marked.  Can be NULL.
   * "ht_stack" is used to add hashtabs to be marked.  Can be NULL.
*** ../vim-8.2.3787/src/evalbuffer.c    2021-07-30 20:32:41.444722506 +0100
--- src/evalbuffer.c    2021-12-12 16:20:28.789487687 +0000
***************
*** 26,56 ****
      FOR_ALL_BUFFERS(bp)
      {
        listener_T *lnr;
-       typval_T tv;
  
        for (lnr = bp->b_listener; !abort && lnr != NULL; lnr = lnr->lr_next)
!       {
!           if (lnr->lr_callback.cb_partial != NULL)
!           {
!               tv.v_type = VAR_PARTIAL;
!               tv.vval.v_partial = lnr->lr_callback.cb_partial;
!               abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
!           }
!       }
  # ifdef FEAT_JOB_CHANNEL
!       if (!abort && bp->b_prompt_callback.cb_partial != NULL)
!       {
!           tv.v_type = VAR_PARTIAL;
!           tv.vval.v_partial = bp->b_prompt_callback.cb_partial;
!           abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
!       }
!       if (!abort && bp->b_prompt_interrupt.cb_partial != NULL)
!       {
!           tv.v_type = VAR_PARTIAL;
!           tv.vval.v_partial = bp->b_prompt_interrupt.cb_partial;
!           abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
!       }
  # endif
        if (abort)
            break;
      }
--- 26,50 ----
      FOR_ALL_BUFFERS(bp)
      {
        listener_T *lnr;
  
        for (lnr = bp->b_listener; !abort && lnr != NULL; lnr = lnr->lr_next)
!           abort = abort || set_ref_in_callback(&lnr->lr_callback, copyID);
  # ifdef FEAT_JOB_CHANNEL
!       if (!abort)
!           abort = abort || set_ref_in_callback(&bp->b_prompt_callback, 
copyID);
!       if (!abort)
!           abort = abort || set_ref_in_callback(&bp->b_prompt_interrupt, 
copyID);
  # endif
+ #ifdef FEAT_COMPL_FUNC
+       if (!abort)
+           abort = abort || set_ref_in_callback(&bp->b_cfu_cb, copyID);
+       if (!abort)
+           abort = abort || set_ref_in_callback(&bp->b_ofu_cb, copyID);
+       if (!abort)
+           abort = abort || set_ref_in_callback(&bp->b_tsrfu_cb, copyID);
+ #endif
+       if (!abort)
+           abort = abort || set_ref_in_callback(&bp->b_tfu_cb, copyID);
        if (abort)
            break;
      }
*** ../vim-8.2.3787/src/evalvars.c      2021-12-11 13:54:43.123245009 +0000
--- src/evalvars.c      2021-12-12 16:20:28.789487687 +0000
***************
*** 1395,1401 ****
        char_u      *tofree = NULL;
        char_u      numbuf[NUMBUFLEN];
  
- 
        c1 = *p;
        *p = NUL;
  
--- 1395,1400 ----
*** ../vim-8.2.3787/src/gui_xim.c       2021-12-04 14:02:25.457024636 +0000
--- src/gui_xim.c       2021-12-12 16:20:28.789487687 +0000
***************
*** 117,123 ****
      void
  free_xim_stuff(void)
  {
! #if defined(FEAT_EVAL) && \
      (defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
      free_callback(&imaf_cb);
      free_callback(&imsf_cb);
--- 117,123 ----
      void
  free_xim_stuff(void)
  {
! # if defined(FEAT_EVAL) && \
      (defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
      free_callback(&imaf_cb);
      free_callback(&imsf_cb);
***************
*** 125,130 ****
--- 125,148 ----
  }
  #endif
  
+ /*
+  * Mark the global 'imactivatefunc' and 'imstatusfunc' callbacks with 'copyID'
+  * so that they are not garbage collected.
+  */
+     int
+ set_ref_in_im_funcs(int copyID UNUSED)
+ {
+     int abort = FALSE;
+ 
+ #if defined(FEAT_EVAL) && \
+     (defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
+     abort = set_ref_in_callback(&imaf_cb, copyID);
+     abort = abort || set_ref_in_callback(&imsf_cb, copyID);
+ #endif
+ 
+     return abort;
+ }
+ 
  
  #if defined(FEAT_XIM) || defined(PROTO)
  
*** ../vim-8.2.3787/src/insexpand.c     2021-12-07 12:23:53.987565086 +0000
--- src/insexpand.c     2021-12-12 16:20:28.789487687 +0000
***************
*** 2341,2346 ****
--- 2341,2361 ----
      return retval;
  }
  
+ /*
+  * Mark the global 'completefunc' 'omnifunc' and 'thesaurusfunc' callbacks 
with
+  * 'copyID' so that they are not garbage collected.
+  */
+     int
+ set_ref_in_insexpand_funcs(int copyID)
+ {
+     int abort = FALSE;
+ 
+     abort = set_ref_in_callback(&cfu_cb, copyID);
+     abort = abort || set_ref_in_callback(&ofu_cb, copyID);
+     abort = abort || set_ref_in_callback(&tsrfu_cb, copyID);
+ 
+     return abort;
+ }
  
  /*
   * Get the user-defined completion function name for completion 'type'
*** ../vim-8.2.3787/src/ops.c   2021-11-27 22:47:38.488624918 +0000
--- src/ops.c   2021-12-12 16:20:28.789487687 +0000
***************
*** 3341,3353 ****
      void
  free_operatorfunc_option(void)
  {
! #  ifdef FEAT_EVAL
      free_callback(&opfunc_cb);
! #  endif
  }
  #endif
  
  /*
   * Handle the "g@" operator: call 'operatorfunc'.
   */
      static void
--- 3341,3369 ----
      void
  free_operatorfunc_option(void)
  {
! # ifdef FEAT_EVAL
      free_callback(&opfunc_cb);
! # endif
  }
  #endif
  
  /*
+  * Mark the global 'operatorfunc' callback with 'copyID' so that it is not
+  * garbage collected.
+  */
+     int
+ set_ref_in_opfunc(int copyID UNUSED)
+ {
+     int abort = FALSE;
+ 
+ #ifdef FEAT_EVAL
+     abort = set_ref_in_callback(&opfunc_cb, copyID);
+ #endif
+ 
+     return abort;
+ }
+ 
+ /*
   * Handle the "g@" operator: call 'operatorfunc'.
   */
      static void
*** ../vim-8.2.3787/src/proto/eval.pro  2021-12-06 11:03:50.946900217 +0000
--- src/proto/eval.pro  2021-12-12 16:20:28.789487687 +0000
***************
*** 52,57 ****
--- 52,58 ----
  int set_ref_in_dict(dict_T *d, int copyID);
  int set_ref_in_list(list_T *ll, int copyID);
  int set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack);
+ int set_ref_in_callback(callback_T *cb, int copyID);
  int set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, 
list_stack_T **list_stack);
  char_u *echo_string_core(typval_T *tv, char_u **tofree, char_u *numbuf, int 
copyID, int echo_style, int restore_copyID, int composite_val);
  char_u *echo_string(typval_T *tv, char_u **tofree, char_u *numbuf, int 
copyID);
*** ../vim-8.2.3787/src/proto/gui_xim.pro       2021-12-04 14:02:25.457024636 
+0000
--- src/proto/gui_xim.pro       2021-12-12 16:20:28.789487687 +0000
***************
*** 2,7 ****
--- 2,8 ----
  int set_imactivatefunc_option(void);
  int set_imstatusfunc_option(void);
  void free_xim_stuff(void);
+ int set_ref_in_im_funcs(int copyID);
  void im_set_active(int active);
  void xim_set_focus(int focus);
  void im_set_position(int row, int col);
*** ../vim-8.2.3787/src/proto/insexpand.pro     2021-12-03 11:08:34.260842706 
+0000
--- src/proto/insexpand.pro     2021-12-12 16:20:28.789487687 +0000
***************
*** 44,49 ****
--- 44,50 ----
  int set_omnifunc_option(void);
  void set_buflocal_ofu_callback(buf_T *buf);
  int set_thesaurusfunc_option(void);
+ int set_ref_in_insexpand_funcs(int copyID);
  callback_T *get_insert_callback(int type);
  void f_complete(typval_T *argvars, typval_T *rettv);
  void f_complete_add(typval_T *argvars, typval_T *rettv);
*** ../vim-8.2.3787/src/proto/ops.pro   2021-11-18 22:08:52.007682711 +0000
--- src/proto/ops.pro   2021-12-12 16:20:28.789487687 +0000
***************
*** 19,23 ****
--- 19,24 ----
  void cursor_pos_info(dict_T *dict);
  int set_operatorfunc_option(void);
  void free_operatorfunc_option(void);
+ int set_ref_in_opfunc(int copyID);
  void do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank);
  /* vim: set ft=c : */
*** ../vim-8.2.3787/src/proto/tag.pro   2021-12-03 11:08:34.260842706 +0000
--- src/proto/tag.pro   2021-12-12 16:20:28.789487687 +0000
***************
*** 1,6 ****
--- 1,7 ----
  /* tag.c */
  int set_tagfunc_option(void);
  void free_tagfunc_option(void);
+ int set_ref_in_tagfunc(int copyID);
  void set_buflocal_tfu_callback(buf_T *buf);
  int do_tag(char_u *tag, int type, int count, int forceit, int verbose);
  void tag_freematch(void);
*** ../vim-8.2.3787/src/quickfix.c      2021-12-09 09:26:58.499426044 +0000
--- src/quickfix.c      2021-12-12 16:20:28.789487687 +0000
***************
*** 7675,7681 ****
  }
  
  /*
!  * Mark the context as in use for all the lists in a quickfix stack.
   */
      static int
  mark_quickfix_ctx(qf_info_T *qi, int copyID)
--- 7675,7682 ----
  }
  
  /*
!  * Mark the quickfix context and callback function as in use for all the lists
!  * in a quickfix stack.
   */
      static int
  mark_quickfix_ctx(qf_info_T *qi, int copyID)
***************
*** 7683,7695 ****
      int               i;
      int               abort = FALSE;
      typval_T  *ctx;
  
      for (i = 0; i < LISTCOUNT && !abort; ++i)
      {
        ctx = qi->qf_lists[i].qf_ctx;
        if (ctx != NULL && ctx->v_type != VAR_NUMBER
                && ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT)
!           abort = set_ref_in_item(ctx, copyID, NULL, NULL);
      }
  
      return abort;
--- 7684,7700 ----
      int               i;
      int               abort = FALSE;
      typval_T  *ctx;
+     callback_T        *cb;
  
      for (i = 0; i < LISTCOUNT && !abort; ++i)
      {
        ctx = qi->qf_lists[i].qf_ctx;
        if (ctx != NULL && ctx->v_type != VAR_NUMBER
                && ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT)
!           abort = abort || set_ref_in_item(ctx, copyID, NULL, NULL);
! 
!       cb = &qi->qf_lists[i].qftf_cb;
!       abort = abort || set_ref_in_callback(cb, copyID);
      }
  
      return abort;
***************
*** 7710,7715 ****
--- 7715,7724 ----
      if (abort)
        return abort;
  
+     abort = set_ref_in_callback(&qftf_cb, copyID);
+     if (abort)
+       return abort;
+ 
      FOR_ALL_TAB_WINDOWS(tp, win)
      {
        if (win->w_llist != NULL)
*** ../vim-8.2.3787/src/tag.c   2021-12-10 20:15:11.697972271 +0000
--- src/tag.c   2021-12-12 16:20:28.789487687 +0000
***************
*** 133,147 ****
      return OK;
  }
  
! # if defined(EXITFREE) || defined(PROTO)
      void
  free_tagfunc_option(void)
  {
! #  ifdef FEAT_EVAL
      free_callback(&tfu_cb);
- #  endif
- }
  # endif
  
  /*
   * Copy the global 'tagfunc' callback function to the buffer-local 'tagfunc'
--- 133,163 ----
      return OK;
  }
  
! #if defined(EXITFREE) || defined(PROTO)
      void
  free_tagfunc_option(void)
  {
! # ifdef FEAT_EVAL
      free_callback(&tfu_cb);
  # endif
+ }
+ #endif
+ 
+ /*
+  * Mark the global 'tagfunc' callback with 'copyID' so that it is not garbage
+  * collected.
+  */
+     int
+ set_ref_in_tagfunc(int copyID UNUSED)
+ {
+     int       abort = FALSE;
+ 
+ #ifdef FEAT_EVAL
+     abort = set_ref_in_callback(&tfu_cb, copyID);
+ #endif
+ 
+     return abort;
+ }
  
  /*
   * Copy the global 'tagfunc' callback function to the buffer-local 'tagfunc'
*** ../vim-8.2.3787/src/testdir/test_iminsert.vim       2021-12-07 
12:23:53.991565068 +0000
--- src/testdir/test_iminsert.vim       2021-12-12 16:20:28.793487675 +0000
***************
*** 119,201 ****
      let g:IMstatusfunc_called += 1
      return 1
    endfunc
-   let g:IMactivatefunc_called = 0
-   let g:IMstatusfunc_called = 0
    set iminsert=2
  
!   " Test for using a function()
!   set imactivatefunc=function('IMactivatefunc1')
!   set imstatusfunc=function('IMstatusfunc1')
!   normal! i
! 
!   " Using a funcref variable to set 'completefunc'
!   let Fn1 = function('IMactivatefunc1')
!   let &imactivatefunc = Fn1
!   let Fn2 = function('IMstatusfunc1')
!   let &imstatusfunc = Fn2
!   normal! i
! 
!   " Using a string(funcref variable) to set 'completefunc'
!   let &imactivatefunc = string(Fn1)
!   let &imstatusfunc = string(Fn2)
!   normal! i
! 
!   " Test for using a funcref()
!   set imactivatefunc=funcref('IMactivatefunc1')
!   set imstatusfunc=funcref('IMstatusfunc1')
!   normal! i
! 
!   " Using a funcref variable to set 'imactivatefunc'
!   let Fn1 = funcref('IMactivatefunc1')
!   let &imactivatefunc = Fn1
!   let Fn2 = funcref('IMstatusfunc1')
!   let &imstatusfunc = Fn2
!   normal! i
! 
!   " Using a string(funcref variable) to set 'imactivatefunc'
!   let &imactivatefunc = string(Fn1)
!   let &imstatusfunc = string(Fn2)
!   normal! i
! 
!   " Test for using a lambda function
!   set imactivatefunc={a\ ->\ IMactivatefunc1(a)}
!   set imstatusfunc={\ ->\ IMstatusfunc1()}
!   normal! i
! 
!   " Set 'imactivatefunc' and 'imstatusfunc' to a lambda expression
!   let &imactivatefunc = {a -> IMactivatefunc1(a)}
!   let &imstatusfunc = { -> IMstatusfunc1()}
!   normal! i
! 
!   " Set 'imactivatefunc' and 'imstatusfunc' to a string(lambda expression)
!   let &imactivatefunc = '{a -> IMactivatefunc1(a)}'
!   let &imstatusfunc = '{ -> IMstatusfunc1()}'
!   normal! i
! 
!   " Set 'imactivatefunc' 'imstatusfunc' to a variable with a lambda expression
!   let Lambda1 = {a -> IMactivatefunc1(a)}
!   let Lambda2 = { -> IMstatusfunc1()}
!   let &imactivatefunc = Lambda1
!   let &imstatusfunc = Lambda2
!   normal! i
! 
!   " Set 'imactivatefunc' 'imstatusfunc' to a string(variable with a lambda
!   " expression)
!   let &imactivatefunc = string(Lambda1)
!   let &imstatusfunc = string(Lambda2)
!   normal! i
! 
!   " Test for clearing the 'completefunc' option
!   set imactivatefunc='' imstatusfunc=''
!   set imactivatefunc& imstatusfunc&
! 
!   call assert_fails("set imactivatefunc=function('abc')", "E700:")
!   call assert_fails("set imstatusfunc=function('abc')", "E700:")
!   call assert_fails("set imactivatefunc=funcref('abc')", "E700:")
!   call assert_fails("set imstatusfunc=funcref('abc')", "E700:")
  
!   call assert_equal(11, g:IMactivatefunc_called)
!   call assert_equal(22, g:IMstatusfunc_called)
  
    " Vim9 tests
    let lines =<< trim END
--- 119,260 ----
      let g:IMstatusfunc_called += 1
      return 1
    endfunc
    set iminsert=2
  
!   let lines =<< trim END
!     LET g:IMactivatefunc_called = 0
!     LET g:IMstatusfunc_called = 0
! 
!     #" Test for using a function()
!     set imactivatefunc=function('g:IMactivatefunc1')
!     set imstatusfunc=function('g:IMstatusfunc1')
!     normal! i
! 
!     #" Using a funcref variable to set 'completefunc'
!     VAR Fn1 = function('g:IMactivatefunc1')
!     LET &imactivatefunc = Fn1
!     VAR Fn2 = function('g:IMstatusfunc1')
!     LET &imstatusfunc = Fn2
!     normal! i
! 
!     #" Using a string(funcref variable) to set 'completefunc'
!     LET &imactivatefunc = string(Fn1)
!     LET &imstatusfunc = string(Fn2)
!     normal! i
! 
!     #" Test for using a funcref()
!     set imactivatefunc=funcref('g:IMactivatefunc1')
!     set imstatusfunc=funcref('g:IMstatusfunc1')
!     normal! i
! 
!     #" Using a funcref variable to set 'imactivatefunc'
!     LET Fn1 = funcref('g:IMactivatefunc1')
!     LET &imactivatefunc = Fn1
!     LET Fn2 = funcref('g:IMstatusfunc1')
!     LET &imstatusfunc = Fn2
!     normal! i
! 
!     #" Using a string(funcref variable) to set 'imactivatefunc'
!     LET &imactivatefunc = string(Fn1)
!     LET &imstatusfunc = string(Fn2)
!     normal! i
! 
!     #" Test for using a lambda function
!     VAR optval = "LSTART a LMIDDLE IMactivatefunc1(a) LEND"
!     LET optval = substitute(optval, ' ', '\\ ', 'g')
!     exe "set imactivatefunc=" .. optval
!     LET optval = "LSTART LMIDDLE IMstatusfunc1() LEND"
!     LET optval = substitute(optval, ' ', '\\ ', 'g')
!     exe "set imstatusfunc=" .. optval
!     normal! i
! 
!     #" Set 'imactivatefunc' and 'imstatusfunc' to a lambda expression
!     LET &imactivatefunc = LSTART a LMIDDLE IMactivatefunc1(a) LEND
!     LET &imstatusfunc = LSTART LMIDDLE IMstatusfunc1() LEND
!     normal! i
! 
!     #" Set 'imactivatefunc' and 'imstatusfunc' to a string(lambda expression)
!     LET &imactivatefunc = 'LSTART a LMIDDLE IMactivatefunc1(a) LEND'
!     LET &imstatusfunc = 'LSTART LMIDDLE IMstatusfunc1() LEND'
!     normal! i
! 
!     #" Set 'imactivatefunc' 'imstatusfunc' to a variable with a lambda
!     #" expression
!     VAR Lambda1 = LSTART a LMIDDLE IMactivatefunc1(a) LEND
!     VAR Lambda2 = LSTART LMIDDLE IMstatusfunc1() LEND
!     LET &imactivatefunc = Lambda1
!     LET &imstatusfunc = Lambda2
!     normal! i
! 
!     #" Set 'imactivatefunc' 'imstatusfunc' to a string(variable with a lambda
!     #" expression)
!     LET &imactivatefunc = string(Lambda1)
!     LET &imstatusfunc = string(Lambda2)
!     normal! i
! 
!     #" Test for clearing the 'completefunc' option
!     set imactivatefunc='' imstatusfunc=''
!     set imactivatefunc& imstatusfunc&
! 
!     set imactivatefunc=g:IMactivatefunc1
!     set imstatusfunc=g:IMstatusfunc1
!     call assert_fails("set imactivatefunc=function('abc')", "E700:")
!     call assert_fails("set imstatusfunc=function('abc')", "E700:")
!     call assert_fails("set imactivatefunc=funcref('abc')", "E700:")
!     call assert_fails("set imstatusfunc=funcref('abc')", "E700:")
!     call assert_fails("LET &imstatusfunc = function('abc')", "E700:")
!     call assert_fails("LET &imactivatefunc = function('abc')", "E700:")
!     normal! i
! 
!     #" set 'imactivatefunc' and 'imstatusfunc' to a non-existing function
!     set imactivatefunc=IMactivatefunc1
!     set imstatusfunc=IMstatusfunc1
!     call assert_fails("set imactivatefunc=function('NonExistingFunc')", 
'E700:')
!     call assert_fails("set imstatusfunc=function('NonExistingFunc')", 'E700:')
!     call assert_fails("LET &imactivatefunc = function('NonExistingFunc')", 
'E700:')
!     call assert_fails("LET &imstatusfunc = function('NonExistingFunc')", 
'E700:')
!     normal! i
  
!     call assert_equal(13, g:IMactivatefunc_called)
!     call assert_equal(26, g:IMstatusfunc_called)
!   END
!   call CheckLegacyAndVim9Success(lines)
! 
!   " Using Vim9 lambda expression in legacy context should fail
!   set imactivatefunc=(a)\ =>\ IMactivatefunc1(a)
!   set imstatusfunc=IMstatusfunc1
!   call assert_fails('normal! i', 'E117:')
!   set imactivatefunc=IMactivatefunc1
!   set imstatusfunc=()\ =>\ IMstatusfunc1(a)
!   call assert_fails('normal! i', 'E117:')
! 
!   " set 'imactivatefunc' and 'imstatusfunc' to a partial with dict. This used
!   " to cause a crash.
!   func SetIMFunc()
!     let params1 = {'activate': function('g:DictActivateFunc')}
!     let params2 = {'status': function('g:DictStatusFunc')}
!     let &imactivatefunc = params1.activate
!     let &imstatusfunc = params2.status
!   endfunc
!   func g:DictActivateFunc(_) dict
!   endfunc
!   func g:DictStatusFunc(_) dict
!   endfunc
!   call SetIMFunc()
!   new
!   call SetIMFunc()
!   bw
!   call test_garbagecollect_now()
!   new
!   set imactivatefunc=
!   set imstatusfunc=
!   wincmd w
!   set imactivatefunc=
!   set imstatusfunc=
!   :%bw!
!   delfunc g:DictActivateFunc
!   delfunc g:DictStatusFunc
!   delfunc SetIMFunc
  
    " Vim9 tests
    let lines =<< trim END
***************
*** 217,275 ****
      set imstatusfunc=function('IMstatusfunc1')
      normal! i
  
-     # Test for using a lambda
-     &imactivatefunc = '(a) => IMactivatefunc1(a)'
-     &imstatusfunc = '() => IMstatusfunc1()'
-     normal! i
- 
-     # Test for using a variable with a lambda expression
-     var Fn1: func = (active) => {
-            g:IMactivatefunc_called += 1
-            return 1
-         }
-     var Fn2: func = () => {
-            g:IMstatusfunc_called += 1
-            return 1
-         }
-     &imactivatefunc = Fn1
-     &imstatusfunc = Fn2
-     normal! i
- 
-     # Test for using a string(variable with a lambda expression)
-     &imactivatefunc = string(Fn1)
-     &imstatusfunc = string(Fn2)
-     normal! i
- 
-     assert_equal(4, g:IMactivatefunc_called)
-     assert_equal(8, g:IMstatusfunc_called)
- 
      set iminsert=0
      set imactivatefunc=
      set imstatusfunc=
    END
    call CheckScriptSuccess(lines)
  
-   " Using Vim9 lambda expression in legacy context should fail
-   set imactivatefunc=(a)\ =>\ IMactivatefunc1(a)
-   set imstatusfunc=IMstatusfunc1
-   call assert_fails('normal! i', 'E117:')
-   set imactivatefunc=IMactivatefunc1
-   set imstatusfunc=()\ =>\ IMstatusfunc1(a)
-   call assert_fails('normal! i', 'E117:')
- 
-   " set 'imactivatefunc' and 'imstatusfunc' to a non-existing function
-   set imactivatefunc=IMactivatefunc1
-   set imstatusfunc=IMstatusfunc1
-   call assert_fails("set imactivatefunc=function('NonExistingFunc')", 'E700:')
-   call assert_fails("set imstatusfunc=function('NonExistingFunc')", 'E700:')
-   call assert_fails("let &imactivatefunc = function('NonExistingFunc')", 
'E700:')
-   call assert_fails("let &imstatusfunc = function('NonExistingFunc')", 
'E700:')
-   let g:IMactivatefunc_called = 0
-   let g:IMstatusfunc_called = 0
-   normal! i
-   call assert_equal(2, g:IMactivatefunc_called)
-   call assert_equal(2, g:IMstatusfunc_called)
- 
    " cleanup
    delfunc IMactivatefunc1
    delfunc IMstatusfunc1
--- 276,287 ----
*** ../vim-8.2.3787/src/testdir/test_ins_complete.vim   2021-12-08 
10:45:43.329331491 +0000
--- src/testdir/test_ins_complete.vim   2021-12-12 16:20:28.793487675 +0000
***************
*** 875,1028 ****
      return a:findstart ? 0 : []
    endfunc
  
!   " Test for using a function()
!   set completefunc=function('MycompleteFunc1',[10])
!   new | only
!   call setline(1, 'one')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[10, 1, ''], [10, 0, 'one']], g:MycompleteFunc1_args)
!   bw!
  
!   " Using a funcref variable to set 'completefunc'
!   let Fn = function('MycompleteFunc1', [11])
!   let &completefunc = Fn
!   new | only
!   call setline(1, 'two')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[11, 1, ''], [11, 0, 'two']], g:MycompleteFunc1_args)
!   bw!
  
!   " Using string(funcref_variable) to set 'completefunc'
!   let Fn = function('MycompleteFunc1', [12])
!   let &completefunc = string(Fn)
!   new | only
!   call setline(1, 'two')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[12, 1, ''], [12, 0, 'two']], g:MycompleteFunc1_args)
!   bw!
  
!   " Test for using a funcref()
!   set completefunc=funcref('MycompleteFunc1',\ [13])
!   new | only
!   call setline(1, 'three')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[13, 1, ''], [13, 0, 'three']], g:MycompleteFunc1_args)
!   bw!
  
!   " Using a funcref variable to set 'completefunc'
!   let Fn = funcref('MycompleteFunc1', [14])
!   let &completefunc = Fn
!   new | only
!   call setline(1, 'four')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[14, 1, ''], [14, 0, 'four']], g:MycompleteFunc1_args)
!   bw!
  
!   " Using a string(funcref_variable) to set 'completefunc'
!   let Fn = funcref('MycompleteFunc1', [15])
!   let &completefunc = string(Fn)
!   new | only
!   call setline(1, 'four')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[15, 1, ''], [15, 0, 'four']], g:MycompleteFunc1_args)
!   bw!
  
!   " Test for using a lambda function
!   set completefunc={a,\ b\ ->\ MycompleteFunc1(16,\ a,\ b)}
!   new | only
!   call setline(1, 'five')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[16, 1, ''], [16, 0, 'five']], g:MycompleteFunc1_args)
!   bw!
  
!   " Set 'completefunc' to a lambda expression
!   let &completefunc = {a, b -> MycompleteFunc1(17, a, b)}
!   new | only
!   call setline(1, 'six')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[17, 1, ''], [17, 0, 'six']], g:MycompleteFunc1_args)
!   bw!
  
!   " Set 'completefunc' to string(lambda_expression)
!   let &completefunc = '{a, b -> MycompleteFunc1(18, a, b)}'
!   new | only
!   call setline(1, 'six')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[18, 1, ''], [18, 0, 'six']], g:MycompleteFunc1_args)
!   bw!
  
!   " Set 'completefunc' to a variable with a lambda expression
!   let Lambda = {a, b -> MycompleteFunc1(19, a, b)}
!   let &completefunc = Lambda
!   new | only
!   call setline(1, 'seven')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:MycompleteFunc1_args)
!   bw!
  
!   " Set 'completefunc' to a string(variable with a lambda expression)
!   let Lambda = {a, b -> MycompleteFunc1(20, a, b)}
!   let &completefunc = string(Lambda)
!   new | only
!   call setline(1, 'seven')
!   let g:MycompleteFunc1_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:MycompleteFunc1_args)
!   bw!
  
!   " Test for using a lambda function with incorrect return value
!   let Lambda = {s -> strlen(s)}
!   let &completefunc = Lambda
!   new | only
!   call setline(1, 'eight')
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   bw!
  
!   " Test for clearing the 'completefunc' option
!   set completefunc=''
!   set completefunc&
  
-   call assert_fails("set completefunc=function('abc')", "E700:")
-   call assert_fails("set completefunc=funcref('abc')", "E700:")
    let &completefunc = {a -> 'abc'}
    call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
  
    " Using Vim9 lambda expression in legacy context should fail
!   set completefunc=(a,\ b)\ =>\ g:MycompleteFunc1(21,\ a,\ b)
    new | only
    let g:MycompleteFunc1_args = []
    call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
    call assert_equal([], g:MycompleteFunc1_args)
  
!   " set 'completefunc' to a non-existing function
!   func MycompleteFunc2(findstart, base)
!     call add(g:MycompleteFunc2_args, [a:findstart, a:base])
!     return a:findstart ? 0 : []
    endfunc
!   set completefunc=MycompleteFunc2
!   call setline(1, 'five')
!   call assert_fails("set completefunc=function('NonExistingFunc')", 'E700:')
!   call assert_fails("let &completefunc = function('NonExistingFunc')", 
'E700:')
!   let g:MycompleteFunc2_args = []
!   call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!   call assert_equal([[1, ''], [0, 'five']], g:MycompleteFunc2_args)
!   bw!
  
    " Vim9 tests
    let lines =<< trim END
      vim9script
  
!     # Test for using function()
      def Vim9CompleteFunc(val: number, findstart: number, base: string): any
        add(g:Vim9completeFuncArgs, [val, findstart, base])
        return findstart ? 0 : []
--- 875,1053 ----
      return a:findstart ? 0 : []
    endfunc
  
!   let lines =<< trim END
!     #" Test for using a function()
!     set completefunc=function('g:MycompleteFunc1',\ [10])
!     new | only
!     call setline(1, 'one')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[10, 1, ''], [10, 0, 'one']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Using a funcref variable to set 'completefunc'
!     VAR Fn = function('g:MycompleteFunc1', [11])
!     LET &completefunc = Fn
!     new | only
!     call setline(1, 'two')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[11, 1, ''], [11, 0, 'two']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Using string(funcref_variable) to set 'completefunc'
!     LET Fn = function('g:MycompleteFunc1', [12])
!     LET &completefunc = string(Fn)
!     new | only
!     call setline(1, 'two')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[12, 1, ''], [12, 0, 'two']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Test for using a funcref()
!     set completefunc=funcref('g:MycompleteFunc1',\ [13])
!     new | only
!     call setline(1, 'three')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[13, 1, ''], [13, 0, 'three']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Using a funcref variable to set 'completefunc'
!     LET Fn = funcref('g:MycompleteFunc1', [14])
!     LET &completefunc = Fn
!     new | only
!     call setline(1, 'four')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[14, 1, ''], [14, 0, 'four']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Using a string(funcref_variable) to set 'completefunc'
!     LET Fn = funcref('g:MycompleteFunc1', [15])
!     LET &completefunc = string(Fn)
!     new | only
!     call setline(1, 'four')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[15, 1, ''], [15, 0, 'four']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Test for using a lambda function with set
!     VAR optval = "LSTART a, b LMIDDLE MycompleteFunc1(16, a, b) LEND"
!     LET optval = substitute(optval, ' ', '\\ ', 'g')
!     exe "set completefunc=" .. optval
!     new | only
!     call setline(1, 'five')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[16, 1, ''], [16, 0, 'five']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Set 'completefunc' to a lambda expression
!     LET &completefunc = LSTART a, b LMIDDLE MycompleteFunc1(17, a, b) LEND
!     new | only
!     call setline(1, 'six')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[17, 1, ''], [17, 0, 'six']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Set 'completefunc' to string(lambda_expression)
!     LET &completefunc = 'LSTART a, b LMIDDLE MycompleteFunc1(18, a, b) LEND'
!     new | only
!     call setline(1, 'six')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[18, 1, ''], [18, 0, 'six']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Set 'completefunc' to a variable with a lambda expression
!     VAR Lambda = LSTART a, b LMIDDLE MycompleteFunc1(19, a, b) LEND
!     LET &completefunc = Lambda
!     new | only
!     call setline(1, 'seven')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Set 'completefunc' to a string(variable with a lambda expression)
!     LET Lambda = LSTART a, b LMIDDLE MycompleteFunc1(20, a, b) LEND
!     LET &completefunc = string(Lambda)
!     new | only
!     call setline(1, 'seven')
!     LET g:MycompleteFunc1_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:MycompleteFunc1_args)
!     bw!
  
!     #" Test for using a lambda function with incorrect return value
!     LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND
!     LET &completefunc = Lambda
!     new | only
!     call setline(1, 'eight')
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     bw!
  
!     #" Test for clearing the 'completefunc' option
!     set completefunc=''
!     set completefunc&
!     call assert_fails("set completefunc=function('abc')", "E700:")
!     call assert_fails("set completefunc=funcref('abc')", "E700:")
! 
!     #" set 'completefunc' to a non-existing function
!     func MycompleteFunc2(findstart, base)
!       call add(g:MycompleteFunc2_args, [a:findstart, a:base])
!       return a:findstart ? 0 : []
!     endfunc
!     set completefunc=MycompleteFunc2
!     call setline(1, 'five')
!     call assert_fails("set completefunc=function('NonExistingFunc')", 'E700:')
!     call assert_fails("LET &completefunc = function('NonExistingFunc')", 
'E700:')
!     LET g:MycompleteFunc2_args = []
!     call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
!     call assert_equal([[1, ''], [0, 'five']], g:MycompleteFunc2_args)
!     bw!
!   END
!   call CheckLegacyAndVim9Success(lines)
  
    let &completefunc = {a -> 'abc'}
    call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
  
    " Using Vim9 lambda expression in legacy context should fail
!   set completefunc=(a,\ b)\ =>\ MycompleteFunc1(21,\ a,\ b)
    new | only
    let g:MycompleteFunc1_args = []
    call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
    call assert_equal([], g:MycompleteFunc1_args)
  
!   " set 'completefunc' to a partial with dict. This used to cause a crash.
!   func SetCompleteFunc()
!     let params = {'complete': function('g:DictCompleteFunc')}
!     let &completefunc = params.complete
    endfunc
!   func g:DictCompleteFunc(_) dict
!   endfunc
!   call SetCompleteFunc()
!   new
!   call SetCompleteFunc()
!   bw
!   call test_garbagecollect_now()
!   new
!   set completefunc=
!   wincmd w
!   set completefunc=
!   %bw!
!   delfunc g:DictCompleteFunc
!   delfunc SetCompleteFunc
  
    " Vim9 tests
    let lines =<< trim END
      vim9script
  
!     # Test for using a def function with completefunc
      def Vim9CompleteFunc(val: number, findstart: number, base: string): any
        add(g:Vim9completeFuncArgs, [val, findstart, base])
        return findstart ? 0 : []
***************
*** 1034,1077 ****
      feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
      assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9completeFuncArgs)
      bw!
- 
-     # Test for using a lambda
-     &completefunc = (a, b) => Vim9CompleteFunc(61, a, b)
-     new | only
-     setline(1, 'two')
-     g:Vim9completeFuncArgs = []
-     feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
-     assert_equal([[61, 1, ''], [61, 0, 'two']], g:Vim9completeFuncArgs)
-     bw!
- 
-     # Test for using a string(lambda)
-     &completefunc = '(a, b) => Vim9CompleteFunc(62, a, b)'
-     new | only
-     setline(1, 'two')
-     g:Vim9completeFuncArgs = []
-     feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
-     assert_equal([[62, 1, ''], [62, 0, 'two']], g:Vim9completeFuncArgs)
-     bw!
- 
-     # Test for using a variable with a lambda expression
-     var Fn: func = (a, b) => Vim9CompleteFunc(63, a, b)
-     &completefunc = Fn
-     new | only
-     setline(1, 'three')
-     g:Vim9completeFuncArgs = []
-     feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
-     assert_equal([[63, 1, ''], [63, 0, 'three']], g:Vim9completeFuncArgs)
-     bw!
- 
-     # Test for using a string(variable with a lambda expression)
-     Fn = (a, b) => Vim9CompleteFunc(64, a, b)
-     &completefunc = string(Fn)
-     new | only
-     setline(1, 'three')
-     g:Vim9completeFuncArgs = []
-     feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
-     assert_equal([[64, 1, ''], [64, 0, 'three']], g:Vim9completeFuncArgs)
-     bw!
    END
    call CheckScriptSuccess(lines)
  
--- 1059,1064 ----
***************
*** 1089,1242 ****
      return a:findstart ? 0 : []
    endfunc
  
!   " Test for using a function()
!   set omnifunc=function('MyomniFunc1',[10])
!   new | only
!   call setline(1, 'one')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[10, 1, ''], [10, 0, 'one']], g:MyomniFunc1_args)
!   bw!
  
!   " Using a funcref variable to set 'omnifunc'
!   let Fn = function('MyomniFunc1', [11])
!   let &omnifunc = Fn
!   new | only
!   call setline(1, 'two')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[11, 1, ''], [11, 0, 'two']], g:MyomniFunc1_args)
!   bw!
  
!   " Using a string(funcref_variable) to set 'omnifunc'
!   let Fn = function('MyomniFunc1', [12])
!   let &omnifunc = string(Fn)
!   new | only
!   call setline(1, 'two')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[12, 1, ''], [12, 0, 'two']], g:MyomniFunc1_args)
!   bw!
  
!   " Test for using a funcref()
!   set omnifunc=funcref('MyomniFunc1',\ [13])
!   new | only
!   call setline(1, 'three')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[13, 1, ''], [13, 0, 'three']], g:MyomniFunc1_args)
!   bw!
  
!   " Using a funcref variable to set 'omnifunc'
!   let Fn = funcref('MyomniFunc1', [14])
!   let &omnifunc = Fn
!   new | only
!   call setline(1, 'four')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[14, 1, ''], [14, 0, 'four']], g:MyomniFunc1_args)
!   bw!
  
!   " Using a string(funcref_variable) to set 'omnifunc'
!   let Fn = funcref('MyomniFunc1', [15])
!   let &omnifunc = string(Fn)
!   new | only
!   call setline(1, 'four')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[15, 1, ''], [15, 0, 'four']], g:MyomniFunc1_args)
!   bw!
  
!   " Test for using a lambda function
!   set omnifunc={a,\ b\ ->\ MyomniFunc1(16,\ a,\ b)}
!   new | only
!   call setline(1, 'five')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[16, 1, ''], [16, 0, 'five']], g:MyomniFunc1_args)
!   bw!
  
!   " Set 'omnifunc' to a lambda expression
!   let &omnifunc = {a, b -> MyomniFunc1(17, a, b)}
!   new | only
!   call setline(1, 'six')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[17, 1, ''], [17, 0, 'six']], g:MyomniFunc1_args)
!   bw!
  
!   " Set 'omnifunc' to a string(lambda_expression)
!   let &omnifunc = '{a, b -> MyomniFunc1(18, a, b)}'
!   new | only
!   call setline(1, 'six')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[18, 1, ''], [18, 0, 'six']], g:MyomniFunc1_args)
!   bw!
  
!   " Set 'omnifunc' to a variable with a lambda expression
!   let Lambda = {a, b -> MyomniFunc1(19, a, b)}
!   let &omnifunc = Lambda
!   new | only
!   call setline(1, 'seven')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:MyomniFunc1_args)
!   bw!
  
!   " Set 'omnifunc' to a string(variable with a lambda expression)
!   let Lambda = {a, b -> MyomniFunc1(20, a, b)}
!   let &omnifunc = string(Lambda)
!   new | only
!   call setline(1, 'seven')
!   let g:MyomniFunc1_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:MyomniFunc1_args)
!   bw!
  
!   " Test for using a lambda function with incorrect return value
!   let Lambda = {s -> strlen(s)}
!   let &omnifunc = Lambda
!   new | only
!   call setline(1, 'eight')
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   bw!
  
!   " Test for clearing the 'omnifunc' option
!   set omnifunc=''
!   set omnifunc&
  
-   call assert_fails("set omnifunc=function('abc')", "E700:")
-   call assert_fails("set omnifunc=funcref('abc')", "E700:")
    let &omnifunc = {a -> 'abc'}
    call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
  
    " Using Vim9 lambda expression in legacy context should fail
!   set omnifunc=(a,\ b)\ =>\ g:MyomniFunc1(21,\ a,\ b)
    new | only
    let g:MyomniFunc1_args = []
    call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
    call assert_equal([], g:MyomniFunc1_args)
  
!   " set 'omnifunc' to a non-existing function
!   func MyomniFunc2(findstart, base)
!     call add(g:MyomniFunc2_args, [a:findstart, a:base])
!     return a:findstart ? 0 : []
    endfunc
!   set omnifunc=MyomniFunc2
!   call setline(1, 'nine')
!   call assert_fails("set omnifunc=function('NonExistingFunc')", 'E700:')
!   call assert_fails("let &omnifunc = function('NonExistingFunc')", 'E700:')
!   let g:MyomniFunc2_args = []
!   call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!   call assert_equal([[1, ''], [0, 'nine']], g:MyomniFunc2_args)
!   bw!
  
    " Vim9 tests
    let lines =<< trim END
      vim9script
  
!     # Test for using function()
      def Vim9omniFunc(val: number, findstart: number, base: string): any
        add(g:Vim9omniFunc_Args, [val, findstart, base])
        return findstart ? 0 : []
--- 1076,1254 ----
      return a:findstart ? 0 : []
    endfunc
  
!   let lines =<< trim END
!     #" Test for using a function()
!     set omnifunc=function('g:MyomniFunc1',\ [10])
!     new | only
!     call setline(1, 'one')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[10, 1, ''], [10, 0, 'one']], g:MyomniFunc1_args)
!     bw!
  
!     #" Using a funcref variable to set 'omnifunc'
!     VAR Fn = function('g:MyomniFunc1', [11])
!     LET &omnifunc = Fn
!     new | only
!     call setline(1, 'two')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[11, 1, ''], [11, 0, 'two']], g:MyomniFunc1_args)
!     bw!
  
!     #" Using a string(funcref_variable) to set 'omnifunc'
!     LET Fn = function('g:MyomniFunc1', [12])
!     LET &omnifunc = string(Fn)
!     new | only
!     call setline(1, 'two')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[12, 1, ''], [12, 0, 'two']], g:MyomniFunc1_args)
!     bw!
  
!     #" Test for using a funcref()
!     set omnifunc=funcref('g:MyomniFunc1',\ [13])
!     new | only
!     call setline(1, 'three')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[13, 1, ''], [13, 0, 'three']], g:MyomniFunc1_args)
!     bw!
  
!     #" Use let to set 'omnifunc' to a funcref
!     LET Fn = funcref('g:MyomniFunc1', [14])
!     LET &omnifunc = Fn
!     new | only
!     call setline(1, 'four')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[14, 1, ''], [14, 0, 'four']], g:MyomniFunc1_args)
!     bw!
  
!     #" Using a string(funcref) to set 'omnifunc'
!     LET Fn = funcref("g:MyomniFunc1", [15])
!     LET &omnifunc = string(Fn)
!     new | only
!     call setline(1, 'four')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[15, 1, ''], [15, 0, 'four']], g:MyomniFunc1_args)
!     bw!
  
!     #" Test for using a lambda function with set
!     VAR optval = "LSTART a, b LMIDDLE MyomniFunc1(16, a, b) LEND"
!     LET optval = substitute(optval, ' ', '\\ ', 'g')
!     exe "set omnifunc=" .. optval
!     new | only
!     call setline(1, 'five')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[16, 1, ''], [16, 0, 'five']], g:MyomniFunc1_args)
!     bw!
  
!     #" Set 'omnifunc' to a lambda expression
!     LET &omnifunc = LSTART a, b LMIDDLE MyomniFunc1(17, a, b) LEND
!     new | only
!     call setline(1, 'six')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[17, 1, ''], [17, 0, 'six']], g:MyomniFunc1_args)
!     bw!
  
!     #" Set 'omnifunc' to a string(lambda_expression)
!     LET &omnifunc = 'LSTART a, b LMIDDLE MyomniFunc1(18, a, b) LEND'
!     new | only
!     call setline(1, 'six')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[18, 1, ''], [18, 0, 'six']], g:MyomniFunc1_args)
!     bw!
  
!     #" Set 'omnifunc' to a variable with a lambda expression
!     VAR Lambda = LSTART a, b LMIDDLE MyomniFunc1(19, a, b) LEND
!     LET &omnifunc = Lambda
!     new | only
!     call setline(1, 'seven')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:MyomniFunc1_args)
!     bw!
  
!     #" Set 'omnifunc' to a string(variable with a lambda expression)
!     LET Lambda = LSTART a, b LMIDDLE MyomniFunc1(20, a, b) LEND
!     LET &omnifunc = string(Lambda)
!     new | only
!     call setline(1, 'seven')
!     LET g:MyomniFunc1_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:MyomniFunc1_args)
!     bw!
  
!     #" Test for using a lambda function with incorrect return value
!     LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND
!     LET &omnifunc = Lambda
!     new | only
!     call setline(1, 'eight')
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     bw!
  
!     #" Test for clearing the 'omnifunc' option
!     set omnifunc=''
!     set omnifunc&
!     call assert_fails("set omnifunc=function('abc')", "E700:")
!     call assert_fails("set omnifunc=funcref('abc')", "E700:")
! 
!     #" set 'omnifunc' to a non-existing function
!     func MyomniFunc2(findstart, base)
!       call add(g:MyomniFunc2_args, [a:findstart, a:base])
!       return a:findstart ? 0 : []
!     endfunc
!     set omnifunc=MyomniFunc2
!     call setline(1, 'nine')
!     call assert_fails("set omnifunc=function('NonExistingFunc')", 'E700:')
!     call assert_fails("LET &omnifunc = function('NonExistingFunc')", 'E700:')
!     LET g:MyomniFunc2_args = []
!     call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
!     call assert_equal([[1, ''], [0, 'nine']], g:MyomniFunc2_args)
!     bw!
!   END
!   call CheckLegacyAndVim9Success(lines)
  
    let &omnifunc = {a -> 'abc'}
    call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
  
    " Using Vim9 lambda expression in legacy context should fail
!   set omnifunc=(a,\ b)\ =>\ MyomniFunc1(21,\ a,\ b)
    new | only
    let g:MyomniFunc1_args = []
    call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
    call assert_equal([], g:MyomniFunc1_args)
  
!   " set 'omnifunc' to a partial with dict. This used to cause a crash.
!   func SetOmniFunc()
!     let params = {'omni': function('g:DictOmniFunc')}
!     let &omnifunc = params.omni
    endfunc
!   func g:DictOmniFunc(_) dict
!   endfunc
!   call SetOmniFunc()
!   new
!   call SetOmniFunc()
!   bw
!   call test_garbagecollect_now()
!   new
!   set omnifunc=
!   wincmd w
!   set omnifunc=
!   %bw!
!   delfunc g:DictOmniFunc
!   delfunc SetOmniFunc
  
    " Vim9 tests
    let lines =<< trim END
      vim9script
  
!     # Test for using a def function with omnifunc
      def Vim9omniFunc(val: number, findstart: number, base: string): any
        add(g:Vim9omniFunc_Args, [val, findstart, base])
        return findstart ? 0 : []
***************
*** 1248,1291 ****
      feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
      assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9omniFunc_Args)
      bw!
- 
-     # Test for using a lambda
-     &omnifunc = (a, b) => Vim9omniFunc(61, a, b)
-     new | only
-     setline(1, 'two')
-     g:Vim9omniFunc_Args = []
-     feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
-     assert_equal([[61, 1, ''], [61, 0, 'two']], g:Vim9omniFunc_Args)
-     bw!
- 
-     # Test for using a string(lambda)
-     &omnifunc = '(a, b) => Vim9omniFunc(62, a, b)'
-     new | only
-     setline(1, 'two')
-     g:Vim9omniFunc_Args = []
-     feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
-     assert_equal([[62, 1, ''], [62, 0, 'two']], g:Vim9omniFunc_Args)
-     bw!
- 
-     # Test for using a variable with a lambda expression
-     var Fn: func = (a, b) => Vim9omniFunc(63, a, b)
-     &omnifunc = Fn
-     new | only
-     setline(1, 'three')
-     g:Vim9omniFunc_Args = []
-     feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
-     assert_equal([[63, 1, ''], [63, 0, 'three']], g:Vim9omniFunc_Args)
-     bw!
- 
-     # Test for using a string(variable with a lambda expression)
-     Fn = (a, b) => Vim9omniFunc(64, a, b)
-     &omnifunc = string(Fn)
-     new | only
-     setline(1, 'three')
-     g:Vim9omniFunc_Args = []
-     feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
-     assert_equal([[64, 1, ''], [64, 0, 'three']], g:Vim9omniFunc_Args)
-     bw!
    END
    call CheckScriptSuccess(lines)
  
--- 1260,1265 ----
***************
*** 1303,1480 ****
      return a:findstart ? 0 : []
    endfunc
  
!   " Test for using a function()
!   set thesaurusfunc=function('MytsrFunc1',[10])
!   new | only
!   call setline(1, 'one')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[10, 1, ''], [10, 0, 'one']], g:MytsrFunc1_args)
!   bw!
! 
!   " Using a funcref variable to set 'thesaurusfunc'
!   let Fn = function('MytsrFunc1', [11])
!   let &thesaurusfunc = Fn
!   new | only
!   call setline(1, 'two')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[11, 1, ''], [11, 0, 'two']], g:MytsrFunc1_args)
!   bw!
! 
!   " Using a string(funcref_variable) to set 'thesaurusfunc'
!   let Fn = function('MytsrFunc1', [12])
!   let &thesaurusfunc = string(Fn)
!   new | only
!   call setline(1, 'two')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[12, 1, ''], [12, 0, 'two']], g:MytsrFunc1_args)
!   bw!
! 
!   " Test for using a funcref()
!   set thesaurusfunc=funcref('MytsrFunc1',[13])
!   new | only
!   call setline(1, 'three')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[13, 1, ''], [13, 0, 'three']], g:MytsrFunc1_args)
!   bw!
! 
!   " Using a funcref variable to set 'thesaurusfunc'
!   let Fn = funcref('MytsrFunc1', [14])
!   let &thesaurusfunc = Fn
!   new | only
!   call setline(1, 'four')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[14, 1, ''], [14, 0, 'four']], g:MytsrFunc1_args)
!   bw!
! 
!   " Using a string(funcref_variable) to set 'thesaurusfunc'
!   let Fn = funcref('MytsrFunc1', [15])
!   let &thesaurusfunc = string(Fn)
!   new | only
!   call setline(1, 'four')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[15, 1, ''], [15, 0, 'four']], g:MytsrFunc1_args)
!   bw!
! 
!   " Test for using a lambda function
!   set thesaurusfunc={a,\ b\ ->\ MytsrFunc1(16,\ a,\ b)}
!   new | only
!   call setline(1, 'five')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[16, 1, ''], [16, 0, 'five']], g:MytsrFunc1_args)
!   bw!
! 
!   " Set 'thesaurusfunc' to a lambda expression
!   let &thesaurusfunc = {a, b -> MytsrFunc1(17, a, b)}
!   new | only
!   call setline(1, 'six')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[17, 1, ''], [17, 0, 'six']], g:MytsrFunc1_args)
!   bw!
! 
!   " Set 'thesaurusfunc' to a string(lambda expression)
!   let &thesaurusfunc = '{a, b -> MytsrFunc1(18, a, b)}'
!   new | only
!   call setline(1, 'six')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[18, 1, ''], [18, 0, 'six']], g:MytsrFunc1_args)
!   bw!
! 
!   " Set 'thesaurusfunc' to a variable with a lambda expression
!   let Lambda = {a, b -> MytsrFunc1(19, a, b)}
!   let &thesaurusfunc = Lambda
!   new | only
!   call setline(1, 'seven')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:MytsrFunc1_args)
!   bw!
! 
!   " Set 'thesaurusfunc' to a string(variable with a lambda expression)
!   let Lambda = {a, b -> MytsrFunc1(20, a, b)}
!   let &thesaurusfunc = string(Lambda)
!   new | only
!   call setline(1, 'seven')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:MytsrFunc1_args)
!   bw!
! 
!   " Test for using a lambda function with incorrect return value
!   let Lambda = {s -> strlen(s)}
!   let &thesaurusfunc = Lambda
!   new | only
!   call setline(1, 'eight')
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   bw!
! 
!   " Test for clearing the 'thesaurusfunc' option
!   set thesaurusfunc=''
!   set thesaurusfunc&
  
-   call assert_fails("set thesaurusfunc=function('abc')", "E700:")
-   call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
    let &thesaurusfunc = {a -> 'abc'}
    call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
  
    " Using Vim9 lambda expression in legacy context should fail
!   set thesaurusfunc=(a,\ b)\ =>\ g:MytsrFunc1(21,\ a,\ b)
    new | only
    let g:MytsrFunc1_args = []
    call assert_fails('call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")', 'E117:')
    call assert_equal([], g:MytsrFunc1_args)
    bw!
  
!   " Use a buffer-local value and a global value
!   set thesaurusfunc&
!   setlocal thesaurusfunc=function('MytsrFunc1',[22])
!   call setline(1, 'sun')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
!   call assert_equal('sun', getline(1))
!   call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:MytsrFunc1_args)
    new
!   call setline(1, 'sun')
!   let g:MytsrFunc1_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
!   call assert_equal('sun', getline(1))
!   call assert_equal([], g:MytsrFunc1_args)
!   set thesaurusfunc=function('MytsrFunc1',[23])
    wincmd w
-   call setline(1, 'sun')
-   let g:MytsrFunc1_args = []
-   call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
-   call assert_equal('sun', getline(1))
-   call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:MytsrFunc1_args)
    %bw!
  
!   " set 'thesaurusfunc' to a non-existing function
!   func MytsrFunc2(findstart, base)
!     call add(g:MytsrFunc2_args, [a:findstart, a:base])
!     return a:findstart ? 0 : ['sunday']
    endfunc
!   set thesaurusfunc=MytsrFunc2
!   call setline(1, 'ten')
!   call assert_fails("set thesaurusfunc=function('NonExistingFunc')", 'E700:')
!   call assert_fails("let &thesaurusfunc = function('NonExistingFunc')", 
'E700:')
!   let g:MytsrFunc2_args = []
!   call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!   call assert_equal([[1, ''], [0, 'ten']], g:MytsrFunc2_args)
    bw!
  
    " Vim9 tests
    let lines =<< trim END
      vim9script
  
!     # Test for using function()
      def Vim9tsrFunc(val: number, findstart: number, base: string): any
        add(g:Vim9tsrFunc_Args, [val, findstart, base])
        return findstart ? 0 : []
--- 1277,1491 ----
      return a:findstart ? 0 : []
    endfunc
  
!   let lines =<< trim END
!     #" Test for using a function()
!     set thesaurusfunc=function('g:MytsrFunc1',\ [10])
!     new | only
!     call setline(1, 'one')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[10, 1, ''], [10, 0, 'one']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Using a funcref variable to set 'thesaurusfunc'
!     VAR Fn = function('g:MytsrFunc1', [11])
!     LET &thesaurusfunc = Fn
!     new | only
!     call setline(1, 'two')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[11, 1, ''], [11, 0, 'two']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Using a string(funcref_variable) to set 'thesaurusfunc'
!     LET Fn = function('g:MytsrFunc1', [12])
!     LET &thesaurusfunc = string(Fn)
!     new | only
!     call setline(1, 'two')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[12, 1, ''], [12, 0, 'two']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Test for using a funcref()
!     set thesaurusfunc=funcref('g:MytsrFunc1',\ [13])
!     new | only
!     call setline(1, 'three')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[13, 1, ''], [13, 0, 'three']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Using a funcref variable to set 'thesaurusfunc'
!     LET Fn = funcref('g:MytsrFunc1', [14])
!     LET &thesaurusfunc = Fn
!     new | only
!     call setline(1, 'four')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[14, 1, ''], [14, 0, 'four']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Using a string(funcref_variable) to set 'thesaurusfunc'
!     LET Fn = funcref('g:MytsrFunc1', [15])
!     LET &thesaurusfunc = string(Fn)
!     new | only
!     call setline(1, 'four')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[15, 1, ''], [15, 0, 'four']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Test for using a lambda function
!     VAR optval = "LSTART a, b LMIDDLE MytsrFunc1(16, a, b) LEND"
!     LET optval = substitute(optval, ' ', '\\ ', 'g')
!     exe "set thesaurusfunc=" .. optval
!     new | only
!     call setline(1, 'five')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[16, 1, ''], [16, 0, 'five']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Test for using a lambda function with set
!     LET &thesaurusfunc = LSTART a, b LMIDDLE MytsrFunc1(17, a, b) LEND
!     new | only
!     call setline(1, 'six')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[17, 1, ''], [17, 0, 'six']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Set 'thesaurusfunc' to a string(lambda expression)
!     LET &thesaurusfunc = 'LSTART a, b LMIDDLE MytsrFunc1(18, a, b) LEND'
!     new | only
!     call setline(1, 'six')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[18, 1, ''], [18, 0, 'six']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Set 'thesaurusfunc' to a variable with a lambda expression
!     VAR Lambda = LSTART a, b LMIDDLE MytsrFunc1(19, a, b) LEND
!     LET &thesaurusfunc = Lambda
!     new | only
!     call setline(1, 'seven')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[19, 1, ''], [19, 0, 'seven']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Set 'thesaurusfunc' to a string(variable with a lambda expression)
!     LET Lambda = LSTART a, b LMIDDLE MytsrFunc1(20, a, b) LEND
!     LET &thesaurusfunc = string(Lambda)
!     new | only
!     call setline(1, 'seven')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[20, 1, ''], [20, 0, 'seven']], g:MytsrFunc1_args)
!     bw!
! 
!     #" Test for using a lambda function with incorrect return value
!     LET Lambda = LSTART a, b LMIDDLE strlen(a) LEND
!     LET &thesaurusfunc = Lambda
!     new | only
!     call setline(1, 'eight')
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     bw!
! 
!     #" Test for clearing the 'thesaurusfunc' option
!     set thesaurusfunc=''
!     set thesaurusfunc&
!     call assert_fails("set thesaurusfunc=function('abc')", "E700:")
!     call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
! 
!     #" set 'thesaurusfunc' to a non-existing function
!     func MytsrFunc2(findstart, base)
!       call add(g:MytsrFunc2_args, [a:findstart, a:base])
!       return a:findstart ? 0 : ['sunday']
!     endfunc
!     set thesaurusfunc=MytsrFunc2
!     call setline(1, 'ten')
!     call assert_fails("set thesaurusfunc=function('NonExistingFunc')", 
'E700:')
!     call assert_fails("LET &thesaurusfunc = function('NonExistingFunc')", 
'E700:')
!     LET g:MytsrFunc2_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
!     call assert_equal([[1, ''], [0, 'ten']], g:MytsrFunc2_args)
!     bw!
! 
!     #" Use a buffer-local value and a global value
!     set thesaurusfunc&
!     setlocal thesaurusfunc=function('g:MytsrFunc1',\ [22])
!     call setline(1, 'sun')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
!     call assert_equal('sun', getline(1))
!     call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:MytsrFunc1_args)
!     new
!     call setline(1, 'sun')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
!     call assert_equal('sun', getline(1))
!     call assert_equal([], g:MytsrFunc1_args)
!     set thesaurusfunc=function('g:MytsrFunc1',\ [23])
!     wincmd w
!     call setline(1, 'sun')
!     LET g:MytsrFunc1_args = []
!     call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
!     call assert_equal('sun', getline(1))
!     call assert_equal([[22, 1, ''], [22, 0, 'sun']], g:MytsrFunc1_args)
!     :%bw!
!   END
!   call CheckLegacyAndVim9Success(lines)
  
    let &thesaurusfunc = {a -> 'abc'}
    call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
  
    " Using Vim9 lambda expression in legacy context should fail
!   set thesaurusfunc=(a,\ b)\ =>\ MytsrFunc1(21,\ a,\ b)
    new | only
    let g:MytsrFunc1_args = []
    call assert_fails('call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")', 'E117:')
    call assert_equal([], g:MytsrFunc1_args)
    bw!
  
!   " set 'thesaurusfunc' to a partial with dict. This used to cause a crash.
!   func SetTsrFunc()
!     let params = {'thesaurus': function('g:DictTsrFunc')}
!     let &thesaurusfunc = params.thesaurus
!   endfunc
!   func g:DictTsrFunc(_) dict
!   endfunc
!   call SetTsrFunc()
    new
!   call SetTsrFunc()
!   bw
!   call test_garbagecollect_now()
!   new
!   set thesaurusfunc=
    wincmd w
    %bw!
+   delfunc SetTsrFunc
  
!   " set buffer-local 'thesaurusfunc' to a partial with dict. This used to
!   " cause a crash.
!   func SetLocalTsrFunc()
!     let params = {'thesaurus': function('g:DictTsrFunc')}
!     let &l:thesaurusfunc = params.thesaurus
    endfunc
!   call SetLocalTsrFunc()
!   call test_garbagecollect_now()
!   call SetLocalTsrFunc()
!   set thesaurusfunc=
    bw!
+   delfunc g:DictTsrFunc
+   delfunc SetLocalTsrFunc
  
    " Vim9 tests
    let lines =<< trim END
      vim9script
  
!     # Test for using a def function with thesaurusfunc
      def Vim9tsrFunc(val: number, findstart: number, base: string): any
        add(g:Vim9tsrFunc_Args, [val, findstart, base])
        return findstart ? 0 : []
***************
*** 1486,1529 ****
      feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
      assert_equal([[60, 1, ''], [60, 0, 'one']], g:Vim9tsrFunc_Args)
      bw!
- 
-     # Test for using a lambda
-     &thesaurusfunc = (a, b) => Vim9tsrFunc(61, a, b)
-     new | only
-     setline(1, 'two')
-     g:Vim9tsrFunc_Args = []
-     feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
-     assert_equal([[61, 1, ''], [61, 0, 'two']], g:Vim9tsrFunc_Args)
-     bw!
- 
-     # Test for using a string(lambda)
-     &thesaurusfunc = '(a, b) => Vim9tsrFunc(62, a, b)'
-     new | only
-     setline(1, 'two')
-     g:Vim9tsrFunc_Args = []
-     feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
-     assert_equal([[62, 1, ''], [62, 0, 'two']], g:Vim9tsrFunc_Args)
-     bw!
- 
-     # Test for using a variable with a lambda expression
-     var Fn: func = (a, b) => Vim9tsrFunc(63, a, b)
-     &thesaurusfunc = Fn
-     new | only
-     setline(1, 'three')
-     g:Vim9tsrFunc_Args = []
-     feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
-     assert_equal([[63, 1, ''], [63, 0, 'three']], g:Vim9tsrFunc_Args)
-     bw!
- 
-     # Test for using a string(variable with a lambda expression)
-     Fn = (a, b) => Vim9tsrFunc(64, a, b)
-     &thesaurusfunc = string(Fn)
-     new | only
-     setline(1, 'three')
-     g:Vim9tsrFunc_Args = []
-     feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
-     assert_equal([[64, 1, ''], [64, 0, 'three']], g:Vim9tsrFunc_Args)
-     bw!
    END
    call CheckScriptSuccess(lines)
  
--- 1497,1502 ----
*** ../vim-8.2.3787/src/testdir/test_normal.vim 2021-12-08 10:45:43.329331491 
+0000
--- src/testdir/test_normal.vim 2021-12-12 16:20:28.793487675 +0000
***************
*** 448,557 ****
      let g:OpFuncArgs = [a:val, a:type]
    endfunc
  
!   " Test for using a function()
!   set opfunc=function('MyopFunc',\ [11])
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([11, 'char'], g:OpFuncArgs)
! 
!   " Using a funcref variable to set 'operatorfunc'
!   let Fn = function('MyopFunc', [12])
!   let &opfunc = Fn
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([12, 'char'], g:OpFuncArgs)
! 
!   " Using a string(funcref_variable) to set 'operatorfunc'
!   let Fn = function('MyopFunc', [13])
!   let &operatorfunc = string(Fn)
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([13, 'char'], g:OpFuncArgs)
! 
!   " Test for using a funcref()
!   set operatorfunc=funcref('MyopFunc',\ [14])
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([14, 'char'], g:OpFuncArgs)
! 
!   " Using a funcref variable to set 'operatorfunc'
!   let Fn = funcref('MyopFunc', [15])
!   let &opfunc = Fn
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([15, 'char'], g:OpFuncArgs)
  
!   " Using a string(funcref_variable) to set 'operatorfunc'
!   let Fn = funcref('MyopFunc', [16])
!   let &opfunc = string(Fn)
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([16, 'char'], g:OpFuncArgs)
  
!   " Test for using a lambda function using set
!   set opfunc={a\ ->\ MyopFunc(17,\ a)}
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([17, 'char'], g:OpFuncArgs)
  
!   " Test for using a lambda function using let
!   let &opfunc = {a -> MyopFunc(18, a)}
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([18, 'char'], g:OpFuncArgs)
  
!   " Set 'operatorfunc' to a string(lambda expression)
!   let &opfunc = '{a -> MyopFunc(19, a)}'
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([19, 'char'], g:OpFuncArgs)
  
!   " Set 'operatorfunc' to a variable with a lambda expression
!   let Lambda = {a -> MyopFunc(20, a)}
!   let &opfunc = Lambda
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([20, 'char'], g:OpFuncArgs)
  
!   " Set 'operatorfunc' to a string(variable with a lambda expression)
!   let Lambda = {a -> MyopFunc(21, a)}
!   let &opfunc = string(Lambda)
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([21, 'char'], g:OpFuncArgs)
  
!   " Try to use 'operatorfunc' after the function is deleted
!   func TmpOpFunc(type)
!     let g:OpFuncArgs = [22, a:type]
!   endfunc
!   let &opfunc = function('TmpOpFunc')
!   delfunc TmpOpFunc
!   call test_garbagecollect_now()
!   let g:OpFuncArgs = []
!   call assert_fails('normal! g@l', 'E117:')
!   call assert_equal([], g:OpFuncArgs)
  
!   " Try to use a function with two arguments for 'operatorfunc'
!   func! MyopFunc2(x, y)
!     let g:OpFuncArgs = [a:x, a:y]
!   endfunc
!   set opfunc=MyopFunc2
!   let g:OpFuncArgs = []
!   call assert_fails('normal! g@l', 'E119:')
!   call assert_equal([], g:OpFuncArgs)
  
!   " Try to use a lambda function with two arguments for 'operatorfunc'
!   let &opfunc = {a, b -> MyopFunc(23, b)}
!   let g:OpFuncArgs = []
!   call assert_fails('normal! g@l', 'E119:')
!   call assert_equal([], g:OpFuncArgs)
  
!   " Test for clearing the 'operatorfunc' option
!   set opfunc=''
!   set opfunc&
  
!   call assert_fails("set opfunc=function('abc')", "E700:")
!   call assert_fails("set opfunc=funcref('abc')", "E700:")
  
    " Using Vim9 lambda expression in legacy context should fail
    set opfunc=(a)\ =>\ MyopFunc(24,\ a)
--- 448,569 ----
      let g:OpFuncArgs = [a:val, a:type]
    endfunc
  
!   let lines =<< trim END
!     #" Test for using a function()
!     set opfunc=function('g:MyopFunc',\ [10])
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([10, 'char'], g:OpFuncArgs)
  
!     #" Using a funcref variable to set 'operatorfunc'
!     VAR Fn = function('g:MyopFunc', [11])
!     LET &opfunc = Fn
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([11, 'char'], g:OpFuncArgs)
  
!     #" Using a string(funcref_variable) to set 'operatorfunc'
!     LET Fn = function('g:MyopFunc', [12])
!     LET &operatorfunc = string(Fn)
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([12, 'char'], g:OpFuncArgs)
  
!     #" Test for using a funcref()
!     set operatorfunc=funcref('g:MyopFunc',\ [13])
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([13, 'char'], g:OpFuncArgs)
  
!     #" Using a funcref variable to set 'operatorfunc'
!     LET Fn = funcref('g:MyopFunc', [14])
!     LET &opfunc = Fn
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([14, 'char'], g:OpFuncArgs)
  
!     #" Using a string(funcref_variable) to set 'operatorfunc'
!     LET Fn = funcref('g:MyopFunc', [15])
!     LET &opfunc = string(Fn)
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([15, 'char'], g:OpFuncArgs)
  
!     #" Test for using a lambda function using set
!     VAR optval = "LSTART a LMIDDLE MyopFunc(16, a) LEND"
!     LET optval = substitute(optval, ' ', '\\ ', 'g')
!     exe "set opfunc=" .. optval
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([16, 'char'], g:OpFuncArgs)
  
!     #" Test for using a lambda function using LET
!     LET &opfunc = LSTART a LMIDDLE MyopFunc(17, a) LEND
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([17, 'char'], g:OpFuncArgs)
  
!     #" Set 'operatorfunc' to a string(lambda expression)
!     LET &opfunc = 'LSTART a LMIDDLE MyopFunc(18, a) LEND'
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([18, 'char'], g:OpFuncArgs)
  
!     #" Set 'operatorfunc' to a variable with a lambda expression
!     VAR Lambda = LSTART a LMIDDLE MyopFunc(19, a) LEND
!     LET &opfunc = Lambda
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([19, 'char'], g:OpFuncArgs)
  
!     #" Set 'operatorfunc' to a string(variable with a lambda expression)
!     LET Lambda = LSTART a LMIDDLE MyopFunc(20, a) LEND
!     LET &opfunc = string(Lambda)
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([20, 'char'], g:OpFuncArgs)
  
!     #" Try to use 'operatorfunc' after the function is deleted
!     func g:TmpOpFunc(type)
!       LET g:OpFuncArgs = [21, a:type]
!     endfunc
!     LET &opfunc = function('g:TmpOpFunc')
!     delfunc g:TmpOpFunc
!     call test_garbagecollect_now()
!     LET g:OpFuncArgs = []
!     call assert_fails('normal! g@l', 'E117:')
!     call assert_equal([], g:OpFuncArgs)
! 
!     #" Try to use a function with two arguments for 'operatorfunc'
!     func MyopFunc2(x, y)
!       LET g:OpFuncArgs = [a:x, a:y]
!     endfunc
!     set opfunc=MyopFunc2
!     LET g:OpFuncArgs = []
!     call assert_fails('normal! g@l', 'E119:')
!     call assert_equal([], g:OpFuncArgs)
! 
!     #" Try to use a lambda function with two arguments for 'operatorfunc'
!     LET &opfunc = LSTART a, b LMIDDLE MyopFunc(22, b) LEND
!     LET g:OpFuncArgs = []
!     call assert_fails('normal! g@l', 'E119:')
!     call assert_equal([], g:OpFuncArgs)
! 
!     #" Test for clearing the 'operatorfunc' option
!     set opfunc=''
!     set opfunc&
!     call assert_fails("set opfunc=function('abc')", "E700:")
!     call assert_fails("set opfunc=funcref('abc')", "E700:")
! 
!     #" set 'operatorfunc' to a non-existing function
!     LET &opfunc = function('g:MyopFunc', [23])
!     call assert_fails("set opfunc=function('NonExistingFunc')", 'E700:')
!     call assert_fails("LET &opfunc = function('NonExistingFunc')", 'E700:')
!     LET g:OpFuncArgs = []
!     normal! g@l
!     call assert_equal([23, 'char'], g:OpFuncArgs)
!   END
!   call CheckTransLegacySuccess(lines)
  
    " Using Vim9 lambda expression in legacy context should fail
    set opfunc=(a)\ =>\ MyopFunc(24,\ a)
***************
*** 559,577 ****
    call assert_fails('normal! g@l', 'E117:')
    call assert_equal([], g:OpFuncArgs)
  
!   " set 'operatorfunc' to a non-existing function
!   let &opfunc = function('MyopFunc', [25])
!   call assert_fails("set opfunc=function('NonExistingFunc')", 'E700:')
!   call assert_fails("let &opfunc = function('NonExistingFunc')", 'E700:')
!   let g:OpFuncArgs = []
!   normal! g@l
!   call assert_equal([25, 'char'], g:OpFuncArgs)
  
    " Vim9 tests
    let lines =<< trim END
      vim9script
  
!     # Test for using function()
      def g:Vim9opFunc(val: number, type: string): void
        g:OpFuncArgs = [val, type]
      enddef
--- 571,594 ----
    call assert_fails('normal! g@l', 'E117:')
    call assert_equal([], g:OpFuncArgs)
  
!   " set 'operatorfunc' to a partial with dict. This used to cause a crash.
!   func SetOpFunc()
!     let operator = {'execute': function('OperatorExecute')}
!     let &opfunc = operator.execute
!   endfunc
!   func OperatorExecute(_) dict
!   endfunc
!   call SetOpFunc()
!   call test_garbagecollect_now()
!   set operatorfunc=
!   delfunc SetOpFunc
!   delfunc OperatorExecute
  
    " Vim9 tests
    let lines =<< trim END
      vim9script
  
!     # Test for using a def function with opfunc
      def g:Vim9opFunc(val: number, type: string): void
        g:OpFuncArgs = [val, type]
      enddef
***************
*** 579,611 ****
      g:OpFuncArgs = []
      normal! g@l
      assert_equal([60, 'char'], g:OpFuncArgs)
- 
-     # Test for using a lambda
-     &opfunc = (a) => Vim9opFunc(61, a)
-     g:OpFuncArgs = []
-     normal! g@l
-     assert_equal([61, 'char'], g:OpFuncArgs)
- 
-     # Test for using a string(lambda)
-     &opfunc = '(a) => Vim9opFunc(62, a)'
-     g:OpFuncArgs = []
-     normal! g@l
-     assert_equal([62, 'char'], g:OpFuncArgs)
- 
-     # Test for using a variable with a lambda expression
-     var Fn: func = (a) => Vim9opFunc(63, a)
-     &opfunc = Fn
-     g:OpFuncArgs = []
-     normal! g@l
-     assert_equal([63, 'char'], g:OpFuncArgs)
- 
-     # Test for using a string(variable with a lambda expression)
-     Fn = (a) => Vim9opFunc(64, a)
-     &opfunc = string(Fn)
-     g:OpFuncArgs = []
-     normal! g@l
-     assert_equal([64, 'char'], g:OpFuncArgs)
-     bw!
    END
    call CheckScriptSuccess(lines)
  
--- 596,601 ----
*** ../vim-8.2.3787/src/testdir/test_quickfix.vim       2021-12-09 
09:26:58.499426044 +0000
--- src/testdir/test_quickfix.vim       2021-12-12 16:20:28.793487675 +0000
***************
*** 1,6 ****
--- 1,7 ----
  " Test for the quickfix feature.
  
  source check.vim
+ source vim9.vim
  CheckFeature quickfix
  
  source screendump.vim
***************
*** 5282,5287 ****
--- 5283,5413 ----
    call Xtest_qftextfunc('l')
  endfunc
  
+ func Test_qftextfunc_callback()
+   let lines =<< trim END
+     set efm=%f:%l:%c:%m
+ 
+     #" Test for using a function()
+     set qftf=function('g:Tqfexpr')
+     cexpr "F1:1:1:L1"
+     copen
+     call assert_equal('F1-L1C1-L1', getline(1))
+     cclose
+ 
+     #" Using a funcref variable to set 'quickfixtextfunc'
+     VAR Fn = function('g:Tqfexpr')
+     LET &qftf = Fn
+     cexpr "F2:2:2:L2"
+     copen
+     call assert_equal('F2-L2C2-L2', getline(1))
+     cclose
+ 
+     #" Using string(funcref_variable) to set 'quickfixtextfunc'
+     LET Fn = function('g:Tqfexpr')
+     LET &qftf = string(Fn)
+     cexpr "F3:3:3:L3"
+     copen
+     call assert_equal('F3-L3C3-L3', getline(1))
+     cclose
+ 
+     #" Test for using a funcref()
+     set qftf=funcref('g:Tqfexpr')
+     cexpr "F4:4:4:L4"
+     copen
+     call assert_equal('F4-L4C4-L4', getline(1))
+     cclose
+ 
+     #" Using a funcref variable to set 'quickfixtextfunc'
+     LET Fn = funcref('g:Tqfexpr')
+     LET &qftf = Fn
+     cexpr "F5:5:5:L5"
+     copen
+     call assert_equal('F5-L5C5-L5', getline(1))
+     cclose
+ 
+     #" Using a string(funcref_variable) to set 'quickfixtextfunc'
+     LET Fn = funcref('g:Tqfexpr')
+     LET &qftf = string(Fn)
+     cexpr "F5:5:5:L5"
+     copen
+     call assert_equal('F5-L5C5-L5', getline(1))
+     cclose
+ 
+     #" Test for using a lambda function with set
+     VAR optval = "LSTART a LMIDDLE Tqfexpr(a) LEND"
+     LET optval = substitute(optval, ' ', '\\ ', 'g')
+     exe "set qftf=" .. optval
+     cexpr "F6:6:6:L6"
+     copen
+     call assert_equal('F6-L6C6-L6', getline(1))
+     cclose
+ 
+     #" Set 'quickfixtextfunc' to a lambda expression
+     LET &qftf = LSTART a LMIDDLE Tqfexpr(a) LEND
+     cexpr "F7:7:7:L7"
+     copen
+     call assert_equal('F7-L7C7-L7', getline(1))
+     cclose
+ 
+     #" Set 'quickfixtextfunc' to string(lambda_expression)
+     LET &qftf = "LSTART a LMIDDLE Tqfexpr(a) LEND"
+     cexpr "F8:8:8:L8"
+     copen
+     call assert_equal('F8-L8C8-L8', getline(1))
+     cclose
+ 
+     #" Set 'quickfixtextfunc' to a variable with a lambda expression
+     VAR Lambda = LSTART a LMIDDLE Tqfexpr(a) LEND
+     LET &qftf = Lambda
+     cexpr "F9:9:9:L9"
+     copen
+     call assert_equal('F9-L9C9-L9', getline(1))
+     cclose
+ 
+     #" Set 'quickfixtextfunc' to a string(variable with a lambda expression)
+     LET Lambda = LSTART a LMIDDLE Tqfexpr(a) LEND
+     LET &qftf = string(Lambda)
+     cexpr "F9:9:9:L9"
+     copen
+     call assert_equal('F9-L9C9-L9', getline(1))
+     cclose
+   END
+   call CheckLegacyAndVim9Success(lines)
+ 
+   " set 'quickfixtextfunc' to a partial with dict. This used to cause a crash.
+   func SetQftfFunc()
+     let params = {'qftf': function('g:DictQftfFunc')}
+     let &quickfixtextfunc = params.qftf
+   endfunc
+   func g:DictQftfFunc(_) dict
+   endfunc
+   call SetQftfFunc()
+   new
+   call SetQftfFunc()
+   bw
+   call test_garbagecollect_now()
+   new
+   set qftf=
+   wincmd w
+   set qftf=
+   :%bw!
+ 
+   " set per-quickfix list 'quickfixtextfunc' to a partial with dict. This used
+   " to cause a crash.
+   let &qftf = ''
+   func SetLocalQftfFunc()
+     let params = {'qftf': function('g:DictQftfFunc')}
+     call setqflist([], 'a', {'quickfixtextfunc' : params.qftf})
+   endfunc
+   call SetLocalQftfFunc()
+   call test_garbagecollect_now()
+   call setqflist([], 'a', {'quickfixtextfunc' : ''})
+   delfunc g:DictQftfFunc
+   delfunc SetQftfFunc
+   delfunc SetLocalQftfFunc
+   set efm&
+ endfunc
+ 
  " Test for updating a location list for some other window and check that
  " 'qftextfunc' uses the correct location list.
  func Test_qftextfunc_other_loclist()
*** ../vim-8.2.3787/src/testdir/test_tagfunc.vim        2021-12-08 
10:45:43.329331491 +0000
--- src/testdir/test_tagfunc.vim        2021-12-12 16:20:28.793487675 +0000
***************
*** 132,186 ****
      return v:null
    endfunc
  
!   " Test for using a function()
!   set tagfunc=function('MytagFunc1',[10])
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails('tag a11', 'E433:')
!   call assert_equal([10, 'a11', '', {}], g:MytagFunc1_args)
  
!   " Using a funcref variable to set 'tagfunc'
!   let Fn = function('MytagFunc1', [11])
!   let &tagfunc = Fn
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails('tag a12', 'E433:')
!   call assert_equal([11, 'a12', '', {}], g:MytagFunc1_args)
  
!   " Using a string(funcref_variable) to set 'tagfunc'
!   let Fn = function('MytagFunc1', [12])
!   let &tagfunc = string(Fn)
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails('tag a12', 'E433:')
!   call assert_equal([12, 'a12', '', {}], g:MytagFunc1_args)
  
!   " Test for using a funcref()
!   func MytagFunc2(pat, flags, info)
!     let g:MytagFunc2_args = [a:pat, a:flags, a:info]
!     return v:null
!   endfunc
!   set tagfunc=funcref('MytagFunc1',[13])
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails('tag a13', 'E433:')
!   call assert_equal([13, 'a13', '', {}], g:MytagFunc1_args)
  
!   " Using a funcref variable to set 'tagfunc'
!   let Fn = funcref('MytagFunc1', [14])
!   let &tagfunc = Fn
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails('tag a14', 'E433:')
!   call assert_equal([14, 'a14', '', {}], g:MytagFunc1_args)
  
!   " Using a string(funcref_variable) to set 'tagfunc'
!   let Fn = funcref('MytagFunc1', [15])
!   let &tagfunc = string(Fn)
    new | only
    let g:MytagFunc1_args = []
!   call assert_fails('tag a14', 'E433:')
!   call assert_equal([15, 'a14', '', {}], g:MytagFunc1_args)
  
    " Test for using a script local function
    set tagfunc=<SID>ScriptLocalTagFunc
--- 132,252 ----
      return v:null
    endfunc
  
!   let lines =<< trim END
!     #" Test for using a function()
!     set tagfunc=function('g:MytagFunc1',\ [10])
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails('tag a11', 'E433:')
!     call assert_equal([10, 'a11', '', {}], g:MytagFunc1_args)
! 
!     #" Using a funcref variable to set 'tagfunc'
!     VAR Fn = function('g:MytagFunc1', [11])
!     LET &tagfunc = Fn
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails('tag a12', 'E433:')
!     call assert_equal([11, 'a12', '', {}], g:MytagFunc1_args)
! 
!     #" Using a string(funcref_variable) to set 'tagfunc'
!     LET Fn = function('g:MytagFunc1', [12])
!     LET &tagfunc = string(Fn)
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails('tag a12', 'E433:')
!     call assert_equal([12, 'a12', '', {}], g:MytagFunc1_args)
  
!     #" Test for using a funcref()
!     set tagfunc=funcref('g:MytagFunc1',\ [13])
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails('tag a13', 'E433:')
!     call assert_equal([13, 'a13', '', {}], g:MytagFunc1_args)
! 
!     #" Using a funcref variable to set 'tagfunc'
!     LET Fn = funcref('g:MytagFunc1', [14])
!     LET &tagfunc = Fn
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails('tag a14', 'E433:')
!     call assert_equal([14, 'a14', '', {}], g:MytagFunc1_args)
! 
!     #" Using a string(funcref_variable) to set 'tagfunc'
!     LET Fn = funcref('g:MytagFunc1', [15])
!     LET &tagfunc = string(Fn)
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails('tag a14', 'E433:')
!     call assert_equal([15, 'a14', '', {}], g:MytagFunc1_args)
! 
!     #" Test for using a lambda function
!     VAR optval = "LSTART a, b, c LMIDDLE MytagFunc1(16, a, b, c) LEND"
!     LET optval = substitute(optval, ' ', '\\ ', 'g')
!     exe "set tagfunc=" .. optval
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails('tag a17', 'E433:')
!     call assert_equal([16, 'a17', '', {}], g:MytagFunc1_args)
  
!     #" Set 'tagfunc' to a lambda expression
!     LET &tagfunc = LSTART a, b, c LMIDDLE MytagFunc1(17, a, b, c) LEND
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails('tag a18', 'E433:')
!     call assert_equal([17, 'a18', '', {}], g:MytagFunc1_args)
  
!     #" Set 'tagfunc' to a string(lambda expression)
!     LET &tagfunc = 'LSTART a, b, c LMIDDLE MytagFunc1(18, a, b, c) LEND'
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails('tag a18', 'E433:')
!     call assert_equal([18, 'a18', '', {}], g:MytagFunc1_args)
! 
!     #" Set 'tagfunc' to a variable with a lambda expression
!     VAR Lambda = LSTART a, b, c LMIDDLE MytagFunc1(19, a, b, c) LEND
!     LET &tagfunc = Lambda
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails("tag a19", "E433:")
!     call assert_equal([19, 'a19', '', {}], g:MytagFunc1_args)
! 
!     #" Set 'tagfunc' to a string(variable with a lambda expression)
!     LET Lambda = LSTART a, b, c LMIDDLE MytagFunc1(20, a, b, c) LEND
!     LET &tagfunc = string(Lambda)
!     new | only
!     LET g:MytagFunc1_args = []
!     call assert_fails("tag a19", "E433:")
!     call assert_equal([20, 'a19', '', {}], g:MytagFunc1_args)
! 
!     #" Test for using a lambda function with incorrect return value
!     LET Lambda = LSTART a, b, c LMIDDLE strlen(a) LEND
!     LET &tagfunc = string(Lambda)
!     new | only
!     call assert_fails("tag a20", "E987:")
  
!     #" Test for clearing the 'tagfunc' option
!     set tagfunc=''
!     set tagfunc&
!     call assert_fails("set tagfunc=function('abc')", "E700:")
!     call assert_fails("set tagfunc=funcref('abc')", "E700:")
! 
!     #" set 'tagfunc' to a non-existing function
!     LET &tagfunc = function('g:MytagFunc1', [21])
!     call assert_fails("set tagfunc=function('NonExistingFunc')", 'E700:')
!     call assert_fails("LET &tagfunc = function('NonExistingFunc')", 'E700:')
!     call assert_fails("tag axb123", 'E426:')
!   END
!   call CheckLegacyAndVim9Success(lines)
! 
!   let &tagfunc = "{a -> 'abc'}"
!   call assert_fails("echo taglist('a')", "E987:")
  
!   " Using Vim9 lambda expression in legacy context should fail
!   set tagfunc=(a,\ b,\ c)\ =>\ g:MytagFunc1(21,\ a,\ b,\ c)
    new | only
    let g:MytagFunc1_args = []
!   call assert_fails("tag a17", "E117:")
!   call assert_equal([], g:MytagFunc1_args)
  
    " Test for using a script local function
    set tagfunc=<SID>ScriptLocalTagFunc
***************
*** 205,274 ****
    call assert_fails('tag a16', 'E433:')
    call assert_equal(['a16', '', {}], g:ScriptLocalFuncArgs)
  
!   " Test for using a lambda function
!   set tagfunc={a,\ b,\ c\ ->\ MytagFunc1(16,\ a,\ b,\ c)}
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails('tag a17', 'E433:')
!   call assert_equal([16, 'a17', '', {}], g:MytagFunc1_args)
! 
!   " Set 'tagfunc' to a lambda expression
!   let &tagfunc = {a, b, c -> MytagFunc1(17, a, b, c)}
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails('tag a18', 'E433:')
!   call assert_equal([17, 'a18', '', {}], g:MytagFunc1_args)
! 
!   " Set 'tagfunc' to a string(lambda expression)
!   let &tagfunc = '{a, b, c -> MytagFunc1(18, a, b, c)}'
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails('tag a18', 'E433:')
!   call assert_equal([18, 'a18', '', {}], g:MytagFunc1_args)
! 
!   " Set 'tagfunc' to a variable with a lambda expression
!   let Lambda = {a, b, c -> MytagFunc1(19, a, b, c)}
!   let &tagfunc = Lambda
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails("tag a19", "E433:")
!   call assert_equal([19, 'a19', '', {}], g:MytagFunc1_args)
! 
!   " Set 'tagfunc' to a string(variable with a lambda expression)
!   let Lambda = {a, b, c -> MytagFunc1(20, a, b, c)}
!   let &tagfunc = string(Lambda)
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails("tag a19", "E433:")
!   call assert_equal([20, 'a19', '', {}], g:MytagFunc1_args)
! 
!   " Test for using a lambda function with incorrect return value
!   let Lambda = {s -> strlen(s)}
!   let &tagfunc = string(Lambda)
!   new | only
!   call assert_fails("tag a20", "E987:")
! 
!   " Test for clearing the 'tagfunc' option
!   set tagfunc=''
!   set tagfunc&
! 
!   call assert_fails("set tagfunc=function('abc')", "E700:")
!   call assert_fails("set tagfunc=funcref('abc')", "E700:")
!   let &tagfunc = "{a -> 'abc'}"
!   call assert_fails("echo taglist('a')", "E987:")
! 
!   " Using Vim9 lambda expression in legacy context should fail
!   set tagfunc=(a,\ b,\ c)\ =>\ g:MytagFunc1(21,\ a,\ b,\ c)
!   new | only
!   let g:MytagFunc1_args = []
!   call assert_fails("tag a17", "E117:")
!   call assert_equal([], g:MytagFunc1_args)
! 
!   " set 'tagfunc' to a non-existing function
!   call assert_fails("set tagfunc=function('NonExistingFunc')", 'E700:')
!   call assert_fails("let &tagfunc = function('NonExistingFunc')", 'E700:')
!   call assert_fails("tag axb123", 'E426:')
!   bw!
  
    " Vim9 tests
    let lines =<< trim END
--- 271,295 ----
    call assert_fails('tag a16', 'E433:')
    call assert_equal(['a16', '', {}], g:ScriptLocalFuncArgs)
  
!   " set 'tagfunc' to a partial with dict. This used to cause a crash.
!   func SetTagFunc()
!     let params = {'tagfn': function('g:DictTagFunc')}
!     let &tagfunc = params.tagfn
!   endfunc
!   func g:DictTagFunc(_) dict
!   endfunc
!   call SetTagFunc()
!   new
!   call SetTagFunc()
!   bw
!   call test_garbagecollect_now()
!   new
!   set tagfunc=
!   wincmd w
!   set tagfunc=
!   :%bw!
!   delfunc g:DictTagFunc
!   delfunc SetTagFunc
  
    " Vim9 tests
    let lines =<< trim END
***************
*** 284,325 ****
      g:Vim9tagFuncArgs = []
      assert_fails('tag a10', 'E433:')
      assert_equal([60, 'a10', '', {}], g:Vim9tagFuncArgs)
- 
-     # Test for using a lambda
-     &tagfunc = (a, b, c) => MytagFunc1(61, a, b, c)
-     new | only
-     g:MytagFunc1_args = []
-     assert_fails('tag a20', 'E433:')
-     assert_equal([61, 'a20', '', {}], g:MytagFunc1_args)
- 
-     # Test for using a string(lambda)
-     &tagfunc = '(a, b, c) => MytagFunc1(62, a, b, c)'
-     new | only
-     g:MytagFunc1_args = []
-     assert_fails('tag a20', 'E433:')
-     assert_equal([62, 'a20', '', {}], g:MytagFunc1_args)
- 
-     # Test for using a variable with a lambda expression
-     var Fn: func = (a, b, c) => MytagFunc1(63, a, b, c)
-     &tagfunc = Fn
-     new | only
-     g:MytagFunc1_args = []
-     assert_fails('tag a30', 'E433:')
-     assert_equal([63, 'a30', '', {}], g:MytagFunc1_args)
- 
-     # Test for using a variable with a lambda expression
-     Fn = (a, b, c) => MytagFunc1(64, a, b, c)
-     &tagfunc = string(Fn)
-     new | only
-     g:MytagFunc1_args = []
-     assert_fails('tag a30', 'E433:')
-     assert_equal([64, 'a30', '', {}], g:MytagFunc1_args)
    END
    call CheckScriptSuccess(lines)
  
    " cleanup
    delfunc MytagFunc1
-   delfunc MytagFunc2
    set tagfunc&
    %bw!
  endfunc
--- 305,315 ----
*** ../vim-8.2.3787/src/version.c       2021-12-12 14:16:34.993862200 +0000
--- src/version.c       2021-12-12 16:23:05.057103921 +0000
***************
*** 755,756 ****
--- 755,758 ----
  {   /* Add new patch number below this line */
+ /**/
+     3788,
  /**/

-- 
How To Keep A Healthy Level Of Insanity:
16. Have your coworkers address you by your wrestling name, Rock Hard Kim.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            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/20211212162837.5668A1C0D69%40moolenaar.net.

Raspunde prin e-mail lui