changeset 23199:59f31d2eb4cf v8.2.2145

patch 8.2.2145: Vim9: concatenating lists does not adjust type of result Commit: https://github.com/vim/vim/commit/399ea8108c8da3fcdf5d738a0f8eae67155b4b10 Author: Bram Moolenaar <Bram@vim.org> 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)
author Bram Moolenaar <Bram@vim.org>
date Tue, 15 Dec 2020 21:30:04 +0100
parents e7fe2f43809c
children f26564daf7a8
files src/testdir/test_vim9_expr.vim src/version.c src/vim9compile.c
diffstat 3 files changed, 35 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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,
--- 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;