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
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()
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 49,
/**/
48,
/**/
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);
}
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;
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;
}
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);
}