0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

patch 8.2.4286: Vim9: strict type checking after copy() and deepcopy()

Problem:    Vim9: strict type checking after copy() and deepcopy().
Solution:   Allow type to change after making a copy. (closes #9644)
This commit is contained in:
Bram Moolenaar
2022-02-02 20:01:27 +00:00
parent a1c5195180
commit 381692b6f1
14 changed files with 154 additions and 57 deletions

View File

@@ -102,6 +102,71 @@ free_type(type_T *type)
vim_free(type);
}
/*
* Return TRUE if "type" is to be recursed into for setting the type.
*/
static int
set_tv_type_recurse(type_T *type)
{
return type->tt_member != NULL
&& (type->tt_member->tt_type == VAR_DICT
|| type->tt_member->tt_type == VAR_LIST)
&& type->tt_member->tt_member != NULL
&& type->tt_member->tt_member != &t_any
&& type->tt_member->tt_member != &t_unknown;
}
/*
* Set the type of "tv" to "type" if it is a list or dict.
*/
void
set_tv_type(typval_T *tv, type_T *type)
{
if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL)
{
dict_T *d = tv->vval.v_dict;
if (d->dv_type != type)
{
free_type(d->dv_type);
d->dv_type = alloc_type(type);
if (set_tv_type_recurse(type))
{
int todo = (int)d->dv_hashtab.ht_used;
hashitem_T *hi;
dictitem_T *di;
for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
{
if (!HASHITEM_EMPTY(hi))
{
--todo;
di = HI2DI(hi);
set_tv_type(&di->di_tv, type->tt_member);
}
}
}
}
}
else if (tv->v_type == VAR_LIST && tv->vval.v_list != NULL)
{
list_T *l = tv->vval.v_list;
if (l->lv_type != type)
{
free_type(l->lv_type);
l->lv_type = alloc_type(type);
if (l->lv_first != &range_list_item && set_tv_type_recurse(type))
{
listitem_T *li;
FOR_ALL_LIST_ITEMS(l, li)
set_tv_type(&li->li_tv, type->tt_member);
}
}
}
}
type_T *
get_list_type(type_T *member_type, garray_T *type_gap)
{