# HG changeset patch # User Bram Moolenaar # Date 1608064204 -3600 # Node ID 59f31d2eb4cf424cff1eedea0dc26bcac7d6eccc # Parent e7fe2f43809c64b54d348f8344d0f64ee23a2da7 patch 8.2.2145: Vim9: concatenating lists does not adjust type of result Commit: https://github.com/vim/vim/commit/399ea8108c8da3fcdf5d738a0f8eae67155b4b10 Author: Bram Moolenaar Date: Tue Dec 15 21:28:57 2020 +0100 patch 8.2.2145: Vim9: concatenating lists does not adjust type of result Problem: Vim9: concatenating lists does not adjust type of result. Solution: When list member types differ use "any" member type. (closes #7473) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1317,6 +1317,23 @@ func Test_expr5_fails_channel() call CheckDefFailure(["var x = 'a' .. test_null_channel()"], 'E1105:', 1) endfunc +def Test_expr5_list_add() + # concatenating two lists with same member types is OK + var d = {} + for i in ['a'] + ['b'] + d = {[i]: 0} + endfor + + # concatenating two lists with different member types results in "any" + var lines =<< trim END + var d = {} + for i in ['a'] + [0] + d = {[i]: 0} + endfor + END + CheckDefExecFailure(lines, 'E1012:') +enddef + " test multiply, divide, modulo def Test_expr6() var lines =<< trim END diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2145, +/**/ 2144, /**/ 2143, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -538,14 +538,15 @@ generate_add_instr( type_T *type1, type_T *type2) { - isn_T *isn = generate_instr_drop(cctx, - vartype == VAR_NUMBER ? ISN_OPNR - : vartype == VAR_LIST ? ISN_ADDLIST - : vartype == VAR_BLOB ? ISN_ADDBLOB + garray_T *stack = &cctx->ctx_type_stack; + isn_T *isn = generate_instr_drop(cctx, + vartype == VAR_NUMBER ? ISN_OPNR + : vartype == VAR_LIST ? ISN_ADDLIST + : vartype == VAR_BLOB ? ISN_ADDBLOB #ifdef FEAT_FLOAT - : vartype == VAR_FLOAT ? ISN_OPFLOAT + : vartype == VAR_FLOAT ? ISN_OPFLOAT #endif - : ISN_OPANY, 1); + : ISN_OPANY, 1); if (vartype != VAR_LIST && vartype != VAR_BLOB && type1->tt_type != VAR_ANY @@ -556,6 +557,14 @@ generate_add_instr( if (isn != NULL) isn->isn_arg.op.op_type = EXPR_ADD; + + // When concatenating two lists with different member types the member type + // becomes "any". + if (vartype == VAR_LIST + && type1->tt_type == VAR_LIST && type2->tt_type == VAR_LIST + && type1->tt_member != type2->tt_member) + (((type_T **)stack->ga_data)[stack->ga_len - 1]) = &t_list_any; + return isn == NULL ? FAIL : OK; } @@ -7172,6 +7181,7 @@ compile_put(char_u *arg, exarg_T *eap, c // Either no range or a number. // "errormsg" will not be set because the range is ADDR_LINES. if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL) + // cannot happen return NULL; if (eap->addr_count == 0) lnum = -1;