Patch 8.2.2621
Problem: typval2type() cannot handle recursive structures.
Solution: Use copyID. (closes #7979)
Files: src/list.c, src/vim9script.c, src/vim9type.c,
src/proto/vim9type.pro, src/testdir/test_vimscript.vim
*** ../vim-8.2.2620/src/list.c 2021-02-21 16:20:14.248629232 +0100
--- src/list.c 2021-03-18 22:02:23.538286414 +0100
***************
*** 2052,2058 ****
{
// Check that map() does not change the type of the dict.
ga_init2(&type_list, sizeof(type_T *), 10);
! type = typval2type(argvars, &type_list);
}
if (argvars[0].v_type == VAR_BLOB)
--- 2052,2058 ----
{
// Check that map() does not change the type of the dict.
ga_init2(&type_list, sizeof(type_T *), 10);
! type = typval2type(argvars, get_copyID(), &type_list);
}
if (argvars[0].v_type == VAR_BLOB)
***************
*** 2558,2564 ****
{
// Check that map() does not change the type of the dict.
ga_init2(&type_list, sizeof(type_T *), 10);
! type = typval2type(argvars, &type_list);
}
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
--- 2558,2564 ----
{
// Check that map() does not change the type of the dict.
ga_init2(&type_list, sizeof(type_T *), 10);
! type = typval2type(argvars, get_copyID(), &type_list);
}
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
*** ../vim-8.2.2620/src/vim9script.c 2021-03-18 21:37:52.192105213 +0100
--- src/vim9script.c 2021-03-18 22:02:38.082269393 +0100
***************
*** 750,756 ****
if (sv != NULL)
{
if (*type == NULL)
! *type = typval2type(tv, &si->sn_type_list);
sv->sv_type = *type;
}
--- 750,756 ----
if (sv != NULL)
{
if (*type == NULL)
! *type = typval2type(tv, get_copyID(), &si->sn_type_list);
sv->sv_type = *type;
}
*** ../vim-8.2.2620/src/vim9type.c 2021-03-13 21:24:53.040409187 +0100
--- src/vim9type.c 2021-03-18 22:13:31.913347899 +0100
***************
*** 254,260 ****
* "type_gap" is used to temporarily create types in.
*/
static type_T *
! typval2type_int(typval_T *tv, garray_T *type_gap)
{
type_T *type;
type_T *member_type = &t_any;
--- 254,260 ----
* "type_gap" is used to temporarily create types in.
*/
static type_T *
! typval2type_int(typval_T *tv, int copyID, garray_T *type_gap)
{
type_T *type;
type_T *member_type = &t_any;
***************
*** 276,286 ****
return &t_list_empty;
if (l->lv_first == &range_list_item)
return &t_list_number;
// Use the common type of all members.
! member_type = typval2type(&l->lv_first->li_tv, type_gap);
for (li = l->lv_first->li_next; li != NULL; li = li->li_next)
! common_type(typval2type(&li->li_tv, type_gap),
member_type, &member_type, type_gap);
return get_list_type(member_type, type_gap);
}
--- 276,290 ----
return &t_list_empty;
if (l->lv_first == &range_list_item)
return &t_list_number;
+ if (l->lv_copyID == copyID)
+ // avoid recursion
+ return &t_list_any;
+ l->lv_copyID = copyID;
// Use the common type of all members.
! member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap);
for (li = l->lv_first->li_next; li != NULL; li = li->li_next)
! common_type(typval2type(&li->li_tv, copyID, type_gap),
member_type, &member_type, type_gap);
return get_list_type(member_type, type_gap);
}
***************
*** 289,305 ****
{
dict_iterator_T iter;
typval_T *value;
! if (tv->vval.v_dict == NULL
! || tv->vval.v_dict->dv_hashtab.ht_used == 0)
return &t_dict_empty;
// Use the common type of all values.
dict_iterate_start(tv, &iter);
dict_iterate_next(&iter, &value);
! member_type = typval2type(value, type_gap);
while (dict_iterate_next(&iter, &value) != NULL)
! common_type(typval2type(value, type_gap),
member_type, &member_type, type_gap);
return get_dict_type(member_type, type_gap);
}
--- 293,313 ----
{
dict_iterator_T iter;
typval_T *value;
+ dict_T *d = tv->vval.v_dict;
! if (d == NULL || d->dv_hashtab.ht_used == 0)
return &t_dict_empty;
+ if (d->dv_copyID == copyID)
+ // avoid recursion
+ return &t_dict_any;
+ d->dv_copyID = copyID;
// Use the common type of all values.
dict_iterate_start(tv, &iter);
dict_iterate_next(&iter, &value);
! member_type = typval2type(value, copyID, type_gap);
while (dict_iterate_next(&iter, &value) != NULL)
! common_type(typval2type(value, copyID, type_gap),
member_type, &member_type, type_gap);
return get_dict_type(member_type, type_gap);
}
***************
*** 372,380 ****
* "type_list" is used to temporarily create types in.
*/
type_T *
! typval2type(typval_T *tv, garray_T *type_gap)
{
! type_T *type = typval2type_int(tv, type_gap);
if (type != NULL && type != &t_bool
&& (tv->v_type == VAR_NUMBER
--- 380,388 ----
* "type_list" is used to temporarily create types in.
*/
type_T *
! typval2type(typval_T *tv, int copyID, garray_T *type_gap)
{
! type_T *type = typval2type_int(tv, copyID, type_gap);
if (type != NULL && type != &t_bool
&& (tv->v_type == VAR_NUMBER
***************
*** 396,402 ****
return &t_list_string;
if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
return &t_dict_any;
! return typval2type(tv, type_gap);
}
int
--- 404,410 ----
return &t_list_string;
if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
return &t_dict_any;
! return typval2type(tv, get_copyID(), type_gap);
}
int
***************
*** 421,427 ****
int res = FAIL;
ga_init2(&type_list, sizeof(type_T *), 10);
! actual_type = typval2type(actual_tv, &type_list);
if (actual_type != NULL)
res = check_type(expected, actual_type, TRUE, where);
clear_type_list(&type_list);
--- 429,435 ----
int res = FAIL;
ga_init2(&type_list, sizeof(type_T *), 10);
! actual_type = typval2type(actual_tv, get_copyID(), &type_list);
if (actual_type != NULL)
res = check_type(expected, actual_type, TRUE, where);
clear_type_list(&type_list);
***************
*** 1202,1208 ****
rettv->v_type = VAR_STRING;
ga_init2(&type_list, sizeof(type_T *), 10);
! type = typval2type(argvars, &type_list);
name = type_name(type, &tofree);
if (tofree != NULL)
rettv->vval.v_string = (char_u *)tofree;
--- 1210,1216 ----
rettv->v_type = VAR_STRING;
ga_init2(&type_list, sizeof(type_T *), 10);
! type = typval2type(argvars, get_copyID(), &type_list);
name = type_name(type, &tofree);
if (tofree != NULL)
rettv->vval.v_string = (char_u *)tofree;
*** ../vim-8.2.2620/src/proto/vim9type.pro 2021-02-11 21:19:30.518147953
+0100
--- src/proto/vim9type.pro 2021-03-18 22:08:09.721832238 +0100
***************
*** 9,15 ****
type_T *get_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
int func_type_add_arg_types(type_T *functype, int argcount, garray_T
*type_gap);
int need_convert_to_bool(type_T *type, typval_T *tv);
! type_T *typval2type(typval_T *tv, garray_T *type_gap);
type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
int check_typval_arg_type(type_T *expected, typval_T *actual_tv, int arg_idx);
int check_typval_type(type_T *expected, typval_T *actual_tv, where_T where);
--- 9,15 ----
type_T *get_func_type(type_T *ret_type, int argcount, garray_T *type_gap);
int func_type_add_arg_types(type_T *functype, int argcount, garray_T
*type_gap);
int need_convert_to_bool(type_T *type, typval_T *tv);
! type_T *typval2type(typval_T *tv, int copyID, garray_T *type_gap);
type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
int check_typval_arg_type(type_T *expected, typval_T *actual_tv, int arg_idx);
int check_typval_type(type_T *expected, typval_T *actual_tv, where_T where);
*** ../vim-8.2.2620/src/testdir/test_vimscript.vim 2021-01-12
21:48:55.879131998 +0100
--- src/testdir/test_vimscript.vim 2021-03-18 22:12:11.917471779 +0100
***************
*** 6606,6611 ****
--- 6606,6618 ----
call assert_equal('list<number>', typename([123]))
call assert_equal('dict<number>', typename(#{key: 123}))
call assert_equal('list<dict<number>>', typename([#{key: 123}]))
+
+ let l = []
+ let d = #{a: 0}
+ let l = [d]
+ let l[0].e = #{b: l}
+ call assert_equal('list<dict<any>>', typename(l))
+ call assert_equal('dict<any>', typename(d))
endfunc
"-------------------------------------------------------------------------------
*** ../vim-8.2.2620/src/version.c 2021-03-18 21:37:52.196105245 +0100
--- src/version.c 2021-03-18 22:14:11.877285250 +0100
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2621,
/**/
--
If someone questions your market projections, simply point out that your
target market is "People who are nuts" and "People who will buy any damn
thing". Nobody is going to tell you there aren't enough of those people
to go around.
(Scott Adams - The Dilbert principle)
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202103182115.12ILFRTY1357164%40masaka.moolenaar.net.