mirror of
https://github.com/vim/vim.git
synced 2026-05-28 00:21:37 +02:00
patch 9.1.2077: Vim9: type issue when appending item to a list
Problem: Vim9: type issue when appending item to a list
(Peter Kenny)
Solution: When adding a new item at the end of a list in vim9script, use
the proper item type (Yegappan Lakshmanan)
fixes: #19045
closes: #19076
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
8ddbd31c18
commit
949e3be916
@@ -1,4 +1,4 @@
|
||||
*eval.txt* For Vim version 9.1. Last change: 2025 Dec 27
|
||||
*eval.txt* For Vim version 9.1. Last change: 2026 Jan 10
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -467,7 +467,13 @@ Changing the order of items in a list: >
|
||||
:call reverse(list) " reverse the order of items
|
||||
:call uniq(sort(list)) " sort and remove duplicates
|
||||
|
||||
|
||||
In a Vim9 script or a def method, a new item can be appended to a List by
|
||||
using the list length as the index: >
|
||||
vim9script
|
||||
var l: list<string>
|
||||
l[0] = 'a'
|
||||
l[1] = 'b'
|
||||
<
|
||||
For loop ~
|
||||
|
||||
The |:for| loop executes commands for each item in a List, Tuple, String or
|
||||
|
||||
+12
@@ -2470,6 +2470,18 @@ set_var_lval(
|
||||
NULL, 0) == FAIL)
|
||||
return;
|
||||
|
||||
// If the lval is a List and the type of the list is not yet set,
|
||||
// then set the item type from the declared type of the variable.
|
||||
if (in_vim9script() && rettv->v_type == VAR_LIST
|
||||
&& rettv->vval.v_list != NULL
|
||||
&& rettv->vval.v_list->lv_type == NULL)
|
||||
{
|
||||
if (lp->ll_tv->v_type == VAR_LIST
|
||||
&& lp->ll_tv->vval.v_list != NULL
|
||||
&& lp->ll_tv->vval.v_list->lv_type != NULL)
|
||||
set_tv_type(rettv, lp->ll_tv->vval.v_list->lv_type);
|
||||
}
|
||||
|
||||
if (lp->ll_newkey != NULL)
|
||||
{
|
||||
if (op != NULL && *op != '=')
|
||||
|
||||
+74
-2
@@ -764,6 +764,63 @@ list_insert(list_T *l, listitem_T *ni, listitem_T *item)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a new empty item into "l" based on the list item type. Used when
|
||||
* adding a new element to a List in Vim9script by using the current list
|
||||
* length as the index.
|
||||
*/
|
||||
static int
|
||||
list_append_new_item(list_T *l)
|
||||
{
|
||||
typval_T tv;
|
||||
|
||||
if (l->lv_type != NULL && l->lv_type->tt_member != NULL)
|
||||
tv.v_type = l->lv_type->tt_member->tt_type;
|
||||
else
|
||||
tv.v_type = VAR_NUMBER;
|
||||
tv.v_lock = 0;
|
||||
|
||||
switch (tv.v_type)
|
||||
{
|
||||
case VAR_BOOL: tv.vval.v_number = VVAL_FALSE; break;
|
||||
case VAR_SPECIAL: tv.vval.v_number = 0; break;
|
||||
case VAR_NUMBER: tv.vval.v_number = 0; break;
|
||||
case VAR_FLOAT: tv.vval.v_float = 0; break;
|
||||
case VAR_STRING: tv.vval.v_string = NULL; break;
|
||||
case VAR_BLOB: tv.vval.v_blob = blob_alloc(); break;
|
||||
case VAR_FUNC: tv.vval.v_string = NULL; break;
|
||||
case VAR_PARTIAL: tv.vval.v_partial = NULL; break;
|
||||
case VAR_LIST: tv.vval.v_list = list_alloc(); break;
|
||||
case VAR_DICT: tv.vval.v_dict = dict_alloc(); break;
|
||||
case VAR_JOB: tv.vval.v_job = NULL; break;
|
||||
case VAR_CHANNEL: tv.vval.v_channel = NULL; break;
|
||||
case VAR_CLASS:
|
||||
if (l->lv_type != NULL && l->lv_type->tt_member != NULL)
|
||||
tv.vval.v_class = l->lv_type->tt_member->tt_class;
|
||||
else
|
||||
tv.vval.v_class = NULL;
|
||||
break;
|
||||
case VAR_OBJECT:
|
||||
if (l->lv_type != NULL && l->lv_type->tt_member != NULL)
|
||||
tv.vval.v_object =
|
||||
alloc_object(l->lv_type->tt_member->tt_class);
|
||||
else
|
||||
tv.vval.v_object = NULL;
|
||||
break;
|
||||
case VAR_TYPEALIAS: tv.vval.v_typealias = NULL; break;
|
||||
case VAR_TUPLE: tv.vval.v_tuple = tuple_alloc(); break;
|
||||
default:
|
||||
tv.v_type = VAR_NUMBER;
|
||||
tv.vval.v_number = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (l->lv_type != NULL && l->lv_type->tt_member != NULL)
|
||||
set_tv_type(&tv, l->lv_type->tt_member);
|
||||
|
||||
return list_append_tv(l, &tv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the list item in "l" with index "n1". "n1" is adjusted if needed.
|
||||
* In Vim9, it is at the end of the list, add an item if "can_append" is TRUE.
|
||||
@@ -782,7 +839,8 @@ check_range_index_one(list_T *l, long *n1, int can_append, int quiet)
|
||||
if (can_append && in_vim9script()
|
||||
&& *n1 == l->lv_len && l->lv_lock == 0)
|
||||
{
|
||||
list_append_number(l, 0);
|
||||
if (list_append_new_item(l) == FAIL)
|
||||
return NULL;
|
||||
li = list_find_index(l, n1);
|
||||
}
|
||||
if (li == NULL)
|
||||
@@ -1265,7 +1323,21 @@ list_slice_or_index(
|
||||
{
|
||||
// copy the item to "var1" to avoid that freeing the list makes it
|
||||
// invalid.
|
||||
copy_tv(&list_find(list, n1)->li_tv, &var1);
|
||||
listitem_T *li = check_range_index_one(list, (long *)&n1, TRUE, TRUE);
|
||||
if (li == NULL)
|
||||
return FAIL;
|
||||
copy_tv(&li->li_tv, &var1);
|
||||
|
||||
// If "var1" is a List and the List item type is not set, then set it
|
||||
// from the declared list item type.
|
||||
if (in_vim9script() && var1.v_type == VAR_LIST
|
||||
&& var1.vval.v_list != NULL
|
||||
&& var1.vval.v_list->lv_type == NULL)
|
||||
{
|
||||
if (list->lv_type != NULL && list->lv_type->tt_member != NULL)
|
||||
set_tv_type(&var1, list->lv_type->tt_member);
|
||||
}
|
||||
|
||||
clear_tv(rettv);
|
||||
*rettv = var1;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ ufunc_T *method_lookup(class_T *cl, vartype_T v_type, char_u *name, size_t namel
|
||||
int inside_class(cctx_T *cctx_arg, class_T *cl);
|
||||
int oc_var_check_ro(class_T *cl, ocmember_T *m);
|
||||
void obj_lock_const_vars(object_T *obj);
|
||||
object_T *alloc_object(class_T *cl);
|
||||
void copy_object(typval_T *from, typval_T *to);
|
||||
void copy_class(typval_T *from, typval_T *to);
|
||||
void class_unref(class_T *cl);
|
||||
|
||||
@@ -1657,4 +1657,473 @@ def Test_id_with_dict()
|
||||
assert_equal('', id(null_channel))
|
||||
assert_equal('', id(null_job))
|
||||
enddef
|
||||
|
||||
" Test for adding an item to a List with type list<any> by using the list
|
||||
" length as the index
|
||||
def Test_list_length_as_index()
|
||||
# Append a new item to a list (vim9script)
|
||||
var lines =<< trim END
|
||||
var l = []
|
||||
l[0] = 'abc'
|
||||
assert_equal(['abc'], l)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# Type check when adding a new item
|
||||
lines =<< trim END
|
||||
var l: list<string>
|
||||
l[0] = 10
|
||||
END
|
||||
v9.CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 2)
|
||||
|
||||
# In legacy script, appending a new item to a list should fail.
|
||||
lines =<< trim END
|
||||
let l = []
|
||||
let l[0] = 'abc'
|
||||
END
|
||||
v9.CheckLegacyFailure(lines, 'E684: List index out of range: 0')
|
||||
|
||||
# Append a new item to a dict which is part of another list
|
||||
lines =<< trim END
|
||||
var inner: dict<string> = {}
|
||||
var outer: list<any> = [inner]
|
||||
|
||||
outer[0] = {a: 'xxx'}
|
||||
assert_equal([{'a': 'xxx'}], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# Append a new item to a list which is part of another tuple
|
||||
lines =<< trim END
|
||||
var inner: list<string>
|
||||
var outer: tuple<any> = (inner,)
|
||||
|
||||
outer[0][0] = 'aaa'
|
||||
assert_equal((['aaa'],), outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# Append a new item to a list which is part of another list
|
||||
lines =<< trim END
|
||||
var inner: list<dict<string>>
|
||||
var outer: list<any> = [inner]
|
||||
|
||||
outer[0][0] = {a: ''}
|
||||
assert_equal([[{'a': ''}]], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# Type check
|
||||
lines =<< trim END
|
||||
var inner: list<dict<string>>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = {a: 0z10}
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected dict<string> but got dict<blob>', 3)
|
||||
|
||||
# In legacy script, appending a new item to a list which is part of another
|
||||
# list should fail.
|
||||
lines =<< trim END
|
||||
let inner = []
|
||||
let outer = [inner]
|
||||
|
||||
let outer[0][0] = {'a': ''}
|
||||
END
|
||||
v9.CheckLegacyFailure(lines, 'E684: List index out of range: 0')
|
||||
|
||||
# appending an item to a nested list
|
||||
lines =<< trim END
|
||||
var inner: list<list<dict<string>>>
|
||||
var outer: list<any> = [inner]
|
||||
|
||||
outer[0][0] = []
|
||||
outer[0][0][0] = {a: 'abc'}
|
||||
assert_equal([[[{'a': 'abc'}]]], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<list<dict<string>>>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = []
|
||||
outer[0][0][0] = {a: 0z10}
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected dict<string> but got dict<blob>', 4)
|
||||
|
||||
# legacy script
|
||||
lines =<< trim END
|
||||
let inner = [[]]
|
||||
let outer = [inner]
|
||||
let outer[0][0][0] = {'a': 'abc'}
|
||||
END
|
||||
v9.CheckLegacyFailure(lines, 'E684: List index out of range: 0')
|
||||
|
||||
# adding a new blob to a list of blobs
|
||||
lines =<< trim END
|
||||
var inner: list<blob>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 0z10
|
||||
assert_equal([[0z10]], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<blob>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 10
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected blob but got number', 3)
|
||||
|
||||
# adding a new tuple to a list of tuples
|
||||
lines =<< trim END
|
||||
var inner: list<tuple<string>>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = ('abc',)
|
||||
assert_equal([[('abc',)]], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<tuple<string>>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = ['abc']
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected tuple<string> but got list<string>', 3)
|
||||
|
||||
# adding a new string to a list of strings
|
||||
lines =<< trim END
|
||||
var inner: list<string>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 'xx'
|
||||
assert_equal([['xx']], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<string>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 10
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 3)
|
||||
|
||||
# adding a new number to a list of numbers
|
||||
lines =<< trim END
|
||||
var inner: list<number>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 1234
|
||||
assert_equal([[1234]], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<number>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = ''
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got string', 3)
|
||||
|
||||
# adding a new float to a list of floats
|
||||
lines =<< trim END
|
||||
var inner: list<float>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 2.0
|
||||
assert_equal([[2.0]], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<float>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = ''
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected float but got string', 3)
|
||||
|
||||
# adding a new bool to a list of bools
|
||||
lines =<< trim END
|
||||
var inner: list<bool>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = true
|
||||
assert_equal([[true]], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<bool>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 'a'
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected bool but got string', 3)
|
||||
|
||||
# adding a new funcref to a list of funcrefs
|
||||
lines =<< trim END
|
||||
var inner: list<func>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = function('min')
|
||||
assert_equal([[function('min')]], outer)
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# adding a new lambda to a list of funcrefs
|
||||
lines =<< trim END
|
||||
var inner: list<func>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = () => 'x'
|
||||
assert_match("\[\[function('<lambda>\d\+')]]", string(outer))
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<func>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 'min'
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected func(...): unknown but got string', 3)
|
||||
|
||||
# adding a new job to a list of jobs
|
||||
lines =<< trim END
|
||||
var inner: list<job>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = test_null_job()
|
||||
assert_equal('[[''no process'']]', string(outer))
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<job>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = test_null_channel()
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected job but got channel', 3)
|
||||
|
||||
# adding a new channel to a list of channels
|
||||
lines =<< trim END
|
||||
var inner: list<channel>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = test_null_channel()
|
||||
assert_equal('[[''channel fail'']]', string(outer))
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# type check
|
||||
lines =<< trim END
|
||||
var inner: list<channel>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = test_null_job()
|
||||
END
|
||||
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected channel but got job', 3)
|
||||
|
||||
# adding a new object to a list of objects
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
endclass
|
||||
var inner: list<A>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = A.new()
|
||||
assert_equal('[[object of A {}]]', string(outer))
|
||||
def Fn()
|
||||
var Finner: list<A>
|
||||
var Fouter: list<any> = [Finner]
|
||||
Fouter[0][0] = A.new()
|
||||
assert_equal('[[object of A {}]]', string(Fouter))
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceSuccess(lines)
|
||||
|
||||
# type check (in a script)
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
endclass
|
||||
class B
|
||||
endclass
|
||||
var inner: list<A>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = B.new()
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got object<B>', 8)
|
||||
|
||||
# type check (in a method)
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
endclass
|
||||
class B
|
||||
endclass
|
||||
def Fn()
|
||||
var inner: list<A>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = B.new()
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected object<A> but got object<B>', 3)
|
||||
|
||||
# adding a new enum to a list of enums
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
enum Color
|
||||
RED,
|
||||
BLUE,
|
||||
GREEN
|
||||
endenum
|
||||
var inner: list<Color>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = Color.BLUE
|
||||
assert_equal("[[enum Color.BLUE {name: 'BLUE', ordinal: 1}]]", string(outer))
|
||||
def Fn()
|
||||
var Finner: list<Color>
|
||||
var Fouter: list<any> = [Finner]
|
||||
Fouter[0][0] = Color.GREEN
|
||||
assert_equal("[[enum Color.GREEN {name: 'GREEN', ordinal: 2}]]", string(Fouter))
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceSuccess(lines)
|
||||
|
||||
# type check (in a script)
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
enum Color
|
||||
RED,
|
||||
BLUE,
|
||||
GREEN
|
||||
endenum
|
||||
enum Shape
|
||||
CIRCLE,
|
||||
SQUARE
|
||||
endenum
|
||||
var inner: list<Color>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = Shape.CIRCLE
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Color> but got enum<Shape>', 13)
|
||||
|
||||
# type check (in a method)
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
enum Color
|
||||
RED,
|
||||
BLUE,
|
||||
GREEN
|
||||
endenum
|
||||
enum Shape
|
||||
CIRCLE,
|
||||
SQUARE
|
||||
endenum
|
||||
def Fn()
|
||||
var inner: list<Color>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = Shape.CIRCLE
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Color> but got enum<Shape>', 3)
|
||||
|
||||
# adding a new string to a list of strings (using type alias)
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type StrType = string
|
||||
var inner: list<StrType>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 'abc'
|
||||
assert_equal([['abc']], outer)
|
||||
|
||||
def Fn()
|
||||
var Finner: list<StrType>
|
||||
var Fouter: list<any> = [Finner]
|
||||
Fouter[0][0] = 'abc'
|
||||
assert_equal([['abc']], Fouter)
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptSuccess(lines)
|
||||
|
||||
# type check (using type alias in a script)
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type StrType = string
|
||||
var inner: list<StrType>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 10
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5)
|
||||
|
||||
# type check (using type alias in a method)
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
type StrType = string
|
||||
def Fn()
|
||||
var inner: list<StrType>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = 10
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 3)
|
||||
|
||||
# append to a List object variable which is part of another list
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
var l: list<string>
|
||||
endclass
|
||||
|
||||
var inner: list<A>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = A.new()
|
||||
outer[0][0].l[0] = 'abc'
|
||||
assert_equal("[[object of A {l: ['abc']}]]", string(outer))
|
||||
|
||||
def Fn()
|
||||
var Finner: list<A>
|
||||
var Fouter: list<any> = [Finner]
|
||||
Fouter[0][0] = A.new()
|
||||
Fouter[0][0].l[0] = 'abc'
|
||||
assert_equal("[[object of A {l: ['abc']}]]", string(Fouter))
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptSuccess(lines)
|
||||
|
||||
# type check (in a script)
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
var l: list<string>
|
||||
endclass
|
||||
var inner: list<A>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = A.new()
|
||||
outer[0][0].l[0] = 0z10
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1012: Type mismatch; expected string but got blob', 8)
|
||||
|
||||
# type check (in a method)
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
class A
|
||||
var l: list<string>
|
||||
endclass
|
||||
def Fn()
|
||||
var inner: list<A>
|
||||
var outer: list<any> = [inner]
|
||||
outer[0][0] = A.new()
|
||||
outer[0][0].l[0] = 0z10
|
||||
enddef
|
||||
Fn()
|
||||
END
|
||||
v9.CheckSourceScriptFailure(lines, 'E1012: Type mismatch; expected string but got blob', 4)
|
||||
enddef
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2077,
|
||||
/**/
|
||||
2076,
|
||||
/**/
|
||||
|
||||
@@ -1895,6 +1895,13 @@ enum_set_internal_obj_vars(class_T *en, object_T *enval)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= en->class_class_member_count)
|
||||
// When adding enum values to an enum, the index value should be less
|
||||
// than the member count. It will be greater only when appending a
|
||||
// new item to a list of enums. In this case, skip setting the enum
|
||||
// name and ordinal (as this is a dummy enum object)
|
||||
return;
|
||||
|
||||
// First object variable is the name
|
||||
ocmember_T *value_ocm = en->class_class_members + i;
|
||||
typval_T *name_tv = (typval_T *)(enval + 1);
|
||||
@@ -3633,6 +3640,36 @@ obj_lock_const_vars(object_T *obj)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new instance of class "cl"
|
||||
*/
|
||||
object_T *
|
||||
alloc_object(class_T *cl)
|
||||
{
|
||||
object_T *obj;
|
||||
int sz;
|
||||
|
||||
if (cl == NULL)
|
||||
return NULL;
|
||||
|
||||
sz = sizeof(object_T) + cl->class_obj_member_count * sizeof(typval_T);
|
||||
obj = alloc_clear(sz);
|
||||
if (obj == NULL)
|
||||
return NULL;
|
||||
|
||||
obj->obj_class = cl;
|
||||
++cl->class_refcount;
|
||||
obj->obj_refcount = 1;
|
||||
object_created(obj);
|
||||
|
||||
// When creating an enum value object, initialize the name and ordinal
|
||||
// object variables.
|
||||
if (IS_ENUM(cl))
|
||||
enum_set_internal_obj_vars(cl, obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a copy of an object.
|
||||
*/
|
||||
|
||||
+2
-13
@@ -3708,19 +3708,8 @@ exec_instructions(ectx_T *ectx)
|
||||
// "this" is always the local variable at index zero
|
||||
tv = STACK_TV_VAR(0);
|
||||
tv->v_type = VAR_OBJECT;
|
||||
tv->vval.v_object = alloc_clear(
|
||||
iptr->isn_arg.construct.construct_size);
|
||||
tv->vval.v_object->obj_class =
|
||||
iptr->isn_arg.construct.construct_class;
|
||||
++tv->vval.v_object->obj_class->class_refcount;
|
||||
tv->vval.v_object->obj_refcount = 1;
|
||||
object_created(tv->vval.v_object);
|
||||
|
||||
// When creating an enum value object, initialize the name and
|
||||
// ordinal object variables.
|
||||
class_T *en = tv->vval.v_object->obj_class;
|
||||
if (IS_ENUM(en))
|
||||
enum_set_internal_obj_vars(en, tv->vval.v_object);
|
||||
tv->vval.v_object =
|
||||
alloc_object(iptr->isn_arg.construct.construct_class);
|
||||
break;
|
||||
|
||||
// execute Ex command line
|
||||
|
||||
Reference in New Issue
Block a user