patch 8.2.3996: Vim9: type checking lacks information about declared type

Problem:    Vim9: type checking for list and dict lacks information about
            declared type.
Solution:   Add dv_decl_type and lv_decl_type.  Refactor the type stack to
            store two types in each entry.
diff --git a/src/vim9instr.c b/src/vim9instr.c
index 49936c3..4961695 100644
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -57,34 +57,46 @@
     isn_T *
 generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop)
 {
-    garray_T	*stack = &cctx->ctx_type_stack;
-
     RETURN_NULL_IF_SKIP(cctx);
-    stack->ga_len -= drop;
+    cctx->ctx_type_stack.ga_len -= drop;
     return generate_instr(cctx, isn_type);
 }
 
 /*
- * Generate instruction "isn_type" and put "type" on the type stack.
+ * Generate instruction "isn_type" and put "type" on the type stack,
+ * use "decl_type" for the declared type.
  */
     isn_T *
-generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
+generate_instr_type2(
+	cctx_T	    *cctx,
+	isntype_T   isn_type,
+	type_T	    *type,
+	type_T	    *decl_type)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
 
     if ((isn = generate_instr(cctx, isn_type)) == NULL)
 	return NULL;
 
-    if (GA_GROW_FAILS(stack, 1))
+    if (push_type_stack2(cctx, type == NULL ? &t_any : type,
+			       decl_type == NULL ? &t_any : decl_type) == FAIL)
 	return NULL;
-    ((type_T **)stack->ga_data)[stack->ga_len] = type == NULL ? &t_any : type;
-    ++stack->ga_len;
 
     return isn;
 }
 
 /*
+ * Generate instruction "isn_type" and put "type" on the type stack.
+ * Uses "any" for the declared type, which works for constants.  For declared
+ * variables use generate_instr_type2().
+ */
+    isn_T *
+generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type)
+{
+    return generate_instr_type2(cctx, isn_type, type, &t_any);
+}
+
+/*
  * Generate an ISN_DEBUG instruction.
  */
     isn_T *
@@ -111,12 +123,11 @@
 {
     isn_T	*isn;
     isntype_T	isntype = ISN_2STRING;
-    garray_T	*stack = &cctx->ctx_type_stack;
-    type_T	**type;
+    type_T	*type;
 
     RETURN_OK_IF_SKIP(cctx);
-    type = ((type_T **)stack->ga_data) + stack->ga_len + offset;
-    switch ((*type)->tt_type)
+    type = get_type_on_stack(cctx, -1 - offset);
+    switch (type->tt_type)
     {
 	// nothing to be done
 	case VAR_STRING: return OK;
@@ -152,11 +163,11 @@
 	case VAR_JOB:
 	case VAR_CHANNEL:
 	case VAR_INSTR:
-			 to_string_error((*type)->tt_type);
+			 to_string_error(type->tt_type);
 			 return FAIL;
     }
 
-    *type = &t_string;
+    set_type_on_stack(cctx, &t_string, -1 - offset);
     if ((isn = generate_instr(cctx, isntype)) == NULL)
 	return FAIL;
     isn->isn_arg.tostring.offset = offset;
@@ -193,7 +204,6 @@
 	type_T *type2,
 	exprtype_T expr_type)
 {
-    garray_T	*stack = &cctx->ctx_type_stack;
     isn_T	*isn = generate_instr_drop(cctx,
 		      vartype == VAR_NUMBER ? ISN_OPNR
 		    : vartype == VAR_LIST ? ISN_ADDLIST
@@ -225,7 +235,7 @@
     if (vartype == VAR_LIST
 	    && type1->tt_type == VAR_LIST && type2->tt_type == VAR_LIST
 	    && type1->tt_member != type2->tt_member)
-	(((type_T **)stack->ga_data)[stack->ga_len - 1]) = &t_list_any;
+	set_type_on_stack(cctx, &t_list_any, 0);
 
     return isn == NULL ? FAIL : OK;
 }
@@ -256,7 +266,6 @@
     int
 generate_two_op(cctx_T *cctx, char_u *op)
 {
-    garray_T	*stack = &cctx->ctx_type_stack;
     type_T	*type1;
     type_T	*type2;
     vartype_T	vartype;
@@ -265,8 +274,8 @@
     RETURN_OK_IF_SKIP(cctx);
 
     // Get the known type of the two items on the stack.
-    type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2];
-    type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1];
+    type1 = get_type_on_stack(cctx, 1);
+    type2 = get_type_on_stack(cctx, 0);
     vartype = operator_type(type1, type2);
 
     switch (*op)
@@ -323,7 +332,7 @@
 		&& (type2->tt_type == VAR_NUMBER || type2->tt_type == VAR_FLOAT))
 	    type = &t_float;
 #endif
-	((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
+	set_type_on_stack(cctx, type, 0);
     }
 
     return OK;
@@ -415,8 +424,8 @@
     // Get the known type of the two items on the stack.  If they are matching
     // use a type-specific instruction. Otherwise fall back to runtime type
     // checking.
-    type1 = ((type_T **)stack->ga_data)[stack->ga_len - 2]->tt_type;
-    type2 = ((type_T **)stack->ga_data)[stack->ga_len - 1]->tt_type;
+    type1 = get_type_on_stack(cctx, 1)->tt_type;
+    type2 = get_type_on_stack(cctx, 0)->tt_type;
     isntype = get_compare_isn(exprtype, type1, type2);
     if (isntype == ISN_DROP)
 	return FAIL;
@@ -430,7 +439,7 @@
     if (stack->ga_len >= 2)
     {
 	--stack->ga_len;
-	((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
+	set_type_on_stack(cctx, &t_bool, 0);
     }
 
     return OK;
@@ -444,7 +453,6 @@
 generate_2BOOL(cctx_T *cctx, int invert, int offset)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr(cctx, ISN_2BOOL)) == NULL)
@@ -453,7 +461,7 @@
     isn->isn_arg.tobool.offset = offset;
 
     // type becomes bool
-    ((type_T **)stack->ga_data)[stack->ga_len + offset] = &t_bool;
+    set_type_on_stack(cctx, &t_bool, -1 - offset);
 
     return OK;
 }
@@ -465,14 +473,13 @@
 generate_COND2BOOL(cctx_T *cctx)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr(cctx, ISN_COND2BOOL)) == NULL)
 	return FAIL;
 
     // type becomes bool
-    ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_bool;
+    set_type_on_stack(cctx, &t_bool, 0);
 
     return OK;
 }
@@ -485,7 +492,6 @@
 	int	    argidx)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL)
@@ -495,7 +501,7 @@
     isn->isn_arg.type.ct_arg_idx = (int8_T)argidx;
 
     // type becomes expected
-    ((type_T **)stack->ga_data)[stack->ga_len + offset] = expected;
+    set_type_on_stack(cctx, expected, -1 - offset);
 
     return OK;
 }
@@ -567,7 +573,6 @@
 generate_PUSHNR(cctx_T *cctx, varnumber_T number)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr_type(cctx, ISN_PUSHNR, &t_number)) == NULL)
@@ -576,7 +581,7 @@
 
     if (number == 0 || number == 1)
 	// A 0 or 1 number can also be used as a bool.
-	((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_number_bool;
+	set_type_on_stack(cctx, &t_number_bool, 0);
     return OK;
 }
 
@@ -747,9 +752,7 @@
 generate_GETITEM(cctx_T *cctx, int index, int with_op)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
-    type_T	*type = ((type_T **)stack->ga_data)[stack->ga_len
-							  - (with_op ? 2 : 1)];
+    type_T	*type = get_type_on_stack(cctx, with_op ? 1 : 0);
     type_T	*item_type = &t_any;
 
     RETURN_OK_IF_SKIP(cctx);
@@ -767,11 +770,7 @@
     isn->isn_arg.getitem.gi_with_op = with_op;
 
     // add the item type to the type stack
-    if (GA_GROW_FAILS(stack, 1))
-	return FAIL;
-    ((type_T **)stack->ga_data)[stack->ga_len] = item_type;
-    ++stack->ga_len;
-    return OK;
+    return push_type_stack(cctx, item_type);
 }
 
 /*
@@ -895,7 +894,7 @@
     isn_T	*isn;
 
     RETURN_OK_IF_SKIP(cctx);
-    if ((isn = generate_instr_type(cctx, isn_type, type)) == NULL)
+    if ((isn = generate_instr_type2(cctx, isn_type, type, type)) == NULL)
 	return FAIL;
     if (name != NULL)
 	isn->isn_arg.string = vim_strsave(name);
@@ -918,7 +917,7 @@
     isn_T	*isn;
 
     RETURN_OK_IF_SKIP(cctx);
-    if ((isn = generate_instr_type(cctx, ISN_LOADOUTER, type)) == NULL)
+    if ((isn = generate_instr_type2(cctx, ISN_LOADOUTER, type, type)) == NULL)
 	return FAIL;
     isn->isn_arg.outer.outer_idx = idx;
     isn->isn_arg.outer.outer_depth = nesting;
@@ -1050,34 +1049,27 @@
 generate_NEWLIST(cctx_T *cctx, int count)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
+    type_T	*member_type;
+    type_T	*decl_member_type;
     type_T	*type;
-    type_T	*member;
+    type_T	*decl_type;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr(cctx, ISN_NEWLIST)) == NULL)
 	return FAIL;
     isn->isn_arg.number = count;
 
-    // get the member type from all the items on the stack.
-    if (count == 0)
-	member = &t_unknown;
-    else
-	member = get_member_type_from_stack(
-	    ((type_T **)stack->ga_data) + stack->ga_len, count, 1,
-							  cctx->ctx_type_list);
-    type = get_list_type(member, cctx->ctx_type_list);
+    // Get the member type and the declared member type from all the items on
+    // the stack.
+    member_type = get_member_type_from_stack(count, 1, &decl_member_type, cctx);
+    type = get_list_type(member_type, cctx->ctx_type_list);
+    decl_type = get_list_type(decl_member_type, cctx->ctx_type_list);
 
     // drop the value types
-    stack->ga_len -= count;
+    cctx->ctx_type_stack.ga_len -= count;
 
     // add the list type to the type stack
-    if (GA_GROW_FAILS(stack, 1))
-	return FAIL;
-    ((type_T **)stack->ga_data)[stack->ga_len] = type;
-    ++stack->ga_len;
-
-    return OK;
+    return push_type_stack2(cctx, type, decl_type);
 }
 
 /*
@@ -1087,33 +1079,26 @@
 generate_NEWDICT(cctx_T *cctx, int count)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
+    type_T	*member_type;
+    type_T	*decl_member_type;
     type_T	*type;
-    type_T	*member;
+    type_T	*decl_type;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr(cctx, ISN_NEWDICT)) == NULL)
 	return FAIL;
     isn->isn_arg.number = count;
 
-    if (count == 0)
-	member = &t_void;
-    else
-	member = get_member_type_from_stack(
-	    ((type_T **)stack->ga_data) + stack->ga_len, count, 2,
-							  cctx->ctx_type_list);
-    type = get_dict_type(member, cctx->ctx_type_list);
+    member_type = get_member_type_from_stack(count, 2,
+						      &decl_member_type, cctx);
+    type = get_dict_type(member_type, cctx->ctx_type_list);
+    decl_type = get_dict_type(decl_member_type, cctx->ctx_type_list);
 
     // drop the key and value types
-    stack->ga_len -= 2 * count;
+    cctx->ctx_type_stack.ga_len -= 2 * count;
 
     // add the dict type to the type stack
-    if (GA_GROW_FAILS(stack, 1))
-	return FAIL;
-    ((type_T **)stack->ga_data)[stack->ga_len] = type;
-    ++stack->ga_len;
-
-    return OK;
+    return push_type_stack2(cctx, type, decl_type);
 }
 
 /*
@@ -1123,7 +1108,7 @@
 generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
+    type_T	*type;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
@@ -1139,13 +1124,8 @@
     if (ufunc->uf_flags & FC_CLOSURE)
 	cctx->ctx_ufunc->uf_flags |= FC_CLOSURE;
 
-    if (GA_GROW_FAILS(stack, 1))
-	return FAIL;
-    ((type_T **)stack->ga_data)[stack->ga_len] =
-	       ufunc->uf_func_type == NULL ? &t_func_any : ufunc->uf_func_type;
-    ++stack->ga_len;
-
-    return OK;
+    type = ufunc->uf_func_type == NULL ? &t_func_any : ufunc->uf_func_type;
+    return push_type_stack(cctx, type);
 }
 
 /*
@@ -1237,20 +1217,14 @@
 generate_FOR(cctx_T *cctx, int loop_idx)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr(cctx, ISN_FOR)) == NULL)
 	return FAIL;
     isn->isn_arg.forloop.for_idx = loop_idx;
 
-    if (GA_GROW_FAILS(stack, 1))
-	return FAIL;
     // type doesn't matter, will be stored next
-    ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
-    ++stack->ga_len;
-
-    return OK;
+    return push_type_stack(cctx, &t_any);
 }
 /*
  * Generate an ISN_TRYCONT instruction.
@@ -1281,9 +1255,11 @@
     isn_T	*isn;
     garray_T	*stack = &cctx->ctx_type_stack;
     int		argoff;
-    type_T	**argtypes = NULL;
-    type_T	*shuffled_argtypes[MAX_FUNC_ARGS];
-    type_T	*maptype = NULL;
+    type2_T	*typep;
+    type2_T	*argtypes = NULL;
+    type2_T	shuffled_argtypes[MAX_FUNC_ARGS];
+    type2_T	*maptype = NULL;
+    type_T	*type;
 
     RETURN_OK_IF_SKIP(cctx);
     argoff = check_internal_func(func_idx, argcount);
@@ -1301,22 +1277,30 @@
     if (argcount > 0)
     {
 	// Check the types of the arguments.
-	argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
+	typep = ((type2_T *)stack->ga_data) + stack->ga_len - argcount;
 	if (method_call && argoff > 1)
 	{
 	    int i;
 
 	    for (i = 0; i < argcount; ++i)
 		shuffled_argtypes[i] = (i < argoff - 1)
-			    ? argtypes[i + 1]
-			    : (i == argoff - 1) ? argtypes[0] : argtypes[i];
+			    ? typep[i + 1]
+				  : (i == argoff - 1) ? typep[0] : typep[i];
+	    argtypes = shuffled_argtypes;
+	}
+	else
+	{
+	    int i;
+
+	    for (i = 0; i < argcount; ++i)
+		shuffled_argtypes[i] = typep[i];
 	    argtypes = shuffled_argtypes;
 	}
 	if (internal_func_check_arg_types(argtypes, func_idx, argcount,
 								 cctx) == FAIL)
 	    return FAIL;
 	if (internal_func_is_map(func_idx))
-	    maptype = *argtypes;
+	    maptype = argtypes;
     }
 
     if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
@@ -1326,16 +1310,14 @@
 
     // Drop the argument types and push the return type.
     stack->ga_len -= argcount;
-    if (GA_GROW_FAILS(stack, 1))
+    type = internal_func_ret_type(func_idx, argcount, argtypes);
+    if (push_type_stack(cctx, type) == FAIL)
 	return FAIL;
-    ((type_T **)stack->ga_data)[stack->ga_len] =
-			  internal_func_ret_type(func_idx, argcount, argtypes);
-    ++stack->ga_len;
 
-    if (maptype != NULL && maptype->tt_member != NULL
-					       && maptype->tt_member != &t_any)
+    if (maptype != NULL && maptype[0].type_curr->tt_member != NULL
+				  && maptype[0].type_curr->tt_member != &t_any)
 	// Check that map() didn't change the item types.
-	generate_TYPECHECK(cctx, maptype, -1, 1);
+	generate_TYPECHECK(cctx, maptype[0].type_curr, -1, 1);
 
     return OK;
 }
@@ -1347,14 +1329,13 @@
     int
 generate_LISTAPPEND(cctx_T *cctx)
 {
-    garray_T	*stack = &cctx->ctx_type_stack;
     type_T	*list_type;
     type_T	*item_type;
     type_T	*expected;
 
     // Caller already checked that list_type is a list.
-    list_type = ((type_T **)stack->ga_data)[stack->ga_len - 2];
-    item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
+    list_type = get_type_on_stack(cctx, 1);
+    item_type = get_type_on_stack(cctx, 0);
     expected = list_type->tt_member;
     if (need_type(item_type, expected, -1, 0, cctx, FALSE, FALSE) == FAIL)
 	return FAIL;
@@ -1362,7 +1343,7 @@
     if (generate_instr(cctx, ISN_LISTAPPEND) == NULL)
 	return FAIL;
 
-    --stack->ga_len;	    // drop the argument
+    --cctx->ctx_type_stack.ga_len;	    // drop the argument
     return OK;
 }
 
@@ -1373,18 +1354,17 @@
     int
 generate_BLOBAPPEND(cctx_T *cctx)
 {
-    garray_T	*stack = &cctx->ctx_type_stack;
     type_T	*item_type;
 
     // Caller already checked that blob_type is a blob.
-    item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
+    item_type = get_type_on_stack(cctx, 0);
     if (need_type(item_type, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
 	return FAIL;
 
     if (generate_instr(cctx, ISN_BLOBAPPEND) == NULL)
 	return FAIL;
 
-    --stack->ga_len;	    // drop the argument
+    --cctx->ctx_type_stack.ga_len;	    // drop the argument
     return OK;
 }
 
@@ -1396,7 +1376,6 @@
 generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
     int		regular_args = ufunc->uf_args.ga_len;
     int		argcount = pushed_argcount;
 
@@ -1424,7 +1403,7 @@
 	    type_T *expected;
 	    type_T *actual;
 
-	    actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
+	    actual = get_type_on_stack(cctx, argcount - i - 1);
 	    if (actual == &t_special
 			      && i >= regular_args - ufunc->uf_def_args.ga_len)
 	    {
@@ -1479,14 +1458,11 @@
 	isn->isn_arg.ufunc.cuf_argcount = argcount;
     }
 
-    stack->ga_len -= argcount; // drop the arguments
-    if (GA_GROW_FAILS(stack, 1))
-	return FAIL;
-    // add return value
-    ((type_T **)stack->ga_data)[stack->ga_len] = ufunc->uf_ret_type;
-    ++stack->ga_len;
+    // drop the argument types
+    cctx->ctx_type_stack.ga_len -= argcount;
 
-    return OK;
+    // add return type
+    return push_type_stack(cctx, ufunc->uf_ret_type);
 }
 
 /*
@@ -1496,7 +1472,6 @@
 generate_UCALL(cctx_T *cctx, char_u *name, int argcount)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr(cctx, ISN_UCALL)) == NULL)
@@ -1504,14 +1479,11 @@
     isn->isn_arg.ufunc.cuf_name = vim_strsave(name);
     isn->isn_arg.ufunc.cuf_argcount = argcount;
 
-    stack->ga_len -= argcount; // drop the arguments
-    if (GA_GROW_FAILS(stack, 1))
-	return FAIL;
-    // add return value
-    ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
-    ++stack->ga_len;
+    // drop the argument types
+    cctx->ctx_type_stack.ga_len -= argcount;
 
-    return OK;
+    // add return value
+    return push_type_stack(cctx, &t_any);
 }
 
 /*
@@ -1527,7 +1499,6 @@
 	int	at_top)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
     type_T	*ret_type;
 
     RETURN_OK_IF_SKIP(cctx);
@@ -1557,8 +1528,7 @@
 		for (i = 0; i < argcount; ++i)
 		{
 		    int	    offset = -argcount + i - (at_top ? 0 : 1);
-		    type_T *actual = ((type_T **)stack->ga_data)[
-						       stack->ga_len + offset];
+		    type_T *actual = get_type_on_stack(cctx, -1 - offset);
 		    type_T *expected;
 
 		    if (varargs && i >= type->tt_argcount - 1)
@@ -1594,10 +1564,11 @@
     isn->isn_arg.pfunc.cpf_top = at_top;
     isn->isn_arg.pfunc.cpf_argcount = argcount;
 
-    stack->ga_len -= argcount; // drop the arguments
+    // drop the arguments and the funcref/partial
+    cctx->ctx_type_stack.ga_len -= argcount + 1;
 
-    // drop the funcref/partial, get back the return value
-    ((type_T **)stack->ga_data)[stack->ga_len - 1] = ret_type;
+    // push the return value
+    push_type_stack(cctx, ret_type);
 
     // If partial is above the arguments it must be cleared and replaced with
     // the return value.
@@ -1614,7 +1585,6 @@
 generate_STRINGMEMBER(cctx_T *cctx, char_u *name, size_t len)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
     type_T	*type;
 
     RETURN_OK_IF_SKIP(cctx);
@@ -1623,7 +1593,7 @@
     isn->isn_arg.string = vim_strnsave(name, len);
 
     // check for dict type
-    type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
+    type = get_type_on_stack(cctx, 0);
     if (type->tt_type != VAR_DICT && type != &t_any && type != &t_unknown)
     {
 	char *tofree;
@@ -1636,8 +1606,9 @@
     // change dict type to dict member type
     if (type->tt_type == VAR_DICT)
     {
-	((type_T **)stack->ga_data)[stack->ga_len - 1] =
-		      type->tt_member == &t_unknown ? &t_any : type->tt_member;
+	type_T *ntype = type->tt_member == &t_unknown
+						    ? &t_any : type->tt_member;
+	set_type_on_stack(cctx, ntype, 0);
     }
 
     return OK;
@@ -1734,19 +1705,13 @@
 generate_LEGACY_EVAL(cctx_T *cctx, char_u *line)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
 
     RETURN_OK_IF_SKIP(cctx);
     if ((isn = generate_instr(cctx, ISN_LEGACY_EVAL)) == NULL)
 	return FAIL;
     isn->isn_arg.string = vim_strsave(line);
 
-    if (GA_GROW_FAILS(stack, 1))
-	return FAIL;
-    ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
-    ++stack->ga_len;
-
-    return OK;
+    return push_type_stack(cctx, &t_any);
 }
 
     int
@@ -1767,17 +1732,12 @@
 generate_RANGE(cctx_T *cctx, char_u *range)
 {
     isn_T	*isn;
-    garray_T	*stack = &cctx->ctx_type_stack;
 
     if ((isn = generate_instr(cctx, ISN_RANGE)) == NULL)
 	return FAIL;
     isn->isn_arg.string = range;
 
-    if (GA_GROW_FAILS(stack, 1))
-	return FAIL;
-    ((type_T **)stack->ga_data)[stack->ga_len] = &t_number;
-    ++stack->ga_len;
-    return OK;
+    return push_type_stack(cctx, &t_number);
 }
 
     int