1
0
forked from aniani/vim

patch 8.2.4279: Vim9: cannot change item type with map() after range()

Problem:    Vim9: cannot change item type with map() after range().
Solution:   Split the return type in current type and declared type.
            (closes #9665)
This commit is contained in:
Bram Moolenaar
2022-02-01 12:11:58 +00:00
parent 4e3b318230
commit 8133018f50
7 changed files with 202 additions and 46 deletions

View File

@@ -992,127 +992,209 @@ static argcheck_T arg24_match_func[] = {arg_string_or_list_any, arg_string, arg_
* Note that "argtypes" is NULL if "argcount" is zero.
*/
static type_T *
ret_void(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_void(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_void;
}
static type_T *
ret_any(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_any(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_any;
}
static type_T *
ret_bool(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_bool(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_bool;
}
static type_T *
ret_number_bool(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_number_bool(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_number_bool;
}
static type_T *
ret_number(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_number(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_number;
}
static type_T *
ret_float(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_float(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_float;
}
static type_T *
ret_string(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_string(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_string;
}
static type_T *
ret_list_any(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_list_any(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_list_any;
}
static type_T *
ret_list_number(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_list_number(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_list_number;
}
static type_T *
ret_list_string(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_range(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type)
{
// returning a list<number>, but it's not declared as such
*decl_type = &t_list_any;
return &t_list_number;
}
static type_T *
ret_list_string(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_list_string;
}
static type_T *
ret_list_dict_any(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_list_dict_any(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_list_dict_any;
}
static type_T *
ret_list_items(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_list_items(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_list_list_any;
}
static type_T *
ret_list_string_items(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_list_string_items(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_list_list_string;
}
static type_T *
ret_dict_any(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_dict_any(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_dict_any;
}
static type_T *
ret_job_info(int argcount, type2_T *argtypes UNUSED)
ret_job_info(int argcount,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
if (argcount == 0)
return &t_list_job;
return &t_dict_any;
}
static type_T *
ret_dict_number(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_dict_number(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_dict_number;
}
static type_T *
ret_dict_string(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_dict_string(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_dict_string;
}
static type_T *
ret_blob(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_blob(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_blob;
}
static type_T *
ret_func_any(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_func_any(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_func_any;
}
static type_T *
ret_func_unknown(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_func_unknown(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_func_unknown;
}
static type_T *
ret_channel(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_channel(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_channel;
}
static type_T *
ret_job(int argcount UNUSED, type2_T *argtypes UNUSED)
ret_job(int argcount UNUSED,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return &t_job;
}
static type_T *
ret_first_arg(int argcount, type2_T *argtypes)
ret_first_arg(int argcount,
type2_T *argtypes,
type_T **decl_type)
{
if (argcount > 0)
{
*decl_type = argtypes[0].type_decl;
return argtypes[0].type_curr;
}
return &t_void;
}
static type_T *
ret_repeat(int argcount, type2_T *argtypes)
ret_extend(int argcount,
type2_T *argtypes,
type_T **decl_type)
{
if (argcount > 0)
{
*decl_type = argtypes[0].type_decl;
// if the second argument has a different current type then the current
// type is "any"
if (argcount > 1 && !equal_type(argtypes[0].type_curr,
argtypes[1].type_curr, 0))
{
if (argtypes[0].type_curr->tt_type == VAR_LIST)
return &t_list_any;
if (argtypes[0].type_curr->tt_type == VAR_DICT)
return &t_dict_any;
}
return argtypes[0].type_curr;
}
return &t_void;
}
static type_T *
ret_repeat(int argcount,
type2_T *argtypes,
type_T **decl_type UNUSED)
{
if (argcount == 0)
return &t_any;
@@ -1122,7 +1204,9 @@ ret_repeat(int argcount, type2_T *argtypes)
}
// for map(): returns first argument but item type may differ
static type_T *
ret_first_cont(int argcount, type2_T *argtypes)
ret_first_cont(int argcount,
type2_T *argtypes,
type_T **decl_type UNUSED)
{
if (argcount > 0)
{
@@ -1137,13 +1221,17 @@ ret_first_cont(int argcount, type2_T *argtypes)
}
// for getline()
static type_T *
ret_getline(int argcount, type2_T *argtypes UNUSED)
ret_getline(int argcount,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
return argcount == 1 ? &t_string : &t_list_string;
}
// for finddir()
static type_T *
ret_finddir(int argcount, type2_T *argtypes UNUSED)
ret_finddir(int argcount,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
if (argcount < 3)
return &t_string;
@@ -1156,7 +1244,9 @@ ret_finddir(int argcount, type2_T *argtypes UNUSED)
* one.
*/
static type_T *
ret_list_or_dict_0(int argcount, type2_T *argtypes UNUSED)
ret_list_or_dict_0(int argcount,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
if (argcount > 0)
return &t_dict_any;
@@ -1168,7 +1258,9 @@ ret_list_or_dict_0(int argcount, type2_T *argtypes UNUSED)
* are two.
*/
static type_T *
ret_list_or_dict_1(int argcount, type2_T *argtypes UNUSED)
ret_list_or_dict_1(int argcount,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
if (argcount > 1)
return &t_dict_any;
@@ -1176,7 +1268,9 @@ ret_list_or_dict_1(int argcount, type2_T *argtypes UNUSED)
}
static type_T *
ret_argv(int argcount, type2_T *argtypes UNUSED)
ret_argv(int argcount,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
// argv() returns list of strings
if (argcount == 0)
@@ -1187,13 +1281,20 @@ ret_argv(int argcount, type2_T *argtypes UNUSED)
}
static type_T *
ret_remove(int argcount, type2_T *argtypes)
ret_remove(int argcount,
type2_T *argtypes,
type_T **decl_type UNUSED)
{
if (argcount > 0)
{
if (argtypes[0].type_curr->tt_type == VAR_LIST
|| argtypes[0].type_curr->tt_type == VAR_DICT)
{
if (argtypes[0].type_curr->tt_type
== argtypes[0].type_decl->tt_type)
*decl_type = argtypes[0].type_decl->tt_member;
return argtypes[0].type_curr->tt_member;
}
if (argtypes[0].type_curr->tt_type == VAR_BLOB)
return &t_number;
}
@@ -1201,7 +1302,9 @@ ret_remove(int argcount, type2_T *argtypes)
}
static type_T *
ret_getreg(int argcount, type2_T *argtypes UNUSED)
ret_getreg(int argcount,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
// Assume that if the third argument is passed it's non-zero
if (argcount == 3)
@@ -1210,7 +1313,9 @@ ret_getreg(int argcount, type2_T *argtypes UNUSED)
}
static type_T *
ret_maparg(int argcount, type2_T *argtypes UNUSED)
ret_maparg(int argcount,
type2_T *argtypes UNUSED,
type_T **decl_type UNUSED)
{
// Assume that if the fourth argument is passed it's non-zero
if (argcount == 4)
@@ -1229,7 +1334,8 @@ typedef struct
char f_max_argc; // maximal number of arguments
char f_argtype; // for method: FEARG_ values
argcheck_T *f_argcheck; // list of functions to check argument types
type_T *(*f_retfunc)(int argcount, type2_T *argtypes);
type_T *(*f_retfunc)(int argcount, type2_T *argtypes,
type_T **decl_type);
// return type function
void (*f_func)(typval_T *args, typval_T *rvar);
// implementation of function
@@ -1533,7 +1639,7 @@ static funcentry_T global_functions[] =
{"expandcmd", 1, 1, FEARG_1, arg1_string,
ret_string, f_expandcmd},
{"extend", 2, 3, FEARG_1, arg23_extend,
ret_first_arg, f_extend},
ret_extend, f_extend},
{"extendnew", 2, 3, FEARG_1, arg23_extendnew,
ret_first_cont, f_extendnew},
{"feedkeys", 1, 2, FEARG_1, arg2_string,
@@ -1991,7 +2097,7 @@ static funcentry_T global_functions[] =
{"rand", 0, 1, FEARG_1, arg1_list_number,
ret_number, f_rand},
{"range", 1, 3, FEARG_1, arg3_number,
ret_list_number, f_range},
ret_range, f_range},
{"readblob", 1, 1, FEARG_1, arg1_string,
ret_blob, f_readblob},
{"readdir", 1, 3, FEARG_1, arg3_string_any_dict,
@@ -2622,14 +2728,25 @@ internal_func_get_argcount(int idx, int *argcount, int *min_argcount)
/*
* Call the "f_retfunc" function to obtain the return type of function "idx".
* "decl_type" is set to the declared type.
* "argtypes" is the list of argument types or NULL when there are no
* arguments.
* "argcount" may be less than the actual count when only getting the type.
*/
type_T *
internal_func_ret_type(int idx, int argcount, type2_T *argtypes)
internal_func_ret_type(
int idx,
int argcount,
type2_T *argtypes,
type_T **decl_type)
{
return global_functions[idx].f_retfunc(argcount, argtypes);
type_T *ret;
*decl_type = NULL;
ret = global_functions[idx].f_retfunc(argcount, argtypes, decl_type);
if (*decl_type == NULL)
*decl_type = ret;
return ret;
}
/*