comparison src/vim9type.c @ 26925:4e77f9961650 v8.2.3991

patch 8.2.3991: Vim9: error when extending dict<any> Commit: https://github.com/vim/vim/commit/114dbda7858df956161c0adba5d4d8279645ff67 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jan 3 12:28:03 2022 +0000 patch 8.2.3991: Vim9: error when extending dict<any> Problem: Vim9: error when extending dict<any> with another type that it was initialized with. Solution: Also set the type for dict<any> if the initializer has a more specific type. (closes #9461)
author Bram Moolenaar <Bram@vim.org>
date Mon, 03 Jan 2022 13:30:04 +0100
parents eb6d56ab4858
children ccb9be1cdd71
comparison
equal deleted inserted replaced
26924:9a1e933647aa 26925:4e77f9961650
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 * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use
256 * "any".
257 * When "flags" has TVTT_MORE_SPECIFIC get the more specific member type if it
258 * is "any".
256 */ 259 */
257 static type_T * 260 static type_T *
258 typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int do_member) 261 typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags)
259 { 262 {
260 type_T *type; 263 type_T *type;
261 type_T *member_type = NULL; 264 type_T *member_type = NULL;
262 int argcount = 0; 265 int argcount = 0;
263 int min_argcount = 0; 266 int min_argcount = 0;
276 list_T *l = tv->vval.v_list; 279 list_T *l = tv->vval.v_list;
277 listitem_T *li; 280 listitem_T *li;
278 281
279 if (l == NULL || (l->lv_first == NULL && l->lv_type == NULL)) 282 if (l == NULL || (l->lv_first == NULL && l->lv_type == NULL))
280 return &t_list_empty; 283 return &t_list_empty;
281 if (!do_member) 284 if ((flags & TVTT_DO_MEMBER) == 0)
282 return &t_list_any; 285 return &t_list_any;
283 if (l->lv_type != NULL) 286 // If the type is list<any> go through the members, it may end up a
287 // more specific type.
288 if (l->lv_type != NULL && (l->lv_first == NULL
289 || (flags & TVTT_MORE_SPECIFIC) == 0
290 || l->lv_type->tt_member != &t_any))
284 return l->lv_type; 291 return l->lv_type;
285 if (l->lv_first == &range_list_item) 292 if (l->lv_first == &range_list_item)
286 return &t_list_number; 293 return &t_list_number;
287 if (l->lv_copyID == copyID) 294 if (l->lv_copyID == copyID)
288 // avoid recursion 295 // avoid recursion
289 return &t_list_any; 296 return &t_list_any;
290 l->lv_copyID = copyID; 297 l->lv_copyID = copyID;
291 298
292 // Use the common type of all members. 299 // Use the common type of all members.
293 member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap, TRUE); 300 member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap,
301 TVTT_DO_MEMBER);
294 for (li = l->lv_first->li_next; li != NULL; li = li->li_next) 302 for (li = l->lv_first->li_next; li != NULL; li = li->li_next)
295 common_type(typval2type(&li->li_tv, copyID, type_gap, TRUE), 303 common_type(typval2type(&li->li_tv, copyID, type_gap,
304 TVTT_DO_MEMBER),
296 member_type, &member_type, type_gap); 305 member_type, &member_type, type_gap);
297 return get_list_type(member_type, type_gap); 306 return get_list_type(member_type, type_gap);
298 } 307 }
299 308
300 if (tv->v_type == VAR_DICT) 309 if (tv->v_type == VAR_DICT)
303 typval_T *value; 312 typval_T *value;
304 dict_T *d = tv->vval.v_dict; 313 dict_T *d = tv->vval.v_dict;
305 314
306 if (d == NULL || (d->dv_hashtab.ht_used == 0 && d->dv_type == NULL)) 315 if (d == NULL || (d->dv_hashtab.ht_used == 0 && d->dv_type == NULL))
307 return &t_dict_empty; 316 return &t_dict_empty;
308 if (!do_member) 317 if ((flags & TVTT_DO_MEMBER) == 0)
309 return &t_dict_any; 318 return &t_dict_any;
310 if (d->dv_type != NULL) 319 // If the type is dict<any> go through the members, it may end up a
320 // more specific type.
321 if (d->dv_type != NULL && (d->dv_hashtab.ht_used == 0
322 || (flags & TVTT_MORE_SPECIFIC) == 0
323 || d->dv_type->tt_member != &t_any))
311 return d->dv_type; 324 return d->dv_type;
312 if (d->dv_copyID == copyID) 325 if (d->dv_copyID == copyID)
313 // avoid recursion 326 // avoid recursion
314 return &t_dict_any; 327 return &t_dict_any;
315 d->dv_copyID = copyID; 328 d->dv_copyID = copyID;
316 329
317 // Use the common type of all values. 330 // Use the common type of all values.
318 dict_iterate_start(tv, &iter); 331 dict_iterate_start(tv, &iter);
319 dict_iterate_next(&iter, &value); 332 dict_iterate_next(&iter, &value);
320 member_type = typval2type(value, copyID, type_gap, TRUE); 333 member_type = typval2type(value, copyID, type_gap, TVTT_DO_MEMBER);
321 while (dict_iterate_next(&iter, &value) != NULL) 334 while (dict_iterate_next(&iter, &value) != NULL)
322 common_type(typval2type(value, copyID, type_gap, TRUE), 335 common_type(typval2type(value, copyID, type_gap, TVTT_DO_MEMBER),
323 member_type, &member_type, type_gap); 336 member_type, &member_type, type_gap);
324 return get_dict_type(member_type, type_gap); 337 return get_dict_type(member_type, type_gap);
325 } 338 }
326 339
327 if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) 340 if (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
422 } 435 }
423 436
424 /* 437 /*
425 * Get a type_T for a typval_T. 438 * Get a type_T for a typval_T.
426 * "type_list" is used to temporarily create types in. 439 * "type_list" is used to temporarily create types in.
427 * When "do_member" is TRUE also get the member type, otherwise use "any". 440 * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use
441 * "any".
442 * When "flags" has TVTT_MORE_SPECIFIC get the most specific member type.
428 */ 443 */
429 type_T * 444 type_T *
430 typval2type(typval_T *tv, int copyID, garray_T *type_gap, int do_member) 445 typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags)
431 { 446 {
432 type_T *type = typval2type_int(tv, copyID, type_gap, do_member); 447 type_T *type = typval2type_int(tv, copyID, type_gap, flags);
433 448
434 if (type != NULL && type != &t_bool 449 if (type != NULL && type != &t_bool
435 && (tv->v_type == VAR_NUMBER 450 && (tv->v_type == VAR_NUMBER
436 && (tv->vval.v_number == 0 || tv->vval.v_number == 1))) 451 && (tv->vval.v_number == 0 || tv->vval.v_number == 1)))
437 // Number 0 and 1 and expression with "&&" or "||" can also be used for 452 // Number 0 and 1 and expression with "&&" or "||" can also be used for
449 { 464 {
450 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles 465 if (tv->v_type == VAR_LIST) // e.g. for v:oldfiles
451 return &t_list_string; 466 return &t_list_string;
452 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item 467 if (tv->v_type == VAR_DICT) // e.g. for v:completed_item
453 return &t_dict_any; 468 return &t_dict_any;
454 return typval2type(tv, get_copyID(), type_gap, TRUE); 469 return typval2type(tv, get_copyID(), type_gap, TVTT_DO_MEMBER);
455 } 470 }
456 471
457 int 472 int
458 check_typval_arg_type( 473 check_typval_arg_type(
459 type_T *expected, 474 type_T *expected,
491 emsg(_(e_function_reference_is_not_set)); 506 emsg(_(e_function_reference_is_not_set));
492 return FAIL; 507 return FAIL;
493 } 508 }
494 509
495 ga_init2(&type_list, sizeof(type_T *), 10); 510 ga_init2(&type_list, sizeof(type_T *), 10);
496 actual_type = typval2type(actual_tv, get_copyID(), &type_list, TRUE); 511
512 // When the actual type is list<any> or dict<any> go through the values to
513 // possibly get a more specific type.
514 actual_type = typval2type(actual_tv, get_copyID(), &type_list,
515 TVTT_DO_MEMBER | TVTT_MORE_SPECIFIC);
497 if (actual_type != NULL) 516 if (actual_type != NULL)
498 { 517 {
499 res = check_type_maybe(expected, actual_type, TRUE, where); 518 res = check_type_maybe(expected, actual_type, TRUE, where);
500 if (res == MAYBE && !(actual_type->tt_type == VAR_FUNC 519 if (res == MAYBE && !(actual_type->tt_type == VAR_FUNC
501 && actual_type->tt_member == &t_unknown)) 520 && actual_type->tt_member == &t_unknown))
1344 char *tofree; 1363 char *tofree;
1345 char *name; 1364 char *name;
1346 1365
1347 rettv->v_type = VAR_STRING; 1366 rettv->v_type = VAR_STRING;
1348 ga_init2(&type_list, sizeof(type_T *), 10); 1367 ga_init2(&type_list, sizeof(type_T *), 10);
1349 type = typval2type(argvars, get_copyID(), &type_list, TRUE); 1368 type = typval2type(argvars, get_copyID(), &type_list, TVTT_DO_MEMBER);
1350 name = type_name(type, &tofree); 1369 name = type_name(type, &tofree);
1351 if (tofree != NULL) 1370 if (tofree != NULL)
1352 rettv->vval.v_string = (char_u *)tofree; 1371 rettv->vval.v_string = (char_u *)tofree;
1353 else 1372 else
1354 { 1373 {