Skip to content

Commit e65081d

Browse files
committed
patch 8.2.3064: Vim9: in script cannot set item in uninitialized list
Problem: Vim9: in script cannot set item in uninitialized list. Solution: When a list is NULL allocate an empty one. (closes #8461)
1 parent 65aee0b commit e65081d

3 files changed

Lines changed: 51 additions & 23 deletions

File tree

src/eval.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -932,15 +932,22 @@ get_lval(
932932
semsg(_(e_dot_can_only_be_used_on_dictionary_str), name);
933933
return NULL;
934934
}
935-
if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
936-
&& !(lp->ll_tv->v_type == VAR_DICT)
937-
&& !(lp->ll_tv->v_type == VAR_BLOB
938-
&& lp->ll_tv->vval.v_blob != NULL))
935+
if (lp->ll_tv->v_type != VAR_LIST
936+
&& lp->ll_tv->v_type != VAR_DICT
937+
&& lp->ll_tv->v_type != VAR_BLOB)
939938
{
940939
if (!quiet)
941940
emsg(_("E689: Can only index a List, Dictionary or Blob"));
942941
return NULL;
943942
}
943+
944+
// a NULL list/blob works like an empty list/blob, allocate one now.
945+
if (lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list == NULL)
946+
rettv_list_alloc(lp->ll_tv);
947+
else if (lp->ll_tv->v_type == VAR_BLOB
948+
&& lp->ll_tv->vval.v_blob == NULL)
949+
rettv_blob_alloc(lp->ll_tv);
950+
944951
if (lp->ll_range)
945952
{
946953
if (!quiet)
@@ -1201,10 +1208,20 @@ get_lval(
12011208
lp->ll_li = list_find_index(lp->ll_list, &lp->ll_n1);
12021209
if (lp->ll_li == NULL)
12031210
{
1204-
clear_tv(&var2);
1205-
if (!quiet)
1206-
semsg(_(e_listidx), lp->ll_n1);
1207-
return NULL;
1211+
// Vim9: Allow for adding an item at the end.
1212+
if (in_vim9script() && lp->ll_n1 == lp->ll_list->lv_len
1213+
&& lp->ll_list->lv_lock == 0)
1214+
{
1215+
list_append_number(lp->ll_list, 0);
1216+
lp->ll_li = list_find_index(lp->ll_list, &lp->ll_n1);
1217+
}
1218+
if (lp->ll_li == NULL)
1219+
{
1220+
clear_tv(&var2);
1221+
if (!quiet)
1222+
semsg(_(e_listidx), lp->ll_n1);
1223+
return NULL;
1224+
}
12081225
}
12091226

12101227
if (lp->ll_valtype != NULL)

src/testdir/test_vim9_assign.vim

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,21 +1102,30 @@ def Test_assignment_failure()
11021102
enddef
11031103

11041104
def Test_assign_list()
1105-
var l: list<string> = []
1106-
l[0] = 'value'
1107-
assert_equal('value', l[0])
1108-
1109-
l[1] = 'asdf'
1110-
assert_equal('value', l[0])
1111-
assert_equal('asdf', l[1])
1112-
assert_equal('asdf', l[-1])
1113-
assert_equal('value', l[-2])
1114-
1115-
var nrl: list<number> = []
1116-
for i in range(5)
1117-
nrl[i] = i
1118-
endfor
1119-
assert_equal([0, 1, 2, 3, 4], nrl)
1105+
var lines =<< trim END
1106+
var l: list<string> = []
1107+
l[0] = 'value'
1108+
assert_equal('value', l[0])
1109+
1110+
l[1] = 'asdf'
1111+
assert_equal('value', l[0])
1112+
assert_equal('asdf', l[1])
1113+
assert_equal('asdf', l[-1])
1114+
assert_equal('value', l[-2])
1115+
1116+
var nrl: list<number> = []
1117+
for i in range(5)
1118+
nrl[i] = i
1119+
endfor
1120+
assert_equal([0, 1, 2, 3, 4], nrl)
1121+
1122+
var ul: list<any>
1123+
ul[0] = 1
1124+
ul[1] = 2
1125+
ul[2] = 3
1126+
assert_equal([1, 2, 3], ul)
1127+
END
1128+
CheckDefAndScriptSuccess(lines)
11201129

11211130
CheckDefFailure(["var l: list<number> = ['', true]"], 'E1012: Type mismatch; expected list<number> but got list<any>', 1)
11221131
CheckDefFailure(["var l: list<list<number>> = [['', true]]"], 'E1012: Type mismatch; expected list<list<number>> but got list<list<any>>', 1)

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ static char *(features[]) =
755755

756756
static int included_patches[] =
757757
{ /* Add new patch number below this line */
758+
/**/
759+
3064,
758760
/**/
759761
3063,
760762
/**/

0 commit comments

Comments
 (0)