Mercurial > vim
changeset 35518:0e8dbbe586c3 v9.1.0520
patch 9.1.0520: Vim9: incorrect type checking for modifying lists
Commit: https://github.com/vim/vim/commit/f4af331d084b4f2c63710179a2f1fa360cc7d74b
Author: LemonBoy <thatlemon@gmail.com>
Date: Thu Jul 4 13:43:12 2024 +0200
patch 9.1.0520: Vim9: incorrect type checking for modifying lists
Problem: Vim9: incorrect type checking for modifying lists
Solution: Correctly assign the member declared types and generate
typechecks, add disassembly test (LemonBoy)
fixes: #15090
closes: #15094
Signed-off-by: LemonBoy <thatlemon@gmail.com>
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 04 Jul 2024 14:00:03 +0200 |
parents | eb26acdda828 |
children | 76685f11f9a1 |
files | src/testdir/test_vim9_class.vim src/testdir/test_vim9_disassemble.vim src/version.c src/vim9class.c src/vim9compile.c |
diffstat | 5 files changed, 68 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -10776,4 +10776,37 @@ def Test_class_object_index() v9.CheckScriptFailure(lines, 'E689: Index not allowed after a object: a[10] = 1', 5) enddef +def Test_class_member_init_typecheck() + # Ensure the class member is assigned its declared type. + var lines =<< trim END + vim9script + class S + static var l: list<string> = [] + endclass + S.l->add(123) + END + v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 5) + + # Ensure the initializer value and the declared type match. + lines =<< trim END + vim9script + class S + var l: list<string> = [1, 2, 3] + endclass + var o = S.new() + END + v9.CheckScriptFailure(lines, 'E1382: Variable "l": type mismatch, expected list<string> but got list<number>') + + # Ensure the class member is assigned its declared type. + lines =<< trim END + vim9script + class S + var l: list<string> = [] + endclass + var o = S.new() + o.l->add(123) + END + v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 6) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
--- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -3496,4 +3496,26 @@ def Test_disassemble_compound_op_in_clos unlet g:instr enddef +def Test_disassemble_member_initializer() + var lines =<< trim END + vim9script + class A + var l: list<string> = [] + var d: dict<string> = {} + endclass + g:instr = execute('disassemble A.new') + END + v9.CheckScriptSuccess(lines) + # Ensure SETTYPE is emitted and that matches the declared type. + assert_match('new\_s*' .. + '0 NEW A size \d\+\_s*' .. + '1 NEWLIST size 0\_s*' .. + '2 SETTYPE list<string>\_s*' .. + '3 STORE_THIS 0\_s*' .. + '4 NEWDICT size 0\_s*' .. + '5 SETTYPE dict<string>\_s*' .. + '6 STORE_THIS 1', g:instr) + unlet g:instr +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
--- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 520, +/**/ 519, /**/ 518,
--- a/src/vim9class.c +++ b/src/vim9class.c @@ -1280,6 +1280,7 @@ add_class_members(class_T *cl, exarg_T * tv->v_type = m->ocm_type->tt_type; tv->vval.v_string = NULL; } + set_tv_type(tv, m->ocm_type); if (m->ocm_flags & OCMFLAG_CONST) item_lock(tv, DICT_MAXNEST, TRUE, TRUE); }
--- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3315,7 +3315,7 @@ obj_constructor_prologue(ufunc_T *ufunc, // the initialization expression type. m->ocm_type = type; } - else if (m->ocm_type->tt_type != type->tt_type) + else { // The type of the member initialization expression is // determined at run time. Add a runtime type check. @@ -3330,6 +3330,15 @@ obj_constructor_prologue(ufunc_T *ufunc, else push_default_value(cctx, m->ocm_type->tt_type, FALSE, NULL); + if ((m->ocm_type->tt_type == VAR_DICT + || m->ocm_type->tt_type == VAR_LIST) + && m->ocm_type->tt_member != NULL + && m->ocm_type->tt_member != &t_any + && m->ocm_type->tt_member != &t_unknown) + // Set the type in the list or dict, so that it can be checked, + // also in legacy script. + generate_SETTYPE(cctx, m->ocm_type); + generate_STORE_THIS(cctx, i); }