Check if this is a well-formed instance with respect to argument count/positions.
(t: Instance, fail: MsgCallback, indexed: bool)
| 2466 | |
| 2467 | |
| 2468 | def validate_instance(t: Instance, fail: MsgCallback, indexed: bool) -> bool: |
| 2469 | """Check if this is a well-formed instance with respect to argument count/positions.""" |
| 2470 | # TODO: combine logic with instantiate_type_alias(). |
| 2471 | if any(unknown_unpack(a) for a in t.args): |
| 2472 | # This type is not ready to be validated, because of unknown total count. |
| 2473 | # TODO: is it OK to fill with TypeOfAny.from_error instead of special form? |
| 2474 | return False |
| 2475 | empty_tuple_index = indexed and not t.args |
| 2476 | if t.type.has_type_var_tuple_type: |
| 2477 | min_tv_count = sum( |
| 2478 | not tv.has_default() and not isinstance(tv, TypeVarTupleType) |
| 2479 | for tv in t.type.defn.type_vars |
| 2480 | ) |
| 2481 | correct = len(t.args) >= min_tv_count |
| 2482 | if any( |
| 2483 | isinstance(a, UnpackType) and isinstance(get_proper_type(a.type), Instance) |
| 2484 | for a in t.args |
| 2485 | ): |
| 2486 | correct = True |
| 2487 | if not t.args: |
| 2488 | if not (empty_tuple_index and len(t.type.type_vars) == 1): |
| 2489 | # The Any arguments should be set by the caller. |
| 2490 | if empty_tuple_index and min_tv_count: |
| 2491 | fail( |
| 2492 | f"At least {min_tv_count} type argument(s) expected, none given", |
| 2493 | t, |
| 2494 | code=codes.TYPE_ARG, |
| 2495 | ) |
| 2496 | return False |
| 2497 | elif not correct: |
| 2498 | fail( |
| 2499 | f"Bad number of arguments, expected: at least {min_tv_count}, given: {len(t.args)}", |
| 2500 | t, |
| 2501 | code=codes.TYPE_ARG, |
| 2502 | ) |
| 2503 | return False |
| 2504 | else: |
| 2505 | # We also need to check if we are not performing a type variable tuple split. |
| 2506 | unpack = find_unpack_in_list(t.args) |
| 2507 | if unpack is not None: |
| 2508 | unpack_arg = t.args[unpack] |
| 2509 | assert isinstance(unpack_arg, UnpackType) |
| 2510 | if isinstance(unpack_arg.type, TypeVarTupleType): |
| 2511 | assert t.type.type_var_tuple_prefix is not None |
| 2512 | assert t.type.type_var_tuple_suffix is not None |
| 2513 | exp_prefix = t.type.type_var_tuple_prefix |
| 2514 | act_prefix = unpack |
| 2515 | exp_suffix = t.type.type_var_tuple_suffix |
| 2516 | act_suffix = len(t.args) - unpack - 1 |
| 2517 | if act_prefix < exp_prefix or act_suffix < exp_suffix: |
| 2518 | fail("TypeVarTuple cannot be split", t, code=codes.TYPE_ARG) |
| 2519 | return False |
| 2520 | elif any(isinstance(a, UnpackType) for a in t.args): |
| 2521 | # A variadic unpack in fixed size instance (fixed unpacks must be flattened by the caller) |
| 2522 | fail(message_registry.INVALID_UNPACK_POSITION, t, code=codes.VALID_TYPE) |
| 2523 | t.args = () |
| 2524 | return False |
| 2525 | elif len(t.args) != len(t.type.type_vars): |
no test coverage detected
searching dependent graphs…