forked from aniani/vim
patch 8.2.2501: not always clear where an error is reported
Problem: Not always clear where an error is reported. Solution: Add the where_T structure and pass it around. (closes #7796)
This commit is contained in:
@@ -1089,7 +1089,8 @@ dict_extend(dict_T *d1, dict_T *d2, char_u *action)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type != NULL
|
if (type != NULL
|
||||||
&& check_typval_type(type, &HI2DI(hi2)->di_tv, 0) == FAIL)
|
&& check_typval_arg_type(type, &HI2DI(hi2)->di_tv, 0)
|
||||||
|
== FAIL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (di1 == NULL)
|
if (di1 == NULL)
|
||||||
|
@@ -361,3 +361,5 @@ EXTERN char e_cannot_json_encode_str[]
|
|||||||
INIT(= N_("E1161: Cannot json encode a %s"));
|
INIT(= N_("E1161: Cannot json encode a %s"));
|
||||||
EXTERN char e_register_name_must_be_one_char_str[]
|
EXTERN char e_register_name_must_be_one_char_str[]
|
||||||
INIT(= N_("E1162: Register name must be one character: %s"));
|
INIT(= N_("E1162: Register name must be one character: %s"));
|
||||||
|
EXTERN char e_variable_nr_type_mismatch_expected_str_but_got_str[]
|
||||||
|
INIT(= N_("E1163: Variable %d: type mismatch, expected %s but got %s"));
|
||||||
|
12
src/eval.c
12
src/eval.c
@@ -1299,8 +1299,9 @@ set_var_lval(
|
|||||||
char_u *endp,
|
char_u *endp,
|
||||||
typval_T *rettv,
|
typval_T *rettv,
|
||||||
int copy,
|
int copy,
|
||||||
int flags, // ASSIGN_CONST, ASSIGN_NO_DECL
|
int flags, // ASSIGN_CONST, ASSIGN_NO_DECL
|
||||||
char_u *op)
|
char_u *op,
|
||||||
|
int var_idx) // index for "let [a, b] = list"
|
||||||
{
|
{
|
||||||
int cc;
|
int cc;
|
||||||
listitem_T *ri;
|
listitem_T *ri;
|
||||||
@@ -1390,9 +1391,10 @@ set_var_lval(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lp->ll_type != NULL
|
if (lp->ll_type != NULL
|
||||||
&& check_typval_type(lp->ll_type, rettv, 0) == FAIL)
|
&& check_typval_arg_type(lp->ll_type, rettv, 0) == FAIL)
|
||||||
return;
|
return;
|
||||||
set_var_const(lp->ll_name, lp->ll_type, rettv, copy, flags);
|
set_var_const(lp->ll_name, lp->ll_type, rettv, copy,
|
||||||
|
flags, var_idx);
|
||||||
}
|
}
|
||||||
*endp = cc;
|
*endp = cc;
|
||||||
}
|
}
|
||||||
@@ -1471,7 +1473,7 @@ set_var_lval(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lp->ll_valtype != NULL
|
if (lp->ll_valtype != NULL
|
||||||
&& check_typval_type(lp->ll_valtype, rettv, 0) == FAIL)
|
&& check_typval_arg_type(lp->ll_valtype, rettv, 0) == FAIL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (lp->ll_newkey != NULL)
|
if (lp->ll_newkey != NULL)
|
||||||
|
@@ -173,7 +173,7 @@ static void list_buf_vars(int *first);
|
|||||||
static void list_win_vars(int *first);
|
static void list_win_vars(int *first);
|
||||||
static void list_tab_vars(int *first);
|
static void list_tab_vars(int *first);
|
||||||
static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
|
static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
|
||||||
static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int flags, char_u *endchars, char_u *op);
|
static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int flags, char_u *endchars, char_u *op, int var_idx);
|
||||||
static int do_unlet_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie);
|
static int do_unlet_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie);
|
||||||
static int do_lock_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie);
|
static int do_lock_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie);
|
||||||
static void list_one_var(dictitem_T *v, char *prefix, int *first);
|
static void list_one_var(dictitem_T *v, char *prefix, int *first);
|
||||||
@@ -929,13 +929,14 @@ ex_let_vars(
|
|||||||
char_u *arg = arg_start;
|
char_u *arg = arg_start;
|
||||||
list_T *l;
|
list_T *l;
|
||||||
int i;
|
int i;
|
||||||
|
int var_idx = 0;
|
||||||
listitem_T *item;
|
listitem_T *item;
|
||||||
typval_T ltv;
|
typval_T ltv;
|
||||||
|
|
||||||
if (*arg != '[')
|
if (*arg != '[')
|
||||||
{
|
{
|
||||||
// ":let var = expr" or ":for var in list"
|
// ":let var = expr" or ":for var in list"
|
||||||
if (ex_let_one(arg, tv, copy, flags, op, op) == NULL)
|
if (ex_let_one(arg, tv, copy, flags, op, op, var_idx) == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -964,7 +965,9 @@ ex_let_vars(
|
|||||||
while (*arg != ']')
|
while (*arg != ']')
|
||||||
{
|
{
|
||||||
arg = skipwhite(arg + 1);
|
arg = skipwhite(arg + 1);
|
||||||
arg = ex_let_one(arg, &item->li_tv, TRUE, flags, (char_u *)",;]", op);
|
++var_idx;
|
||||||
|
arg = ex_let_one(arg, &item->li_tv, TRUE, flags, (char_u *)",;]",
|
||||||
|
op, var_idx);
|
||||||
item = item->li_next;
|
item = item->li_next;
|
||||||
if (arg == NULL)
|
if (arg == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -987,9 +990,10 @@ ex_let_vars(
|
|||||||
ltv.v_lock = 0;
|
ltv.v_lock = 0;
|
||||||
ltv.vval.v_list = l;
|
ltv.vval.v_list = l;
|
||||||
l->lv_refcount = 1;
|
l->lv_refcount = 1;
|
||||||
|
++var_idx;
|
||||||
|
|
||||||
arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, flags,
|
arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, flags,
|
||||||
(char_u *)"]", op);
|
(char_u *)"]", op, var_idx);
|
||||||
clear_tv(<v);
|
clear_tv(<v);
|
||||||
if (arg == NULL)
|
if (arg == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -1284,7 +1288,8 @@ ex_let_one(
|
|||||||
int copy, // copy value from "tv"
|
int copy, // copy value from "tv"
|
||||||
int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc.
|
int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc.
|
||||||
char_u *endchars, // valid chars after variable name or NULL
|
char_u *endchars, // valid chars after variable name or NULL
|
||||||
char_u *op) // "+", "-", "." or NULL
|
char_u *op, // "+", "-", "." or NULL
|
||||||
|
int var_idx) // variable index for "let [a, b] = list"
|
||||||
{
|
{
|
||||||
int c1;
|
int c1;
|
||||||
char_u *name;
|
char_u *name;
|
||||||
@@ -1508,7 +1513,7 @@ ex_let_one(
|
|||||||
emsg(_(e_letunexp));
|
emsg(_(e_letunexp));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_var_lval(&lv, p, tv, copy, flags, op);
|
set_var_lval(&lv, p, tv, copy, flags, op, var_idx);
|
||||||
arg_end = p;
|
arg_end = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3075,7 +3080,7 @@ set_var(
|
|||||||
typval_T *tv,
|
typval_T *tv,
|
||||||
int copy) // make copy of value in "tv"
|
int copy) // make copy of value in "tv"
|
||||||
{
|
{
|
||||||
set_var_const(name, NULL, tv, copy, ASSIGN_DECL);
|
set_var_const(name, NULL, tv, copy, ASSIGN_DECL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3089,7 +3094,8 @@ set_var_const(
|
|||||||
type_T *type,
|
type_T *type,
|
||||||
typval_T *tv_arg,
|
typval_T *tv_arg,
|
||||||
int copy, // make copy of value in "tv"
|
int copy, // make copy of value in "tv"
|
||||||
int flags) // ASSIGN_CONST, ASSIGN_FINAL, etc.
|
int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc.
|
||||||
|
int var_idx) // index for ":let [a, b] = list"
|
||||||
{
|
{
|
||||||
typval_T *tv = tv_arg;
|
typval_T *tv = tv_arg;
|
||||||
typval_T bool_tv;
|
typval_T bool_tv;
|
||||||
@@ -3148,6 +3154,8 @@ set_var_const(
|
|||||||
|
|
||||||
if (is_script_local && vim9script)
|
if (is_script_local && vim9script)
|
||||||
{
|
{
|
||||||
|
where_T where;
|
||||||
|
|
||||||
if ((flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0)
|
if ((flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0)
|
||||||
{
|
{
|
||||||
semsg(_(e_redefining_script_item_str), name);
|
semsg(_(e_redefining_script_item_str), name);
|
||||||
@@ -3155,7 +3163,9 @@ set_var_const(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check the type and adjust to bool if needed
|
// check the type and adjust to bool if needed
|
||||||
if (check_script_var_type(&di->di_tv, tv, name) == FAIL)
|
where.wt_index = var_idx;
|
||||||
|
where.wt_variable = TRUE;
|
||||||
|
if (check_script_var_type(&di->di_tv, tv, name, where) == FAIL)
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3719,10 +3729,10 @@ var_redir_start(char_u *name, int append)
|
|||||||
tv.vval.v_string = (char_u *)"";
|
tv.vval.v_string = (char_u *)"";
|
||||||
if (append)
|
if (append)
|
||||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE,
|
set_var_lval(redir_lval, redir_endp, &tv, TRUE,
|
||||||
ASSIGN_NO_DECL, (char_u *)".");
|
ASSIGN_NO_DECL, (char_u *)".", 0);
|
||||||
else
|
else
|
||||||
set_var_lval(redir_lval, redir_endp, &tv, TRUE,
|
set_var_lval(redir_lval, redir_endp, &tv, TRUE,
|
||||||
ASSIGN_NO_DECL, (char_u *)"=");
|
ASSIGN_NO_DECL, (char_u *)"=", 0);
|
||||||
clear_lval(redir_lval);
|
clear_lval(redir_lval);
|
||||||
if (called_emsg > called_emsg_before)
|
if (called_emsg > called_emsg_before)
|
||||||
{
|
{
|
||||||
@@ -3794,7 +3804,7 @@ var_redir_stop(void)
|
|||||||
FALSE, FALSE, 0, FNE_CHECK_START);
|
FALSE, FALSE, 0, FNE_CHECK_START);
|
||||||
if (redir_endp != NULL && redir_lval->ll_name != NULL)
|
if (redir_endp != NULL && redir_lval->ll_name != NULL)
|
||||||
set_var_lval(redir_lval, redir_endp, &tv, FALSE, 0,
|
set_var_lval(redir_lval, redir_endp, &tv, FALSE, 0,
|
||||||
(char_u *)".");
|
(char_u *)".", 0);
|
||||||
clear_lval(redir_lval);
|
clear_lval(redir_lval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
src/list.c
20
src/list.c
@@ -698,7 +698,7 @@ list_insert_tv(list_T *l, typval_T *tv, listitem_T *item)
|
|||||||
listitem_T *ni;
|
listitem_T *ni;
|
||||||
|
|
||||||
if (l->lv_type != NULL && l->lv_type->tt_member != NULL
|
if (l->lv_type != NULL && l->lv_type->tt_member != NULL
|
||||||
&& check_typval_type(l->lv_type->tt_member, tv, 0) == FAIL)
|
&& check_typval_arg_type(l->lv_type->tt_member, tv, 0) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
ni = listitem_alloc();
|
ni = listitem_alloc();
|
||||||
if (ni == NULL)
|
if (ni == NULL)
|
||||||
@@ -2135,8 +2135,8 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
|
|||||||
}
|
}
|
||||||
if (filtermap == FILTERMAP_MAP)
|
if (filtermap == FILTERMAP_MAP)
|
||||||
{
|
{
|
||||||
if (type != NULL && check_typval_type(type->tt_member,
|
if (type != NULL && check_typval_arg_type(
|
||||||
&newtv, 0) == FAIL)
|
type->tt_member, &newtv, 0) == FAIL)
|
||||||
{
|
{
|
||||||
clear_tv(&newtv);
|
clear_tv(&newtv);
|
||||||
break;
|
break;
|
||||||
@@ -2270,8 +2270,8 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
|
|||||||
if (filtermap != FILTERMAP_FILTER)
|
if (filtermap != FILTERMAP_FILTER)
|
||||||
{
|
{
|
||||||
if (filtermap == FILTERMAP_MAP && type != NULL
|
if (filtermap == FILTERMAP_MAP && type != NULL
|
||||||
&& check_typval_type(type->tt_member,
|
&& check_typval_arg_type(
|
||||||
&newtv, 0) == FAIL)
|
type->tt_member, &newtv, 0) == FAIL)
|
||||||
{
|
{
|
||||||
clear_tv(&newtv);
|
clear_tv(&newtv);
|
||||||
break;
|
break;
|
||||||
@@ -2314,8 +2314,8 @@ filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
|
|||||||
}
|
}
|
||||||
if (filtermap == FILTERMAP_MAP)
|
if (filtermap == FILTERMAP_MAP)
|
||||||
{
|
{
|
||||||
if (type != NULL && check_typval_type(type->tt_member,
|
if (type != NULL && check_typval_arg_type(
|
||||||
&newtv, 0) == FAIL)
|
type->tt_member, &newtv, 0) == FAIL)
|
||||||
{
|
{
|
||||||
clear_tv(&newtv);
|
clear_tv(&newtv);
|
||||||
break;
|
break;
|
||||||
@@ -2584,7 +2584,8 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
item = NULL;
|
item = NULL;
|
||||||
if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
|
if (type != NULL && check_typval_arg_type(
|
||||||
|
type, &argvars[1], 2) == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
list_extend(l1, l2, item);
|
list_extend(l1, l2, item);
|
||||||
|
|
||||||
@@ -2641,7 +2642,8 @@ extend(typval_T *argvars, typval_T *rettv, char_u *arg_errmsg, int is_new)
|
|||||||
else
|
else
|
||||||
action = (char_u *)"force";
|
action = (char_u *)"force";
|
||||||
|
|
||||||
if (type != NULL && check_typval_type(type, &argvars[1], 2) == FAIL)
|
if (type != NULL && check_typval_arg_type(
|
||||||
|
type, &argvars[1], 2) == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
dict_extend(d1, d2, action);
|
dict_extend(d1, d2, action);
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@ void *call_func_retlist(char_u *func, int argc, typval_T *argv);
|
|||||||
int eval_foldexpr(char_u *arg, int *cp);
|
int eval_foldexpr(char_u *arg, int *cp);
|
||||||
char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags);
|
char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags);
|
||||||
void clear_lval(lval_T *lp);
|
void clear_lval(lval_T *lp);
|
||||||
void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op);
|
void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op, int var_idx);
|
||||||
void *eval_for_line(char_u *arg, int *errp, exarg_T *eap, evalarg_T *evalarg);
|
void *eval_for_line(char_u *arg, int *errp, exarg_T *eap, evalarg_T *evalarg);
|
||||||
void skip_for_lines(void *fi_void, evalarg_T *evalarg);
|
void skip_for_lines(void *fi_void, evalarg_T *evalarg);
|
||||||
int next_for_item(void *fi_void, char_u *arg);
|
int next_for_item(void *fi_void, char_u *arg);
|
||||||
|
@@ -70,7 +70,7 @@ void vars_clear(hashtab_T *ht);
|
|||||||
void vars_clear_ext(hashtab_T *ht, int free_val);
|
void vars_clear_ext(hashtab_T *ht, int free_val);
|
||||||
void delete_var(hashtab_T *ht, hashitem_T *hi);
|
void delete_var(hashtab_T *ht, hashitem_T *hi);
|
||||||
void set_var(char_u *name, typval_T *tv, int copy);
|
void set_var(char_u *name, typval_T *tv, int copy);
|
||||||
void set_var_const(char_u *name, type_T *type, typval_T *tv_arg, int copy, int flags);
|
void set_var_const(char_u *name, type_T *type, typval_T *tv_arg, int copy, int flags, int var_idx);
|
||||||
int var_check_permission(dictitem_T *di, char_u *name);
|
int var_check_permission(dictitem_T *di, char_u *name);
|
||||||
int var_check_ro(int flags, char_u *name, int use_gettext);
|
int var_check_ro(int flags, char_u *name, int use_gettext);
|
||||||
int var_check_lock(int flags, char_u *name, int use_gettext);
|
int var_check_lock(int flags, char_u *name, int use_gettext);
|
||||||
|
@@ -14,5 +14,5 @@ void update_vim9_script_var(int create, dictitem_T *di, int flags, typval_T *tv,
|
|||||||
void hide_script_var(scriptitem_T *si, int idx, int func_defined);
|
void hide_script_var(scriptitem_T *si, int idx, int func_defined);
|
||||||
void free_all_script_vars(scriptitem_T *si);
|
void free_all_script_vars(scriptitem_T *si);
|
||||||
svar_T *find_typval_in_script(typval_T *dest);
|
svar_T *find_typval_in_script(typval_T *dest);
|
||||||
int check_script_var_type(typval_T *dest, typval_T *value, char_u *name);
|
int check_script_var_type(typval_T *dest, typval_T *value, char_u *name, where_T where);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -11,10 +11,12 @@ int func_type_add_arg_types(type_T *functype, int argcount, garray_T *type_gap);
|
|||||||
int need_convert_to_bool(type_T *type, typval_T *tv);
|
int need_convert_to_bool(type_T *type, typval_T *tv);
|
||||||
type_T *typval2type(typval_T *tv, garray_T *type_gap);
|
type_T *typval2type(typval_T *tv, garray_T *type_gap);
|
||||||
type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
|
type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap);
|
||||||
int check_typval_type(type_T *expected, typval_T *actual_tv, int argidx);
|
int check_typval_arg_type(type_T *expected, typval_T *actual_tv, int arg_idx);
|
||||||
|
int check_typval_type(type_T *expected, typval_T *actual_tv, where_T where);
|
||||||
void type_mismatch(type_T *expected, type_T *actual);
|
void type_mismatch(type_T *expected, type_T *actual);
|
||||||
void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
|
void arg_type_mismatch(type_T *expected, type_T *actual, int arg_idx);
|
||||||
int check_type(type_T *expected, type_T *actual, int give_msg, int argidx);
|
void type_mismatch_where(type_T *expected, type_T *actual, where_T where);
|
||||||
|
int check_type(type_T *expected, type_T *actual, int give_msg, where_T where);
|
||||||
int check_argument_types(type_T *type, typval_T *argvars, int argcount, char_u *name);
|
int check_argument_types(type_T *type, typval_T *argvars, int argcount, char_u *name);
|
||||||
char_u *skip_type(char_u *start, int optional);
|
char_u *skip_type(char_u *start, int optional);
|
||||||
type_T *parse_type(char_u **arg, garray_T *type_gap, int give_error);
|
type_T *parse_type(char_u **arg, garray_T *type_gap, int give_error);
|
||||||
|
@@ -4387,3 +4387,10 @@ typedef enum {
|
|||||||
MAGIC_ON = 3, // "\m" or 'magic'
|
MAGIC_ON = 3, // "\m" or 'magic'
|
||||||
MAGIC_ALL = 4 // "\v" very magic
|
MAGIC_ALL = 4 // "\v" very magic
|
||||||
} magic_T;
|
} magic_T;
|
||||||
|
|
||||||
|
// Struct used to pass to error messages about where the error happened.
|
||||||
|
typedef struct {
|
||||||
|
char wt_index; // argument or variable index, 0 means unknown
|
||||||
|
char wt_variable; // "variable" when TRUE, "argument" otherwise
|
||||||
|
} where_T;
|
||||||
|
|
||||||
|
@@ -284,6 +284,14 @@ def Test_assign_unpack()
|
|||||||
[v1, v2] = ''
|
[v1, v2] = ''
|
||||||
END
|
END
|
||||||
CheckDefFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 3)
|
CheckDefFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 3)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
g:values = [false, 0]
|
||||||
|
var x: bool
|
||||||
|
var y: string
|
||||||
|
[x, y] = g:values
|
||||||
|
END
|
||||||
|
CheckDefExecAndScriptFailure(lines, 'E1163: Variable 2: type mismatch, expected string but got number')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assign_linebreak()
|
def Test_assign_linebreak()
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2501,
|
||||||
/**/
|
/**/
|
||||||
2500,
|
2500,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -893,6 +893,8 @@ need_type(
|
|||||||
int silent,
|
int silent,
|
||||||
int actual_is_const)
|
int actual_is_const)
|
||||||
{
|
{
|
||||||
|
where_T where;
|
||||||
|
|
||||||
if (expected == &t_bool && actual != &t_bool
|
if (expected == &t_bool && actual != &t_bool
|
||||||
&& (actual->tt_flags & TTFLAG_BOOL_OK))
|
&& (actual->tt_flags & TTFLAG_BOOL_OK))
|
||||||
{
|
{
|
||||||
@@ -902,7 +904,9 @@ need_type(
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_type(expected, actual, FALSE, arg_idx) == OK)
|
where.wt_index = arg_idx;
|
||||||
|
where.wt_variable = FALSE;
|
||||||
|
if (check_type(expected, actual, FALSE, where) == OK)
|
||||||
return OK;
|
return OK;
|
||||||
|
|
||||||
// If the actual type can be the expected type add a runtime check.
|
// If the actual type can be the expected type add a runtime check.
|
||||||
@@ -4287,10 +4291,13 @@ compile_expr7t(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
|||||||
{
|
{
|
||||||
garray_T *stack = &cctx->ctx_type_stack;
|
garray_T *stack = &cctx->ctx_type_stack;
|
||||||
type_T *actual;
|
type_T *actual;
|
||||||
|
where_T where;
|
||||||
|
|
||||||
generate_ppconst(cctx, ppconst);
|
generate_ppconst(cctx, ppconst);
|
||||||
actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
actual = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||||
if (check_type(want_type, actual, FALSE, 0) == FAIL)
|
where.wt_index = 0;
|
||||||
|
where.wt_variable = FALSE;
|
||||||
|
if (check_type(want_type, actual, FALSE, where) == FAIL)
|
||||||
{
|
{
|
||||||
if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL)
|
if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -8078,6 +8085,7 @@ compile_def_function(
|
|||||||
garray_T *stack = &cctx.ctx_type_stack;
|
garray_T *stack = &cctx.ctx_type_stack;
|
||||||
type_T *val_type;
|
type_T *val_type;
|
||||||
int arg_idx = first_def_arg + i;
|
int arg_idx = first_def_arg + i;
|
||||||
|
where_T where;
|
||||||
|
|
||||||
ufunc->uf_def_arg_idx[i] = instr->ga_len;
|
ufunc->uf_def_arg_idx[i] = instr->ga_len;
|
||||||
arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
|
arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i];
|
||||||
@@ -8088,13 +8096,15 @@ compile_def_function(
|
|||||||
// Otherwise check that the default value type matches the
|
// Otherwise check that the default value type matches the
|
||||||
// specified type.
|
// specified type.
|
||||||
val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
val_type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
|
||||||
|
where.wt_index = arg_idx + 1;
|
||||||
|
where.wt_variable = FALSE;
|
||||||
if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
|
if (ufunc->uf_arg_types[arg_idx] == &t_unknown)
|
||||||
{
|
{
|
||||||
did_set_arg_type = TRUE;
|
did_set_arg_type = TRUE;
|
||||||
ufunc->uf_arg_types[arg_idx] = val_type;
|
ufunc->uf_arg_types[arg_idx] = val_type;
|
||||||
}
|
}
|
||||||
else if (check_type(ufunc->uf_arg_types[arg_idx], val_type,
|
else if (check_type(ufunc->uf_arg_types[arg_idx], val_type,
|
||||||
TRUE, arg_idx + 1) == FAIL)
|
TRUE, where) == FAIL)
|
||||||
goto erret;
|
goto erret;
|
||||||
|
|
||||||
if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
|
if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL)
|
||||||
|
@@ -851,7 +851,7 @@ store_var(char_u *name, typval_T *tv)
|
|||||||
funccal_entry_T entry;
|
funccal_entry_T entry;
|
||||||
|
|
||||||
save_funccal(&entry);
|
save_funccal(&entry);
|
||||||
set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL);
|
set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL, 0);
|
||||||
restore_funccal();
|
restore_funccal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1146,6 +1146,7 @@ call_def_function(
|
|||||||
int save_did_emsg_def = did_emsg_def;
|
int save_did_emsg_def = did_emsg_def;
|
||||||
int trylevel_at_start = trylevel;
|
int trylevel_at_start = trylevel;
|
||||||
int orig_funcdepth;
|
int orig_funcdepth;
|
||||||
|
where_T where;
|
||||||
|
|
||||||
// Get pointer to item in the stack.
|
// Get pointer to item in the stack.
|
||||||
#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
|
#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx)
|
||||||
@@ -1202,7 +1203,7 @@ call_def_function(
|
|||||||
++idx)
|
++idx)
|
||||||
{
|
{
|
||||||
if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
|
if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len
|
||||||
&& check_typval_type(ufunc->uf_arg_types[idx], &argv[idx],
|
&& check_typval_arg_type(ufunc->uf_arg_types[idx], &argv[idx],
|
||||||
idx + 1) == FAIL)
|
idx + 1) == FAIL)
|
||||||
goto failed_early;
|
goto failed_early;
|
||||||
copy_tv(&argv[idx], STACK_TV_BOT(0));
|
copy_tv(&argv[idx], STACK_TV_BOT(0));
|
||||||
@@ -1233,7 +1234,7 @@ call_def_function(
|
|||||||
|
|
||||||
for (idx = 0; idx < vararg_count; ++idx)
|
for (idx = 0; idx < vararg_count; ++idx)
|
||||||
{
|
{
|
||||||
if (check_typval_type(expected, &li->li_tv,
|
if (check_typval_arg_type(expected, &li->li_tv,
|
||||||
argc + idx + 1) == FAIL)
|
argc + idx + 1) == FAIL)
|
||||||
goto failed_early;
|
goto failed_early;
|
||||||
li = li->li_next;
|
li = li->li_next;
|
||||||
@@ -1333,6 +1334,9 @@ call_def_function(
|
|||||||
emsg_silent_def = emsg_silent;
|
emsg_silent_def = emsg_silent;
|
||||||
did_emsg_def = 0;
|
did_emsg_def = 0;
|
||||||
|
|
||||||
|
where.wt_index = 0;
|
||||||
|
where.wt_variable = FALSE;
|
||||||
|
|
||||||
// Decide where to start execution, handles optional arguments.
|
// Decide where to start execution, handles optional arguments.
|
||||||
init_instr_idx(ufunc, argc, &ectx);
|
init_instr_idx(ufunc, argc, &ectx);
|
||||||
|
|
||||||
@@ -3170,6 +3174,11 @@ call_def_function(
|
|||||||
goto failed;
|
goto failed;
|
||||||
++ectx.ec_stack.ga_len;
|
++ectx.ec_stack.ga_len;
|
||||||
copy_tv(&li->li_tv, STACK_TV_BOT(-1));
|
copy_tv(&li->li_tv, STACK_TV_BOT(-1));
|
||||||
|
|
||||||
|
// Useful when used in unpack assignment. Reset at
|
||||||
|
// ISN_DROP.
|
||||||
|
where.wt_index = index + 1;
|
||||||
|
where.wt_variable = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -3288,9 +3297,12 @@ call_def_function(
|
|||||||
|
|
||||||
tv = STACK_TV_BOT((int)ct->ct_off);
|
tv = STACK_TV_BOT((int)ct->ct_off);
|
||||||
SOURCING_LNUM = iptr->isn_lnum;
|
SOURCING_LNUM = iptr->isn_lnum;
|
||||||
if (check_typval_type(ct->ct_type, tv, ct->ct_arg_idx)
|
if (!where.wt_variable)
|
||||||
== FAIL)
|
where.wt_index = ct->ct_arg_idx;
|
||||||
|
if (check_typval_type(ct->ct_type, tv, where) == FAIL)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
if (!where.wt_variable)
|
||||||
|
where.wt_index = 0;
|
||||||
|
|
||||||
// number 0 is FALSE, number 1 is TRUE
|
// number 0 is FALSE, number 1 is TRUE
|
||||||
if (tv->v_type == VAR_NUMBER
|
if (tv->v_type == VAR_NUMBER
|
||||||
@@ -3573,6 +3585,8 @@ call_def_function(
|
|||||||
case ISN_DROP:
|
case ISN_DROP:
|
||||||
--ectx.ec_stack.ga_len;
|
--ectx.ec_stack.ga_len;
|
||||||
clear_tv(STACK_TV_BOT(0));
|
clear_tv(STACK_TV_BOT(0));
|
||||||
|
where.wt_index = 0;
|
||||||
|
where.wt_variable = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@@ -650,7 +650,7 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg)
|
|||||||
init_tv.v_type = VAR_NUMBER;
|
init_tv.v_type = VAR_NUMBER;
|
||||||
else
|
else
|
||||||
init_tv.v_type = type->tt_type;
|
init_tv.v_type = type->tt_type;
|
||||||
set_var_const(name, type, &init_tv, FALSE, 0);
|
set_var_const(name, type, &init_tv, FALSE, 0, 0);
|
||||||
|
|
||||||
vim_free(name);
|
vim_free(name);
|
||||||
return p;
|
return p;
|
||||||
@@ -855,7 +855,7 @@ find_typval_in_script(typval_T *dest)
|
|||||||
if (sv->sv_name != NULL && sv->sv_tv == dest)
|
if (sv->sv_name != NULL && sv->sv_tv == dest)
|
||||||
return sv;
|
return sv;
|
||||||
}
|
}
|
||||||
iemsg("check_script_var_type(): not found");
|
iemsg("find_typval_in_script(): not found");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,7 +864,11 @@ find_typval_in_script(typval_T *dest)
|
|||||||
* If needed convert "value" to a bool.
|
* If needed convert "value" to a bool.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
|
check_script_var_type(
|
||||||
|
typval_T *dest,
|
||||||
|
typval_T *value,
|
||||||
|
char_u *name,
|
||||||
|
where_T where)
|
||||||
{
|
{
|
||||||
svar_T *sv = find_typval_in_script(dest);
|
svar_T *sv = find_typval_in_script(dest);
|
||||||
int ret;
|
int ret;
|
||||||
@@ -876,7 +880,7 @@ check_script_var_type(typval_T *dest, typval_T *value, char_u *name)
|
|||||||
semsg(_(e_readonlyvar), name);
|
semsg(_(e_readonlyvar), name);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
ret = check_typval_type(sv->sv_type, value, 0);
|
ret = check_typval_type(sv->sv_type, value, where);
|
||||||
if (ret == OK && need_convert_to_bool(sv->sv_type, value))
|
if (ret == OK && need_convert_to_bool(sv->sv_type, value))
|
||||||
{
|
{
|
||||||
int val = tv2bool(value);
|
int val = tv2bool(value);
|
||||||
|
@@ -399,13 +399,22 @@ typval2type_vimvar(typval_T *tv, garray_T *type_gap)
|
|||||||
return typval2type(tv, type_gap);
|
return typval2type(tv, type_gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
check_typval_arg_type(type_T *expected, typval_T *actual_tv, int arg_idx)
|
||||||
|
{
|
||||||
|
where_T where;
|
||||||
|
|
||||||
|
where.wt_index = arg_idx;
|
||||||
|
where.wt_variable = FALSE;
|
||||||
|
return check_typval_type(expected, actual_tv, where);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return FAIL if "expected" and "actual" don't match.
|
* Return FAIL if "expected" and "actual" don't match.
|
||||||
* When "argidx" > 0 it is included in the error message.
|
* When "argidx" > 0 it is included in the error message.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
check_typval_type(type_T *expected, typval_T *actual_tv, int argidx)
|
check_typval_type(type_T *expected, typval_T *actual_tv, where_T where)
|
||||||
{
|
{
|
||||||
garray_T type_list;
|
garray_T type_list;
|
||||||
type_T *actual_type;
|
type_T *actual_type;
|
||||||
@@ -414,7 +423,7 @@ check_typval_type(type_T *expected, typval_T *actual_tv, int argidx)
|
|||||||
ga_init2(&type_list, sizeof(type_T *), 10);
|
ga_init2(&type_list, sizeof(type_T *), 10);
|
||||||
actual_type = typval2type(actual_tv, &type_list);
|
actual_type = typval2type(actual_tv, &type_list);
|
||||||
if (actual_type != NULL)
|
if (actual_type != NULL)
|
||||||
res = check_type(expected, actual_type, TRUE, argidx);
|
res = check_type(expected, actual_type, TRUE, where);
|
||||||
clear_type_list(&type_list);
|
clear_type_list(&type_list);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -426,15 +435,29 @@ type_mismatch(type_T *expected, type_T *actual)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
|
arg_type_mismatch(type_T *expected, type_T *actual, int arg_idx)
|
||||||
|
{
|
||||||
|
where_T where;
|
||||||
|
|
||||||
|
where.wt_index = arg_idx;
|
||||||
|
where.wt_variable = FALSE;
|
||||||
|
type_mismatch_where(expected, actual, where);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
type_mismatch_where(type_T *expected, type_T *actual, where_T where)
|
||||||
{
|
{
|
||||||
char *tofree1, *tofree2;
|
char *tofree1, *tofree2;
|
||||||
char *typename1 = type_name(expected, &tofree1);
|
char *typename1 = type_name(expected, &tofree1);
|
||||||
char *typename2 = type_name(actual, &tofree2);
|
char *typename2 = type_name(actual, &tofree2);
|
||||||
|
|
||||||
if (argidx > 0)
|
if (where.wt_index > 0)
|
||||||
semsg(_(e_argument_nr_type_mismatch_expected_str_but_got_str),
|
{
|
||||||
argidx, typename1, typename2);
|
semsg(_(where.wt_variable
|
||||||
|
? e_variable_nr_type_mismatch_expected_str_but_got_str
|
||||||
|
: e_argument_nr_type_mismatch_expected_str_but_got_str),
|
||||||
|
where.wt_index, typename1, typename2);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
semsg(_(e_type_mismatch_expected_str_but_got_str),
|
semsg(_(e_type_mismatch_expected_str_but_got_str),
|
||||||
typename1, typename2);
|
typename1, typename2);
|
||||||
@@ -448,7 +471,7 @@ arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
|
|||||||
* When "argidx" > 0 it is included in the error message.
|
* When "argidx" > 0 it is included in the error message.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
check_type(type_T *expected, type_T *actual, int give_msg, int argidx)
|
check_type(type_T *expected, type_T *actual, int give_msg, where_T where)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
@@ -469,7 +492,7 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx)
|
|||||||
// Using number 0 or 1 for bool is OK.
|
// Using number 0 or 1 for bool is OK.
|
||||||
return OK;
|
return OK;
|
||||||
if (give_msg)
|
if (give_msg)
|
||||||
arg_type_mismatch(expected, actual, argidx);
|
type_mismatch_where(expected, actual, where);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
|
if (expected->tt_type == VAR_DICT || expected->tt_type == VAR_LIST)
|
||||||
@@ -477,7 +500,7 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx)
|
|||||||
// "unknown" is used for an empty list or dict
|
// "unknown" is used for an empty list or dict
|
||||||
if (actual->tt_member != &t_unknown)
|
if (actual->tt_member != &t_unknown)
|
||||||
ret = check_type(expected->tt_member, actual->tt_member,
|
ret = check_type(expected->tt_member, actual->tt_member,
|
||||||
FALSE, 0);
|
FALSE, where);
|
||||||
}
|
}
|
||||||
else if (expected->tt_type == VAR_FUNC)
|
else if (expected->tt_type == VAR_FUNC)
|
||||||
{
|
{
|
||||||
@@ -486,7 +509,7 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx)
|
|||||||
if (expected->tt_member != &t_unknown
|
if (expected->tt_member != &t_unknown
|
||||||
&& actual->tt_member != &t_unknown)
|
&& actual->tt_member != &t_unknown)
|
||||||
ret = check_type(expected->tt_member, actual->tt_member,
|
ret = check_type(expected->tt_member, actual->tt_member,
|
||||||
FALSE, 0);
|
FALSE, where);
|
||||||
if (ret == OK && expected->tt_argcount != -1
|
if (ret == OK && expected->tt_argcount != -1
|
||||||
&& actual->tt_argcount != -1
|
&& actual->tt_argcount != -1
|
||||||
&& (actual->tt_argcount < expected->tt_min_argcount
|
&& (actual->tt_argcount < expected->tt_min_argcount
|
||||||
@@ -500,8 +523,8 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx)
|
|||||||
for (i = 0; i < expected->tt_argcount; ++i)
|
for (i = 0; i < expected->tt_argcount; ++i)
|
||||||
// Allow for using "any" argument type, lambda's have them.
|
// Allow for using "any" argument type, lambda's have them.
|
||||||
if (actual->tt_args[i] != &t_any && check_type(
|
if (actual->tt_args[i] != &t_any && check_type(
|
||||||
expected->tt_args[i], actual->tt_args[i], FALSE, 0)
|
expected->tt_args[i], actual->tt_args[i], FALSE,
|
||||||
== FAIL)
|
where) == FAIL)
|
||||||
{
|
{
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
break;
|
break;
|
||||||
@@ -509,7 +532,7 @@ check_type(type_T *expected, type_T *actual, int give_msg, int argidx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret == FAIL && give_msg)
|
if (ret == FAIL && give_msg)
|
||||||
arg_type_mismatch(expected, actual, argidx);
|
type_mismatch_where(expected, actual, where);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -552,7 +575,7 @@ check_argument_types(
|
|||||||
expected = type->tt_args[type->tt_argcount - 1]->tt_member;
|
expected = type->tt_args[type->tt_argcount - 1]->tt_member;
|
||||||
else
|
else
|
||||||
expected = type->tt_args[i];
|
expected = type->tt_args[i];
|
||||||
if (check_typval_type(expected, &argvars[i], i + 1) == FAIL)
|
if (check_typval_arg_type(expected, &argvars[i], i + 1) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
|
Reference in New Issue
Block a user