Commit d2f1d34
authored
Optionally allow redefinition of variable with different type (#6197)
If the flag `--allow-redefinition` is used, it's now possible to redefine a
variable with a different type. For example, this code will be okay:
```
x = 0 # Define 'x' with type 'int'
print(x)
x = 'a' # Define another 'x' with type 'str'
print(x)
```
The variable needs to be read before redefinition is possible. This is mainly
to allow these idioms:
```
x: List[int]
x = [] # Not a redefinition
y = None # type: List[int] # Strict optional disabled
y = [] # Not a redefinition
```
It's also okay to use a type annotation in any of the assignments. This is
fine:
```
x: int = 0
print(x)
x: str = 'a'
print(x)
```
Redefinition is only allowed to happen in the same block and the nesting level
as the original definition. This lets us keep the implementation relatively simple,
and there will hopefully be less of a readability impact, since it's less likely that
users accidentally redefine a variable or use redefinition in confusing ways. We
may want to lift the restriction in the future, however. Function arguments can
be redefined in the body but only in non-nested blocks.
The implementation does a simple static analysis to rename variables to make
them distinct when we detect redefinition. This happens before semantic
analysis pass 1.
The new behavior is not fully backward compatible with the old behavior. For
example, here we lose type context in the second assignment:
```
x: List[int] = []
f(x)
x = [] # Need type annotation since this creates an independent variable
```
Internally we use a sequence of single quotes as a variable suffix
to represent renamed variants. The implementation provides an `unmangle()`
function to get the original name from a potentially mangled name.
It's still impossible to redefine final names, classes and certain other things.
The main use case is simple variables, either in single or multiple assignments.
I did some benchmarking (not with the latest version though) and the performance
impact of the new pass was minor (under 2% IIRC).
Things to do in additional PRs:
* Add documentation.
* Make sure we unmangle names everywhere.
* Consider allowing redefinition to happen sometimes in another block.
* Consider propagating type context from original definition.1 parent d5cf72b commit d2f1d34
File tree
20 files changed
+1315
-170
lines changed- mypy
- plugins
- test
- test-data/unit
20 files changed
+1315
-170
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
895 | 896 | | |
896 | 897 | | |
897 | 898 | | |
898 | | - | |
899 | | - | |
900 | | - | |
901 | | - | |
902 | | - | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
523 | 523 | | |
524 | 524 | | |
525 | 525 | | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
526 | 530 | | |
527 | 531 | | |
528 | 532 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
32 | 33 | | |
33 | 34 | | |
34 | 35 | | |
| |||
952 | 953 | | |
953 | 954 | | |
954 | 955 | | |
955 | | - | |
| 956 | + | |
956 | 957 | | |
957 | 958 | | |
958 | 959 | | |
| |||
1064 | 1065 | | |
1065 | 1066 | | |
1066 | 1067 | | |
1067 | | - | |
| 1068 | + | |
1068 | 1069 | | |
1069 | 1070 | | |
1070 | 1071 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
924 | 924 | | |
925 | 925 | | |
926 | 926 | | |
927 | | - | |
| 927 | + | |
| 928 | + | |
928 | 929 | | |
929 | 930 | | |
930 | | - | |
| 931 | + | |
| 932 | + | |
931 | 933 | | |
932 | | - | |
| 934 | + | |
933 | 935 | | |
934 | 936 | | |
935 | 937 | | |
| 938 | + | |
936 | 939 | | |
937 | 940 | | |
938 | 941 | | |
| |||
2968 | 2971 | | |
2969 | 2972 | | |
2970 | 2973 | | |
| 2974 | + | |
| 2975 | + | |
| 2976 | + | |
| 2977 | + | |
| 2978 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
| |||
149 | 150 | | |
150 | 151 | | |
151 | 152 | | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
152 | 157 | | |
153 | 158 | | |
154 | 159 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
376 | 377 | | |
377 | 378 | | |
378 | 379 | | |
| 380 | + | |
379 | 381 | | |
380 | 382 | | |
381 | | - | |
| 383 | + | |
382 | 384 | | |
383 | 385 | | |
384 | 386 | | |
| |||
443 | 445 | | |
444 | 446 | | |
445 | 447 | | |
446 | | - | |
| 448 | + | |
| 449 | + | |
447 | 450 | | |
448 | 451 | | |
449 | 452 | | |
| |||
0 commit comments