-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[red-knot] Add diagnostic for invalid unpacking (#15086)
## Summary Part of #13773 This PR adds diagnostics when there is a length mismatch during unpacking between the number of target expressions and the number of types for the unpack value expression. There are 3 cases of diagnostics here where the first two occurs when there isn't a starred expression and the last one occurs when there's a starred expression: 1. Number of target expressions is **less** than the number of types that needs to be unpacked 2. Number of target expressions is **greater** then the number of types that needs to be unpacked 3. When there's a starred expression as one of the target expression and the number of target expressions is greater than the number of types Examples for all each of the above cases: ```py # red-knot: Too many values to unpack (expected 2, got 3) [lint:invalid-assignment] a, b = (1, 2, 3) # red-knot: Not enough values to unpack (expected 2, got 1) [lint:invalid-assignment] a, b = (1,) # red-knot: Not enough values to unpack (expected 3 or more, got 2) [lint:invalid-assignment] a, *b, c, d = (1, 2) ``` The (3) case is a bit special because it uses a distinct wording "expected n or more" instead of "expected n" because of the starred expression. ### Location The diagnostic location is the target expression that's being unpacked. For nested targets, the location will be the nested expression. For example: ```py (a, (b, c), d) = (1, (2, 3, 4), 5) # ^^^^^^ # red-knot: Too many values to unpack (expected 2, got 3) [lint:invalid-assignment] ``` For future improvements, it would be useful to show the context for why this unpacking failed. For example, for why the expected number of targets is `n`, we can highlight the relevant elements for the value expression. In the **ecosystem**, **Pyright** uses the target expressions for location while **mypy** uses the value expression for the location. For example: ```py if 1: # mypy: Too many values to unpack (2 expected, 3 provided) [misc] # vvvvvvvvv a, b = (1, 2, 3) # ^^^^ # Pyright: Expression with type "tuple[Literal[1], Literal[2], Literal[3]]" cannot be assigned to target tuple # Type "tuple[Literal[1], Literal[2], Literal[3]]" is incompatible with target tuple # Tuple size mismatch; expected 2 but received 3 [reportAssignmentType] # red-knot: Too many values to unpack (expected 2, got 3) [lint:invalid-assignment] ``` ## Test Plan Update existing test cases TODO with the error directives.
- Loading branch information
1 parent
901b7dd
commit 8a98d88
Showing
3 changed files
with
81 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters