mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
patch 9.2.0049: Vim9: typename() wrong for lists/dicts/tuples with shared references
Problem: Vim9: typename() returns wrong type for lists/dicts/tuples
with shared references (Mao-Yining).
Solution: Reset CopyID after processing the item so it can be
re-inspected if encountered again via a different reference
(Hirohito Higashi).
fixes: #19490
closes: #19492
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
71cc1b12cd
commit
b1d4b03058
@@ -2238,6 +2238,14 @@ func Test_tuple_typename()
|
||||
END
|
||||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||||
|
||||
" Shared (non-circular) references must not be treated as circular.
|
||||
" repeat() makes all elements point to the same inner tuple object.
|
||||
let lines =<< trim END
|
||||
call assert_equal('tuple<tuple<number, number>, tuple<number, number>, tuple<number, number>>', ((1, 2),)->repeat(3)->typename())
|
||||
call assert_equal('list<tuple<number, number>>', [(1, 2)]->repeat(3)->typename())
|
||||
END
|
||||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||||
|
||||
" When a tuple item is used in a "for" loop, the type is tuple<any>
|
||||
let lines =<< trim END
|
||||
vim9script
|
||||
|
||||
@@ -4983,6 +4983,22 @@ def Test_typename()
|
||||
endif
|
||||
var l: list<func(list<number>): any> = [function('min')]
|
||||
assert_equal('list<func(list<number>): any>', typename(l))
|
||||
|
||||
# Check that circular list/dict references don't cause infinite recursion.
|
||||
# Use legacy script where lv_type is not set so the copyID mechanism is used.
|
||||
v9.CheckSourceLegacySuccess([
|
||||
'let circ_l = []',
|
||||
'call add(circ_l, circ_l)',
|
||||
"call assert_equal('list<list<any>>', typename(circ_l))",
|
||||
'let circ_d = {}',
|
||||
"let circ_d['self'] = circ_d",
|
||||
"call assert_equal('dict<dict<any>>', typename(circ_d))",
|
||||
])
|
||||
|
||||
# Shared (non-circular) references must not be treated as circular.
|
||||
# repeat() makes all elements point to the same inner list/dict object.
|
||||
assert_equal('list<list<string>>', [[" "]]->repeat(3)->typename())
|
||||
assert_equal('list<dict<number>>', [{'a': 1}]->repeat(3)->typename())
|
||||
enddef
|
||||
|
||||
def Test_undofile()
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
49,
|
||||
/**/
|
||||
48,
|
||||
/**/
|
||||
|
||||
@@ -612,6 +612,10 @@ list_typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags)
|
||||
common_type(typval2type(&li->li_tv, copyID, type_gap, TVTT_DO_MEMBER),
|
||||
member_type, &member_type, type_gap);
|
||||
|
||||
// Reset copyID so that a shared reference to this list (not a circular
|
||||
// reference) can be processed again to get the correct type.
|
||||
l->lv_copyID = 0;
|
||||
|
||||
return get_list_type(member_type, type_gap);
|
||||
}
|
||||
|
||||
@@ -661,6 +665,9 @@ tuple_typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags)
|
||||
if (ga_grow(&tuple_types_ga, 1) == FAIL)
|
||||
{
|
||||
ga_clear(&tuple_types_ga);
|
||||
// Reset copyID so that a shared reference to this tuple can be
|
||||
// processed again.
|
||||
tuple->tv_copyID = 0;
|
||||
return NULL;
|
||||
}
|
||||
((type_T **)tuple_types_ga.ga_data)[tuple_types_ga.ga_len] = type;
|
||||
@@ -670,6 +677,10 @@ tuple_typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags)
|
||||
type_T *tuple_type = get_tuple_type(&tuple_types_ga, type_gap);
|
||||
ga_clear(&tuple_types_ga);
|
||||
|
||||
// Reset copyID so that a shared reference to this tuple (not a circular
|
||||
// reference) can be processed again to get the correct type.
|
||||
tuple->tv_copyID = 0;
|
||||
|
||||
return tuple_type;
|
||||
}
|
||||
|
||||
@@ -716,6 +727,10 @@ dict_typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags)
|
||||
common_type(typval2type(value, copyID, type_gap, TVTT_DO_MEMBER),
|
||||
member_type, &member_type, type_gap);
|
||||
|
||||
// Reset copyID so that a shared reference to this dict (not a circular
|
||||
// reference) can be processed again to get the correct type.
|
||||
d->dv_copyID = 0;
|
||||
|
||||
return get_dict_type(member_type, type_gap);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user