patch 8.2.2331: Vim9: wrong error when modifying dict declared with :final

Problem:    Vim9: wrong error when modifying dict declared with :final.
Solution:   Do not check for writable variable when an index follows.
            (closes #7657)
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 0064bd2..4b2ee07 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2127,10 +2127,29 @@
 }
 
 /*
+ * If "check_writable" is ASSIGN_CONST give an error if the variable was
+ * defined with :final or :const, if "check_writable" is ASSIGN_FINAL give an
+ * error if the variable was defined with :const.
+ */
+    static int
+check_item_writable(svar_T *sv, int check_writable, char_u *name)
+{
+    if ((check_writable == ASSIGN_CONST && sv->sv_const != 0)
+	    || (check_writable == ASSIGN_FINAL
+					      && sv->sv_const == ASSIGN_CONST))
+    {
+	semsg(_(e_readonlyvar), name);
+	return FAIL;
+    }
+    return OK;
+}
+
+/*
  * Find "name" in script-local items of script "sid".
+ * Pass "check_writable" to check_item_writable().
  * Returns the index in "sn_var_vals" if found.
  * If found but not in "sn_var_vals" returns -1.
- * If not found returns -2.
+ * If not found or the variable is not writable returns -2.
  */
     int
 get_script_item_idx(int sid, char_u *name, int check_writable, cctx_T *cctx)
@@ -2151,8 +2170,8 @@
 	    return -2;
 	idx = sav->sav_var_vals_idx;
 	sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
-	if (check_writable && sv->sv_const)
-	    semsg(_(e_readonlyvar), name);
+	if (check_item_writable(sv, check_writable, name) == FAIL)
+	    return -2;
 	return idx;
     }
 
@@ -2168,8 +2187,8 @@
 	sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
 	if (sv->sv_tv == &di->di_tv)
 	{
-	    if (check_writable && sv->sv_const)
-		semsg(_(e_readonlyvar), name);
+	    if (check_item_writable(sv, check_writable, name) == FAIL)
+		return -2;
 	    return idx;
 	}
     }
@@ -2466,7 +2485,7 @@
     if (!SCRIPT_ID_VALID(current_sctx.sc_sid))
 	return FAIL;
     si = SCRIPT_ITEM(current_sctx.sc_sid);
-    idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE, cctx);
+    idx = get_script_item_idx(current_sctx.sc_sid, name, 0, cctx);
     if (idx == -1 || si->sn_version != SCRIPT_VERSION_VIM9)
     {
 	// variable is not in sn_var_vals: old style script.
@@ -5475,6 +5494,11 @@
     lhs->lhs_name = vim_strnsave(var_start, lhs->lhs_varlen);
     if (lhs->lhs_name == NULL)
 	return FAIL;
+
+    if (lhs->lhs_dest_end > var_start + lhs->lhs_varlen)
+	// Something follows after the variable: "var[idx]" or "var.key".
+	lhs->lhs_has_index = TRUE;
+
     if (heredoc)
 	lhs->lhs_type = &t_list_string;
     else
@@ -5576,9 +5600,11 @@
 			lhs->lhs_scriptvar_sid = import->imp_sid;
 		    if (SCRIPT_ID_VALID(lhs->lhs_scriptvar_sid))
 		    {
+			// Check writable only when no index follows.
 			lhs->lhs_scriptvar_idx = get_script_item_idx(
-							lhs->lhs_scriptvar_sid,
-							  rawname, TRUE, cctx);
+					       lhs->lhs_scriptvar_sid, rawname,
+			      lhs->lhs_has_index ? ASSIGN_FINAL : ASSIGN_CONST,
+									 cctx);
 			if (lhs->lhs_scriptvar_idx >= 0)
 			{
 			    scriptitem_T *si = SCRIPT_ITEM(
@@ -5665,7 +5691,7 @@
     }
 
     lhs->lhs_member_type = lhs->lhs_type;
-    if (lhs->lhs_dest_end > var_start + lhs->lhs_varlen)
+    if (lhs->lhs_has_index)
     {
 	// Something follows after the variable: "var[idx]" or "var.key".
 	// TODO: should we also handle "->func()" here?
@@ -5700,7 +5726,6 @@
 		lhs->lhs_type = &t_any;
 	    }
 
-	    lhs->lhs_has_index = TRUE;
 	    if (lhs->lhs_type->tt_member == NULL)
 		lhs->lhs_member_type = &t_any;
 	    else