Patch 9.0.0629
Problem: Get an error for using const only when executing.
Solution: Check for const at compile time for filter(), map(), remove(),
reverse(), sort() and uniq().
Files: src/evalfunc.c, src/testdir/test_vim9_builtin.vim
*** ../vim-9.0.0628/src/evalfunc.c 2022-09-29 19:14:37.675876694 +0100
--- src/evalfunc.c 2022-09-30 17:45:51.081009611 +0100
***************
*** 214,227 ****
type_T *actual,
argcontext_T *context)
{
- // TODO: would be useful to know if "actual" is a constant and pass it to
- // need_type() to get a compile time error if possible.
return need_type(actual, expected,
context->arg_idx - context->arg_count, context->arg_idx + 1,
context->arg_cctx, FALSE, FALSE);
}
/*
* Give an error if "type" is a constant.
*/
int
--- 214,241 ----
type_T *actual,
argcontext_T *context)
{
return need_type(actual, expected,
context->arg_idx - context->arg_count, context->arg_idx + 1,
context->arg_cctx, FALSE, FALSE);
}
/*
+ * Call need_type() to check an argument type and that it is modifiable
+ */
+ static int
+ check_arg_type_mod(
+ type_T *expected,
+ type_T *actual,
+ argcontext_T *context)
+ {
+ if (need_type(actual, expected,
+ context->arg_idx - context->arg_count, context->arg_idx + 1,
+ context->arg_cctx, FALSE, FALSE) == FAIL)
+ return FAIL;
+ return arg_type_modifiable(actual, context->arg_idx + 1);
+ }
+
+ /*
* Give an error if "type" is a constant.
*/
int
***************
*** 280,285 ****
--- 294,311 ----
}
/*
+ * Check "type" is a list of 'any' and modifiable
+ */
+ static int
+ arg_list_any_mod(
+ type_T *type,
+ type_T *decl_type UNUSED,
+ argcontext_T *context)
+ {
+ return check_arg_type_mod(&t_list_any, type, context);
+ }
+
+ /*
* Check "type" is a list of numbers.
*/
static int
***************
*** 513,528 ****
/*
* Check "type" is a list of 'any' or a dict of 'any' or a blob.
*/
static int
! arg_list_or_dict_or_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T
*context)
{
if (type->tt_type == VAR_ANY
|| type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_LIST
|| type->tt_type == VAR_DICT
|| type->tt_type == VAR_BLOB)
! return OK;
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
}
--- 539,558 ----
/*
* Check "type" is a list of 'any' or a dict of 'any' or a blob.
+ * Also check if "type" is modifiable.
*/
static int
! arg_list_or_dict_or_blob_mod(
! type_T *type,
! type_T *decl_type UNUSED,
! argcontext_T *context)
{
if (type->tt_type == VAR_ANY
|| type->tt_type == VAR_UNKNOWN
|| type->tt_type == VAR_LIST
|| type->tt_type == VAR_DICT
|| type->tt_type == VAR_BLOB)
! return arg_type_modifiable(type, context->arg_idx + 1);
arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
return FAIL;
}
***************
*** 545,550 ****
--- 575,595 ----
}
/*
+ * Check "type" is a list of 'any' or a dict of 'any' or a blob or a string.
+ * Also check the value is modifiable.
+ */
+ static int
+ arg_list_or_dict_or_blob_or_string_mod(
+ type_T *type,
+ type_T *decl_type,
+ argcontext_T *context)
+ {
+ if (arg_list_or_dict_or_blob_or_string(type, decl_type, context) == FAIL)
+ return FAIL;
+ return arg_type_modifiable(type, context->arg_idx + 1);
+ }
+
+ /*
* Check second argument of map() or filter().
*/
static int
***************
*** 994,1000 ****
static argcheck_T arg1_job[] = {arg_job};
static argcheck_T arg1_list_any[] = {arg_list_any};
static argcheck_T arg1_list_number[] = {arg_list_number};
! static argcheck_T arg1_list_or_blob[] = {arg_list_or_blob};
static argcheck_T arg1_list_or_dict[] = {arg_list_or_dict};
static argcheck_T arg1_list_string[] = {arg_list_string};
static argcheck_T arg1_string_or_list_or_dict[] =
{arg_string_or_list_or_dict};
--- 1039,1045 ----
static argcheck_T arg1_job[] = {arg_job};
static argcheck_T arg1_list_any[] = {arg_list_any};
static argcheck_T arg1_list_number[] = {arg_list_number};
! static argcheck_T arg1_list_or_blob_mod[] = {arg_list_or_blob_mod};
static argcheck_T arg1_list_or_dict[] = {arg_list_or_dict};
static argcheck_T arg1_list_string[] = {arg_list_string};
static argcheck_T arg1_string_or_list_or_dict[] =
{arg_string_or_list_or_dict};
***************
*** 1091,1105 ****
static argcheck_T arg1_len[] = {arg_len1};
static argcheck_T arg3_libcall[] = {arg_string, arg_string, arg_string_or_nr};
static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool,
arg_bool};
! static argcheck_T arg2_filter[] = {arg_list_or_dict_or_blob_or_string,
arg_filter_func};
! static argcheck_T arg2_map[] = {arg_list_or_dict_or_blob_or_string,
arg_map_func};
static argcheck_T arg2_mapnew[] = {arg_list_or_dict_or_blob_or_string, NULL};
static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number,
arg_number, arg_dict_any};
static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any,
arg_number, arg_number, arg_dict_any};
static argcheck_T arg119_printf[] = {arg_string_or_nr, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL};
static argcheck_T arg23_reduce[] = {arg_string_list_or_blob, NULL, NULL};
static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string,
arg_number};
! static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob, arg_remove2,
arg_number};
static argcheck_T arg2_repeat[] = {arg_repeat1, arg_number};
static argcheck_T arg15_search[] = {arg_string, arg_string, arg_number,
arg_number, arg_string_or_func};
static argcheck_T arg37_searchpair[] = {arg_string, arg_string, arg_string,
arg_string, arg_string_or_func, arg_number, arg_number};
--- 1136,1150 ----
static argcheck_T arg1_len[] = {arg_len1};
static argcheck_T arg3_libcall[] = {arg_string, arg_string, arg_string_or_nr};
static argcheck_T arg14_maparg[] = {arg_string, arg_string, arg_bool,
arg_bool};
! static argcheck_T arg2_filter[] = {arg_list_or_dict_or_blob_or_string_mod,
arg_filter_func};
! static argcheck_T arg2_map[] = {arg_list_or_dict_or_blob_or_string_mod,
arg_map_func};
static argcheck_T arg2_mapnew[] = {arg_list_or_dict_or_blob_or_string, NULL};
static argcheck_T arg25_matchadd[] = {arg_string, arg_string, arg_number,
arg_number, arg_dict_any};
static argcheck_T arg25_matchaddpos[] = {arg_string, arg_list_any,
arg_number, arg_number, arg_dict_any};
static argcheck_T arg119_printf[] = {arg_string_or_nr, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL};
static argcheck_T arg23_reduce[] = {arg_string_list_or_blob, NULL, NULL};
static argcheck_T arg24_remote_expr[] = {arg_string, arg_string, arg_string,
arg_number};
! static argcheck_T arg23_remove[] = {arg_list_or_dict_or_blob_mod,
arg_remove2, arg_number};
static argcheck_T arg2_repeat[] = {arg_repeat1, arg_number};
static argcheck_T arg15_search[] = {arg_string, arg_string, arg_number,
arg_number, arg_string_or_func};
static argcheck_T arg37_searchpair[] = {arg_string, arg_string, arg_string,
arg_string, arg_string_or_func, arg_number, arg_number};
***************
*** 1111,1117 ****
static argcheck_T arg02_sign_getplaced[] = {arg_buffer, arg_dict_any};
static argcheck_T arg45_sign_place[] = {arg_number, arg_string, arg_string,
arg_buffer, arg_dict_any};
static argcheck_T arg23_slice[] = {arg_slice1, arg_number, arg_number};
! static argcheck_T arg13_sortuniq[] = {arg_list_any, arg_sort_how,
arg_dict_any};
static argcheck_T arg24_strpart[] = {arg_string, arg_number, arg_number,
arg_bool};
static argcheck_T arg12_system[] = {arg_string, arg_str_or_nr_or_list};
static argcheck_T arg23_win_execute[] = {arg_number,
arg_string_or_list_string, arg_string};
--- 1156,1162 ----
static argcheck_T arg02_sign_getplaced[] = {arg_buffer, arg_dict_any};
static argcheck_T arg45_sign_place[] = {arg_number, arg_string, arg_string,
arg_buffer, arg_dict_any};
static argcheck_T arg23_slice[] = {arg_slice1, arg_number, arg_number};
! static argcheck_T arg13_sortuniq[] = {arg_list_any_mod, arg_sort_how,
arg_dict_any};
static argcheck_T arg24_strpart[] = {arg_string, arg_number, arg_number,
arg_bool};
static argcheck_T arg12_system[] = {arg_string, arg_str_or_nr_or_list};
static argcheck_T arg23_win_execute[] = {arg_number,
arg_string_or_list_string, arg_string};
***************
*** 2362,2368 ****
ret_repeat, f_repeat},
{"resolve", 1, 1, FEARG_1, arg1_string,
ret_string, f_resolve},
! {"reverse", 1, 1, FEARG_1, arg1_list_or_blob,
ret_first_arg, f_reverse},
{"round", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, f_round},
--- 2407,2413 ----
ret_repeat, f_repeat},
{"resolve", 1, 1, FEARG_1, arg1_string,
ret_string, f_resolve},
! {"reverse", 1, 1, FEARG_1, arg1_list_or_blob_mod,
ret_first_arg, f_reverse},
{"round", 1, 1, FEARG_1, arg1_float_or_nr,
ret_float, f_round},
*** ../vim-9.0.0628/src/testdir/test_vim9_builtin.vim 2022-09-30
11:04:47.169344522 +0100
--- src/testdir/test_vim9_builtin.vim 2022-09-30 17:47:04.828826612 +0100
***************
*** 1528,1533 ****
--- 1528,1547 ----
res->assert_equal({aa: [1], ac: [3]})
enddef
+ def Test_filter_const()
+ var lines =<< trim END
+ const l = [1, 2, 3]
+ filter(l, 'v:val == 2')
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
list<number>')
+
+ lines =<< trim END
+ const d = {a: 1, b: 2}
+ filter(d, 'v:val == 2')
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
dict<number>')
+ enddef
+
def Test_foldclosed()
v9.CheckDefAndScriptFailure(['foldclosed(function("min"))'], ['E1013:
Argument 1: type mismatch, expected string but got func(...): unknown', 'E1220:
String or Number required for argument 1'])
v9.CheckDefExecAndScriptFailure(['foldclosed("")'], 'E1209: Invalid value
for a line number')
***************
*** 2547,2552 ****
--- 2561,2580 ----
v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected
number but got bool')
enddef
+ def Test_map_const()
+ var lines =<< trim END
+ const l = [1, 2, 3]
+ map(l, 'SomeFunc')
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
list<number>')
+
+ lines =<< trim END
+ const d = {a: 1, b: 2}
+ map(d, 'SomeFunc')
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
dict<number>')
+ enddef
+
def Test_map_function_arg()
var lines =<< trim END
def MapOne(i: number, v: string): string
***************
*** 3334,3345 ****
v9.CheckDefAndScriptFailure(['remote_startserver({})'], ['E1013: Argument
1: type mismatch, expected string but got dict<unknown>', 'E1174: String
required for argument 1'])
enddef
! def Test_remove_const_list()
var l: list<number> = [1, 2, 3, 4]
assert_equal([1, 2], remove(l, 0, 1))
assert_equal([3, 4], l)
enddef
def Test_remove()
v9.CheckDefAndScriptFailure(['remove("a", 1)'], ['E1013: Argument 1: type
mismatch, expected list<any> but got string', 'E1228: List, Dictionary or Blob
required for argument 1'])
v9.CheckDefAndScriptFailure(['remove([], "b")'], ['E1013: Argument 2: type
mismatch, expected number but got string', 'E1210: Number required for argument
2'])
--- 3362,3393 ----
v9.CheckDefAndScriptFailure(['remote_startserver({})'], ['E1013: Argument
1: type mismatch, expected string but got dict<unknown>', 'E1174: String
required for argument 1'])
enddef
! def Test_remove_literal_list()
var l: list<number> = [1, 2, 3, 4]
assert_equal([1, 2], remove(l, 0, 1))
assert_equal([3, 4], l)
enddef
+ def Test_remove_const()
+ var lines =<< trim END
+ const l = [1, 2, 3, 4]
+ remove(l, 1)
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
list<number>')
+
+ lines =<< trim END
+ const d = {a: 1, b: 2}
+ remove(d, 'a')
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
dict<number>')
+
+ lines =<< trim END
+ const b = 0z010203
+ remove(b, 1)
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
blob')
+ enddef
+
def Test_remove()
v9.CheckDefAndScriptFailure(['remove("a", 1)'], ['E1013: Argument 1: type
mismatch, expected list<any> but got string', 'E1228: List, Dictionary or Blob
required for argument 1'])
v9.CheckDefAndScriptFailure(['remove([], "b")'], ['E1013: Argument 2: type
mismatch, expected number but got string', 'E1210: Number required for argument
2'])
***************
*** 3419,3424 ****
--- 3467,3486 ----
res->assert_equal(6)
enddef
+ def Test_reverse_const()
+ var lines =<< trim END
+ const l = [1, 2, 3, 4]
+ reverse(l)
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
list<number>')
+
+ lines =<< trim END
+ const b = 0z010203
+ reverse(b)
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
blob')
+ enddef
+
def Test_rubyeval()
if !has('ruby')
CheckFeature ruby
***************
*** 4053,4058 ****
--- 4115,4128 ----
v9.CheckScriptSuccess(lines)
enddef
+ def Test_sort_const()
+ var lines =<< trim END
+ const l = [1, 2, 3, 4]
+ sort(l)
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
list<number>')
+ enddef
+
def Test_sort_compare_func_fails()
v9.CheckDefAndScriptFailure(['sort("a")'], ['E1013: Argument 1: type
mismatch, expected list<any> but got string', 'E1211: List required for
argument 1'])
v9.CheckDefAndScriptFailure(['sort([1], "", [1])'], ['E1013: Argument 3:
type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary
required for argument 3'])
***************
*** 4654,4659 ****
--- 4724,4737 ----
v9.CheckDefFailure(['var l: list<number> = uniq(["a", "b"])'], 'E1012: Type
mismatch; expected list<number> but got list<string>')
enddef
+ def Test_uniq_const()
+ var lines =<< trim END
+ const l = [1, 2, 3, 4]
+ uniq(l)
+ END
+ v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const
list<number>')
+ enddef
+
def Test_values()
v9.CheckDefAndScriptFailure(['values([])'], ['E1013: Argument 1: type
mismatch, expected dict<any> but got list<unknown>', 'E1206: Dictionary
required for argument 1'])
assert_equal([], {}->values())
*** ../vim-9.0.0628/src/version.c 2022-09-30 12:00:02.329104816 +0100
--- src/version.c 2022-09-30 16:54:10.851168233 +0100
***************
*** 701,702 ****
--- 701,704 ----
{ /* Add new patch number below this line */
+ /**/
+ 629,
/**/
--
hundred-and-one symptoms of being an internet addict:
231. You sprinkle Carpet Fresh on the rugs and put your vacuum cleaner
in the front doorway permanently so it always looks like you are
actually attempting to do something about that mess that has amassed
since you discovered the Internet.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20220930170250.9A6151C09A3%40moolenaar.net.