]> granicus.if.org Git - vim/commitdiff
patch 8.2.2145: Vim9: concatenating lists does not adjust type of result v8.2.2145
authorBram Moolenaar <Bram@vim.org>
Tue, 15 Dec 2020 20:28:57 +0000 (21:28 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 15 Dec 2020 20:28:57 +0000 (21:28 +0100)
Problem:    Vim9: concatenating lists does not adjust type of result.
Solution:   When list member types differ use "any" member type.
            (closes #7473)

src/testdir/test_vim9_expr.vim
src/version.c
src/vim9compile.c

index 812aabf99ac137691c3be40046a82c5b2ebf9aba..9147536a66f5524398879a67ab53e7b7f09da734 100644 (file)
@@ -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
index dfd565126dc30aadb305e11d13f29cdce56a8208..aeac2652e728081580c560df58ccffb475c245d5 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2145,
 /**/
     2144,
 /**/
index 86d3260d96f8f1ad6c2f0a7796be70326ed06f68..2db226c8d73b5be2407ef9e343fe9d817dbcf0ee 100644 (file)
@@ -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, cctx_T *cctx)
        // 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;