comparison src/vim9type.c @ 24438:5c6ccab68d1e v8.2.2759

patch 8.2.2759: Vim9: for loop infers type of loop variable Commit: https://github.com/vim/vim/commit/f2253963c28e4791092620df6a6bb238c33168df Author: Bram Moolenaar <Bram@vim.org> Date: Tue Apr 13 20:53:13 2021 +0200 patch 8.2.2759: Vim9: for loop infers type of loop variable Problem: Vim9: for loop infers type of loop variable. Solution: Do not get the member type. (closes https://github.com/vim/vim/issues/8102)
author Bram Moolenaar <Bram@vim.org>
date Tue, 13 Apr 2021 21:00:05 +0200
parents e695db9a5465
children a4fda40e0bb9
comparison
equal deleted inserted replaced
24437:c63e5ce43b69 24438:5c6ccab68d1e
250 } 250 }
251 251
252 /* 252 /*
253 * Get a type_T for a typval_T. 253 * Get a type_T for a typval_T.
254 * "type_gap" is used to temporarily create types in. 254 * "type_gap" is used to temporarily create types in.
255 * When "do_member" is TRUE also get the member type, otherwise use "any".
255 */ 256 */
256 static type_T * 257 static type_T *
257 typval2type_int(typval_T *tv, int copyID, garray_T *type_gap) 258 typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int do_member)
258 { 259 {
259 type_T *type; 260 type_T *type;
260 type_T *member_type = &t_any; 261 type_T *member_type = &t_any;
261 int argcount = 0; 262 int argcount = 0;
262 263
272 list_T *l = tv->vval.v_list; 273 list_T *l = tv->vval.v_list;
273 listitem_T *li; 274 listitem_T *li;
274 275
275 if (l == NULL || l->lv_first == NULL) 276 if (l == NULL || l->lv_first == NULL)
276 return &t_list_empty; 277 return &t_list_empty;
278 if (!do_member)
279 return &t_list_any;
277 if (l->lv_first == &range_list_item) 280 if (l->lv_first == &range_list_item)
278 return &t_list_number; 281 return &t_list_number;
279 if (l->lv_copyID == copyID) 282 if (l->lv_copyID == copyID)
280 // avoid recursion 283 // avoid recursion
281 return &t_list_any; 284 return &t_list_any;
282 l->lv_copyID = copyID; 285 l->lv_copyID = copyID;
283 286
284 // Use the common type of all members. 287 // Use the common type of all members.
285 member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap); 288 member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap, TRUE);
286 for (li = l->lv_first->li_next; li != NULL; li = li->li_next) 289 for (li = l->lv_first->li_next; li != NULL; li = li->li_next)
287 common_type(typval2type(&li->li_tv, copyID, type_gap), 290 common_type(typval2type(&li->li_tv, copyID, type_gap, TRUE),
288 member_type, &member_type, type_gap); 291 member_type, &member_type, type_gap);
289 return get_list_type(member_type, type_gap); 292 return get_list_type(member_type, type_gap);
290 } 293 }
291 294
292 if (tv->v_type == VAR_DICT) 295 if (tv->v_type == VAR_DICT)
295 typval_T *value; 298 typval_T *value;
296 dict_T *d = tv->vval.v_dict; 299 dict_T *d = tv->vval.v_dict;
297 300
298 if (d == NULL || d->dv_hashtab.ht_used == 0) 301 if (d == NULL || d->dv_hashtab.ht_used == 0)
299 return &t_dict_empty; 302 return &t_dict_empty;
303 if (!do_member)
304 return &t_dict_any;
300 if (d->dv_copyID == copyID) 305 if (d->dv_copyID == copyID)
301 // avoid recursion 306 // avoid recursion
302 return &t_dict_any; 307 return &t_dict_any;
303 d->dv_copyID = copyID; 308 d->dv_copyID = copyID;
304 309
305 // Use the common type of all values. 310 // Use the common type of all values.
306 dict_iterate_start(tv, &iter); 311 dict_iterate_start(tv, &iter);
307 dict_iterate_next(&iter, &value); 312 dict_iterate_next(&iter, &value);
308 member_type = typval2type(value, copyID, type_gap); 313 member_type = typval2type(value, copyID, type_gap, TRUE);
309 while (dict_iterate_next(&iter, &value) != NULL) 314 while (dict_iterate_next(&iter, &value) != NULL)
310 common_type(typval2type(value, copyID, type_gap), 315 common_type(typval2type(value, copyID, type_gap, TRUE),
311 member_type, &member_type, type_gap); 316 member_type, &member_type, type_gap);
312 return get_dict_type(member_type, type_gap); 317 return get_dict_type(member_type, type_gap);
313 } 318 }
314 319
315 if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) 320 if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
376 } 381 }
377 382
378 /* 383 /*
379 * Get a type_T for a typval_T. 384 * Get a type_T for a typval_T.
380 * "type_list" is used to temporarily create types in. 385 * "type_list" is used to temporarily create types in.
386 * When "do_member" is TRUE also get the member type, otherwise use "any".
381 */ 387 */
382 type_T * 388 type_T *
383 typval2type(typval_T *tv, int copyID, garray_T *type_gap) 389 typval2type(typval_T *tv, int copyID, garray_T *type_gap, int do_member)
384 { 390 {
385 type_T *type = typval2type_int(tv, copyID, type_gap); 391 type_T *type = typval2type_int(tv, copyID, type_gap, do_member);
386 392
387 if (type != NULL && type != &t_bool 393 if (type != NULL && type != &t_bool
388 && (tv->v_type == VAR_NUMBER 394 && (tv->v_type == VAR_NUMBER
389 && (tv->vval.v_number == 0 || tv->vval.v_number == 1))) 395 && (tv->vval.v_number == 0 || tv->vval.v_number == 1)))
390 // Number 0 and 1 and expression with "&&" or "||" can also be used for 396 // Number 0 and 1 and expression with "&&" or "||" can also be used for
402 { 408 {
403 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles 409 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
404 return &t_list_string; 410 return &t_list_string;
405 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item 411 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
406 return &t_dict_any; 412 return &t_dict_any;
407 return typval2type(tv, get_copyID(), type_gap); 413 return typval2type(tv, get_copyID(), type_gap, TRUE);
408 } 414 }
409 415
410 int 416 int
411 check_typval_arg_type(type_T *expected, typval_T *actual_tv, int arg_idx) 417 check_typval_arg_type(type_T *expected, typval_T *actual_tv, int arg_idx)
412 { 418 {
427 garray_T type_list; 433 garray_T type_list;
428 type_T *actual_type; 434 type_T *actual_type;
429 int res = FAIL; 435 int res = FAIL;
430 436
431 ga_init2(&type_list, sizeof(type_T *), 10); 437 ga_init2(&type_list, sizeof(type_T *), 10);
432 actual_type = typval2type(actual_tv, get_copyID(), &type_list); 438 actual_type = typval2type(actual_tv, get_copyID(), &type_list, TRUE);
433 if (actual_type != NULL) 439 if (actual_type != NULL)
434 res = check_type(expected, actual_type, TRUE, where); 440 res = check_type(expected, actual_type, TRUE, where);
435 clear_type_list(&type_list); 441 clear_type_list(&type_list);
436 return res; 442 return res;
437 } 443 }
1208 char *tofree; 1214 char *tofree;
1209 char *name; 1215 char *name;
1210 1216
1211 rettv->v_type = VAR_STRING; 1217 rettv->v_type = VAR_STRING;
1212 ga_init2(&type_list, sizeof(type_T *), 10); 1218 ga_init2(&type_list, sizeof(type_T *), 10);
1213 type = typval2type(argvars, get_copyID(), &type_list); 1219 type = typval2type(argvars, get_copyID(), &type_list, TRUE);
1214 name = type_name(type, &tofree); 1220 name = type_name(type, &tofree);
1215 if (tofree != NULL) 1221 if (tofree != NULL)
1216 rettv->vval.v_string = (char_u *)tofree; 1222 rettv->vval.v_string = (char_u *)tofree;
1217 else 1223 else
1218 { 1224 {