Mercurial > vim
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 { |