patch 8.2.0696: Vim9: nested function does not work properly

Problem:    Vim9: nested function does not work properly
Solution:   Create a function reference.  Check argument count.
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 7127331..840c220 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -93,6 +93,9 @@
   enddef
   assert_equal('nested function', Nested('function'))
 
+  CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:')
+  CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:')
+
   CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
 enddef
 
diff --git a/src/version.c b/src/version.c
index da1a20f..38755db 100644
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    696,
+/**/
     695,
 /**/
     694,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 7e700d5..de2fb96 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -101,7 +101,6 @@
     int		lv_from_outer;	// when TRUE using ctx_outer scope
     int		lv_const;	// when TRUE cannot be assigned to
     int		lv_arg;		// when TRUE this is an argument
-    int		lv_func_idx;	// for nested function
 } lvar_T;
 
 /*
@@ -1504,7 +1503,24 @@
     if (type->tt_type == VAR_ANY)
 	ret_type = &t_any;
     else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
+    {
+	if (type->tt_argcount != -1)
+	{
+	    int	    varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0;
+
+	    if (argcount < type->tt_min_argcount - varargs)
+	    {
+		semsg(_(e_toofewarg), "[reference]");
+		return FAIL;
+	    }
+	    if (!varargs && argcount > type->tt_argcount)
+	    {
+		semsg(_(e_toomanyarg), "[reference]");
+		return FAIL;
+	    }
+	}
 	ret_type = type->tt_member;
+    }
     else
     {
 	semsg(_("E1085: Not a callable type: %s"), name);
@@ -2616,7 +2632,6 @@
     int		error = FCERR_NONE;
     ufunc_T	*ufunc;
     int		res = FAIL;
-    lvar_T	*lvar;
 
     if (varlen >= sizeof(namebuf))
     {
@@ -2643,16 +2658,6 @@
 	goto theend;
     }
 
-    // Check if the name is a nested function.
-    lvar = lookup_local(namebuf, varlen, cctx);
-    if (lvar != NULL && lvar->lv_func_idx > 0)
-    {
-	dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
-							   + lvar->lv_func_idx;
-	res = generate_CALL(cctx, dfunc->df_ufunc, argcount);
-	goto theend;
-    }
-
     // If we can find the function by name generate the right call.
     ufunc = find_func(name, FALSE, cctx);
     if (ufunc != NULL)
@@ -2807,7 +2812,6 @@
     static int
 compile_lambda(char_u **arg, cctx_T *cctx)
 {
-    garray_T	*instr = &cctx->ctx_instr;
     typval_T	rettv;
     ufunc_T	*ufunc;
 
@@ -2825,12 +2829,7 @@
     compile_def_function(ufunc, TRUE, cctx);
 
     if (ufunc->uf_dfunc_idx >= 0)
-    {
-	if (ga_grow(instr, 1) == FAIL)
-	    return FAIL;
-	generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
-	return OK;
-    }
+	return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
     return FAIL;
 }
 
@@ -4103,16 +4102,16 @@
     eap->forceit = FALSE;
     ufunc = def_function(eap, name, cctx);
 
-    if (ufunc == NULL)
+    if (ufunc == NULL || ufunc->uf_dfunc_idx < 0)
 	return NULL;
 
-    // Define a local variable for the function, but change the index to -1 to
-    // mark it as a function name.
+    // Define a local variable for the function reference.
     lvar = reserve_local(cctx, name_start, name_end - name_start,
-						       TRUE, &t_func_unknown);
-    lvar->lv_idx = 0;
-    ++cctx->ctx_locals_count;  // doesn't count as a local variable
-    lvar->lv_func_idx = ufunc->uf_dfunc_idx;
+						    TRUE, ufunc->uf_func_type);
+
+    if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL
+	    || generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL) == FAIL)
+	return NULL;
 
     // TODO: warning for trailing?
     return (char_u *)"";
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 665c6af..c74240f 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -206,11 +206,6 @@
 		       + dfunc->df_varcount + dfunc->df_closure_count) == FAIL)
 	return FAIL;
 
-    // Closure may need the function context where it was defined.
-    // TODO: assuming current context.
-    ectx->ec_outer_stack = &ectx->ec_stack;
-    ectx->ec_outer_frame = ectx->ec_frame_idx;
-
     // Move the vararg-list to below the missing optional arguments.
     if (vararg_count > 0 && arg_to_add > 0)
 	*STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);