patch 8.2.2264: Vim9: no error for mismatched :endfunc or :enddef

Problem:    Vim9: no error for mismatched :endfunc or :enddef.
Solution:   Check for the mismatch. (issue #7582)
diff --git a/src/errors.h b/src/errors.h
index 4b4245a..6f4ac0e 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -335,3 +335,7 @@
 	INIT(= N_("E1149: Script variable is invalid after reload in function %s"));
 EXTERN char e_script_variable_type_changed[]
 	INIT(= N_("E1150: Script variable type changed"));
+EXTERN char e_mismatched_endfunction[]
+	INIT(= N_("E1151: Mismatched endfunction"));
+EXTERN char e_mismatched_enddef[]
+	INIT(= N_("E1152: Mismatched enddef"));
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index a2d1ed3..223b2fb 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -79,6 +79,25 @@
   set maxfuncdepth&
 enddef
 
+def Test_endfunc_enddef()
+  var lines =<< trim END
+    def Test()
+      echo 'test'
+      endfunc
+    enddef
+  END
+  CheckScriptFailure(lines, 'E1151:', 3)
+
+  lines =<< trim END
+    def Test()
+      func Nested()
+        echo 'test'
+      enddef
+    enddef
+  END
+  CheckScriptFailure(lines, 'E1152:', 4)
+enddef
+
 def ReturnString(): string
   return 'string'
 enddef
diff --git a/src/userfunc.c b/src/userfunc.c
index bc3dd0e..f0877e1 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -3404,35 +3404,51 @@
 
 	    // Check for "endfunction" or "enddef".
 	    if (checkforcmd(&p, nesting_def[nesting]
-			     ? "enddef" : "endfunction", 4) && nesting-- == 0)
+						? "enddef" : "endfunction", 4))
 	    {
-		char_u *nextcmd = NULL;
-
-		if (*p == '|')
-		    nextcmd = p + 1;
-		else if (line_arg != NULL && *skipwhite(line_arg) != NUL)
-		    nextcmd = line_arg;
-		else if (*p != NUL && *p != '"' && p_verbose > 0)
-		    give_warning2(eap->cmdidx == CMD_def
-			? (char_u *)_("W1001: Text found after :enddef: %s")
-			: (char_u *)_("W22: Text found after :endfunction: %s"),
-			 p, TRUE);
-		if (nextcmd != NULL)
+		if (nesting-- == 0)
 		{
-		    // Another command follows. If the line came from "eap" we
-		    // can simply point into it, otherwise we need to change
-		    // "eap->cmdlinep".
-		    eap->nextcmd = nextcmd;
-		    if (line_to_free != NULL)
+		    char_u *nextcmd = NULL;
+
+		    if (*p == '|')
+			nextcmd = p + 1;
+		    else if (line_arg != NULL && *skipwhite(line_arg) != NUL)
+			nextcmd = line_arg;
+		    else if (*p != NUL && *p != '"' && p_verbose > 0)
+			give_warning2(eap->cmdidx == CMD_def
+			    ? (char_u *)_("W1001: Text found after :enddef: %s")
+			    : (char_u *)_("W22: Text found after :endfunction: %s"),
+			     p, TRUE);
+		    if (nextcmd != NULL)
 		    {
-			vim_free(*eap->cmdlinep);
-			*eap->cmdlinep = line_to_free;
-			line_to_free = NULL;
+			// Another command follows. If the line came from "eap"
+			// we can simply point into it, otherwise we need to
+			// change "eap->cmdlinep".
+			eap->nextcmd = nextcmd;
+			if (line_to_free != NULL)
+			{
+			    vim_free(*eap->cmdlinep);
+			    *eap->cmdlinep = line_to_free;
+			    line_to_free = NULL;
+			}
 		    }
+		    break;
 		}
-		break;
 	    }
 
+	    // Check for mismatched "endfunc" or "enddef".
+	    // We don't check for "def" inside "func" thus we also can't check
+	    // for "enddef".
+	    // We continue to find the end of the function, although we might
+	    // not find it.
+	    else if (nesting_def[nesting])
+	    {
+		if (checkforcmd(&p, "endfunction", 4))
+		    emsg(_(e_mismatched_endfunction));
+	    }
+	    else if (eap->cmdidx == CMD_def && checkforcmd(&p, "enddef", 4))
+		emsg(_(e_mismatched_enddef));
+
 	    // Increase indent inside "if", "while", "for" and "try", decrease
 	    // at "end".
 	    if (indent > 2 && (*p == '}' || STRNCMP(p, "end", 3) == 0))
diff --git a/src/version.c b/src/version.c
index 26c9d8b..3fc3c01 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2264,
+/**/
     2263,
 /**/
     2262,