Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optionally allow redefinition of variable with different type #6197

Merged
merged 56 commits into from
Jan 21, 2019
Merged
Changes from 1 commit
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
8e49664
Support redefinition of local variables with a different type
JukkaL Sep 20, 2018
3b409fc
Add docstring
JukkaL Sep 20, 2018
71cb8ea
Allow redefinitions of form "x = f(x)"
JukkaL Sep 20, 2018
35f56ae
Fix special cases
JukkaL Sep 20, 2018
2524777
Add test cases
JukkaL Sep 20, 2018
ab70d0d
Fix redefinition with 'break' and 'continue'
JukkaL Sep 20, 2018
525d5f4
Fix issues
JukkaL Sep 20, 2018
2c614a2
Fix some edge cases
JukkaL Sep 20, 2018
bf2f869
Support top-level redefinition through renaming (WIP)
JukkaL Sep 28, 2018
9e2c6b8
Remove obsolete code
JukkaL Sep 28, 2018
2b885da
Cleanup
JukkaL Sep 28, 2018
712669c
Merge transform code into a single class
JukkaL Sep 28, 2018
e0b7df0
Code cleanup
JukkaL Sep 28, 2018
f153809
Fix issues
JukkaL Sep 28, 2018
856d401
Fix issues
JukkaL Sep 28, 2018
865f1dd
Work around type check error
JukkaL Sep 28, 2018
2deff14
Merge branch 'master' into redefine-var
JukkaL Oct 4, 2018
27a1e57
Fix merge issue
JukkaL Oct 4, 2018
f04e37a
Fix lint
JukkaL Oct 4, 2018
1f9f62e
Fix more tests
JukkaL Oct 4, 2018
9ba82a9
Rename semanal_redef -> renaming
JukkaL Oct 4, 2018
fbf052e
Only perform redefinition if variable has been read
JukkaL Oct 9, 2018
1116b47
A few fixes
JukkaL Oct 9, 2018
70a3085
Add hacky workaround for 'self'
JukkaL Oct 9, 2018
cfad560
Merge branch 'master' into redefine-var
JukkaL Oct 9, 2018
b57960b
Remove unused things
JukkaL Oct 10, 2018
580a774
Revert some unnecessary changes
JukkaL Oct 10, 2018
051e695
Merge commit '3bea26f89a66834f42caaa90cf8db44f99d39dcc' into redefine…
JukkaL Dec 9, 2018
77495fb
Merge branch 'master' into redefine-var
JukkaL Dec 9, 2018
dc03143
Fix test case
JukkaL Dec 9, 2018
4ceed87
Merge branch 'master' into redefine-var
JukkaL Dec 19, 2018
ac00e6d
Merge branch 'master' into redefine-var
JukkaL Dec 20, 2018
20fd0f9
Use `if int():` consistently
JukkaL Dec 20, 2018
3843cea
Fix some test cases
JukkaL Dec 20, 2018
5cfaf9c
Add flag for allowing redefinitions
JukkaL Dec 20, 2018
83ba85f
Use the flag
JukkaL Dec 20, 2018
43a0362
Fix tests
JukkaL Dec 20, 2018
59b3413
Fix test cases
JukkaL Dec 20, 2018
7e3eff9
Add test case for turning flag off explicitly
JukkaL Dec 20, 2018
afa1096
Rename flag to --[dis]allow-redefinition (no plural)
JukkaL Dec 20, 2018
916288c
Fix semantic analyzer tests
JukkaL Dec 21, 2018
459187e
Update test case
JukkaL Dec 21, 2018
e165e46
Merge branch 'master' into redefine-var
JukkaL Jan 15, 2019
0a119b3
Merge branch 'master' into redefine-var
JukkaL Jan 15, 2019
fadb322
Merge branch 'master' into redefine-var
JukkaL Jan 17, 2019
76ad071
Fix brokenness from merge
JukkaL Jan 17, 2019
979a17c
Respond to review
JukkaL Jan 18, 2019
ae0043f
Clarify code
JukkaL Jan 18, 2019
512c1ed
Test additional special case
JukkaL Jan 18, 2019
1f7e36d
Add test case
JukkaL Jan 18, 2019
72043ae
Fix with statements
JukkaL Jan 18, 2019
8c30c90
Remove unnecessary check
JukkaL Jan 18, 2019
e390f38
Add comment
JukkaL Jan 18, 2019
bc0ee19
Ensure renaming cannot happen across scopes in class
JukkaL Jan 18, 2019
54b86d8
Remove unnecessary call
JukkaL Jan 18, 2019
496d2dd
The final assignments takes precedence in class when renaming
JukkaL Jan 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
A few fixes
  • Loading branch information
JukkaL committed Oct 9, 2018
commit 1116b477ee1030af9981e1251fd437db53bb6a78
3 changes: 2 additions & 1 deletion mypy/renaming.py
Original file line number Diff line number Diff line change
@@ -165,7 +165,7 @@ def analyze_lvalue(self, lvalue: Lvalue, is_nested: bool = False) -> None:
lvalue.base.accept(self)
lvalue.index.accept(self)
elif isinstance(lvalue, StarExpr):
self.analyze_lvalue(lvalue.expr)
self.analyze_lvalue(lvalue.expr, is_nested=is_nested)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explain that we pass is_nested=is_nested because a typical use case is x, y, *rest = stuff (rest may be reused).


def visit_name_expr(self, expr: NameExpr) -> None:
self.handle_ref(expr)
@@ -176,6 +176,7 @@ def handle_arg(self, name: str) -> None:
"""Store function argument."""
if name not in self.refs[-1]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I am missing something, but why do we need this check? Shouldn't all function arguments have unique names?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the check.

self.refs[-1][name] = [[]]
self.num_reads[-1][name] = 0

def handle_def(self, expr: NameExpr) -> None:
"""Store new name definition."""
8 changes: 4 additions & 4 deletions test-data/unit/check-final.test
Original file line number Diff line number Diff line change
@@ -352,15 +352,15 @@ def f2() -> None:
global x2
x2 = 1 # E: Cannot assign to final name "x2"

y = 1 # E: Cannot asign to final name "y"
y = 1
y
y: Final = 2 # E: Cannot redefine an existing name as final
y = 3 # No error here, first definition wins
y = 3 # E: Cannot assign to final name "y"

z: Final = 1
z: Final = 2 # E: Cannot redefine an existing name as final
z: Final = 2 # E: Name 'z' already defined on line 22 \
# E: Cannot redefine an existing name as final
z = 3 # E: Cannot assign to final name "z"
[out]

[case testFinalReassignModuleReexport]
from typing import Final
4 changes: 2 additions & 2 deletions test-data/unit/check-inference.test
Original file line number Diff line number Diff line change
@@ -2433,7 +2433,7 @@ _ = '' # E: Incompatible types in assignment (expression has type "str", variabl

[case testUnusedTargetNotClass]
class C:
_ = 0
_, _ = 0, 0
_ = ''
reveal_type(C._) # E: Revealed type is 'builtins.str'

@@ -2494,7 +2494,7 @@ def foo() -> None:
_ = 0 # E: Incompatible types in assignment (expression has type "int", variable has type "Callable[[], Any]")
[builtins fixtures/module.pyi]

[case testUnusedTargetNotClass]
[case testUnusedTargetNotClass2]
def foo() -> None:
class _:
pass
5 changes: 4 additions & 1 deletion test-data/unit/check-redefine.test
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ def f() -> None:

[case testRedefineFunctionArg]
def f(x: int) -> None:
g(x)
x = ''
reveal_type(x) # E: Revealed type is 'builtins.str'
def g(x: int) -> None:
@@ -286,7 +287,9 @@ def h() -> None:
x: object
x: object = '' # E: Name 'x' already defined on line 15
def farg(x: int) -> None:
x: str = ''
x: str = '' # E: Name 'x' already defined on line 17
def farg2(x: int) -> None:
x: str = x # E: Incompatible types in assignment (expression has type "int", variable has type "str")

[case testRedefineLocalWithTypeAnnotationSpecialCases]
def f() -> None:
6 changes: 3 additions & 3 deletions test-data/unit/semanal-basic.test
Original file line number Diff line number Diff line change
@@ -345,13 +345,13 @@ MypyFile:1(
NameExpr(object [builtins.object]))
Then(
AssignmentStmt:2(
NameExpr(x* [__main__.x])
NameExpr(x'* [__main__.x'])
CallExpr:2(
NameExpr(object [builtins.object])
Args()))
AssignmentStmt:3(
NameExpr(x [__main__.x])
NameExpr(x [__main__.x]))))
NameExpr(x* [__main__.x])
NameExpr(x' [__main__.x']))))
ExpressionStmt:4(
NameExpr(x [__main__.x])))

12 changes: 6 additions & 6 deletions test-data/unit/semanal-expressions.test
Original file line number Diff line number Diff line change
@@ -219,14 +219,14 @@ MypyFile:1(

[case testListComprehensionWithCondition]
a = 0
a = [x for x in a if x]
b = [x for x in a if x]
[out]
MypyFile:1(
AssignmentStmt:1(
NameExpr(a* [__main__.a])
IntExpr(0))
AssignmentStmt:2(
NameExpr(a [__main__.a])
NameExpr(b* [__main__.b])
ListComprehension:2(
GeneratorExpr:2(
NameExpr(x [l])
@@ -254,14 +254,14 @@ MypyFile:1(

[case testSetComprehensionWithCondition]
a = 0
a = {x for x in a if x}
b = {x for x in a if x}
[out]
MypyFile:1(
AssignmentStmt:1(
NameExpr(a* [__main__.a])
IntExpr(0))
AssignmentStmt:2(
NameExpr(a [__main__.a])
NameExpr(b* [__main__.b])
SetComprehension:2(
GeneratorExpr:2(
NameExpr(x [l])
@@ -289,14 +289,14 @@ MypyFile:1(

[case testDictionaryComprehensionWithCondition]
a = 0
a = {x: x + 1 for x in a if x}
b = {x: x + 1 for x in a if x}
[out]
MypyFile:1(
AssignmentStmt:1(
NameExpr(a* [__main__.a])
IntExpr(0))
AssignmentStmt:2(
NameExpr(a [__main__.a])
NameExpr(b* [__main__.b])
DictionaryComprehension:2(
NameExpr(x [l])
OpExpr:2(
104 changes: 57 additions & 47 deletions test-data/unit/semanal-statements.test
Original file line number Diff line number Diff line change
@@ -164,12 +164,12 @@ for x in None:
[out]
MypyFile:1(
ForStmt:1(
NameExpr(x* [__main__.x])
NameExpr(x'* [__main__.x'])
NameExpr(None [builtins.None])
Block:1(
PassStmt:2()))
ForStmt:3(
NameExpr(x [__main__.x])
NameExpr(x* [__main__.x])
NameExpr(None [builtins.None])
Block:3(
PassStmt:4())))
@@ -191,7 +191,7 @@ MypyFile:1(
Block:2(
PassStmt:3()))
ForStmt:4(
NameExpr(x [l])
NameExpr(x'* [l])
NameExpr(None [builtins.None])
Block:4(
PassStmt:5())))))
@@ -310,12 +310,12 @@ MypyFile:1(

[case testLvalues]
x = y = 1
x = 1
xx = 1
x.m = 1
x[y] = 1
x, y = 1
[x, y] = 1
(x, y) = 1
x2, y2 = 1
[x3, y3] = 1
(x4, y4) = 1
[out]
MypyFile:1(
AssignmentStmt:1(
@@ -324,7 +324,7 @@ MypyFile:1(
NameExpr(y* [__main__.y]))
IntExpr(1))
AssignmentStmt:2(
NameExpr(x [__main__.x])
NameExpr(xx* [__main__.xx])
IntExpr(1))
AssignmentStmt:3(
MemberExpr:3(
@@ -338,18 +338,18 @@ MypyFile:1(
IntExpr(1))
AssignmentStmt:5(
TupleExpr:5(
NameExpr(x [__main__.x])
NameExpr(y [__main__.y]))
NameExpr(x2* [__main__.x2])
NameExpr(y2* [__main__.y2]))
IntExpr(1))
AssignmentStmt:6(
TupleExpr:6(
NameExpr(x [__main__.x])
NameExpr(y [__main__.y]))
NameExpr(x3* [__main__.x3])
NameExpr(y3* [__main__.y3]))
IntExpr(1))
AssignmentStmt:7(
TupleExpr:7(
NameExpr(x [__main__.x])
NameExpr(y [__main__.y]))
NameExpr(x4* [__main__.x4])
NameExpr(y4* [__main__.y4]))
IntExpr(1)))

[case testStarLvalues]
@@ -361,23 +361,23 @@ MypyFile:1(
AssignmentStmt:1(
TupleExpr:1(
StarExpr:1(
NameExpr(x* [__main__.x]))
NameExpr(y* [__main__.y]))
NameExpr(x'* [__main__.x']))
NameExpr(y'* [__main__.y']))
IntExpr(1))
AssignmentStmt:2(
TupleExpr:2(
StarExpr:2(
NameExpr(x [__main__.x]))
NameExpr(x''* [__main__.x'']))
TupleExpr:2(
NameExpr(y [__main__.y])
NameExpr(y* [__main__.y])
StarExpr:2(
NameExpr(z* [__main__.z]))))
IntExpr(1))
AssignmentStmt:3(
TupleExpr:3(
StarExpr:3(
TupleExpr:3(
NameExpr(x [__main__.x])
NameExpr(x* [__main__.x])
NameExpr(q* [__main__.q])))
NameExpr(r* [__main__.r]))
IntExpr(1)))
@@ -389,13 +389,13 @@ x, y = 2
MypyFile:1(
AssignmentStmt:1(
TupleExpr:1(
NameExpr(x* [__main__.x])
NameExpr(y* [__main__.y]))
NameExpr(x'* [__main__.x'])
NameExpr(y'* [__main__.y']))
IntExpr(1))
AssignmentStmt:2(
TupleExpr:2(
NameExpr(x [__main__.x])
NameExpr(y [__main__.y]))
NameExpr(x* [__main__.x])
NameExpr(y* [__main__.y]))
IntExpr(2)))

[case testComplexDefinitions]
@@ -458,27 +458,32 @@ MypyFile:1(

[case testMultipleDefOnlySomeNewNestedLists]
x = 1
y, [x, z] = 1
[p, [x, r]] = 1
if x:
y, [x, z] = 1
[p, [x, r]] = 1
[out]
MypyFile:1(
AssignmentStmt:1(
NameExpr(x* [__main__.x])
IntExpr(1))
AssignmentStmt:2(
TupleExpr:2(
NameExpr(y* [__main__.y])
TupleExpr:2(
NameExpr(x [__main__.x])
NameExpr(z* [__main__.z])))
IntExpr(1))
AssignmentStmt:3(
TupleExpr:3(
NameExpr(p* [__main__.p])
TupleExpr:3(
NameExpr(x [__main__.x])
NameExpr(r* [__main__.r])))
IntExpr(1)))
IfStmt:2(
If(
NameExpr(x [__main__.x]))
Then(
AssignmentStmt:3(
TupleExpr:3(
NameExpr(y* [__main__.y])
TupleExpr:3(
NameExpr(x [__main__.x])
NameExpr(z* [__main__.z])))
IntExpr(1))
AssignmentStmt:4(
TupleExpr:4(
NameExpr(p* [__main__.p])
TupleExpr:4(
NameExpr(x [__main__.x])
NameExpr(r* [__main__.r])))
IntExpr(1)))))

[case testIndexedDel]
x = y = 1
@@ -712,7 +717,8 @@ MypyFile:1(
[case testVariableInBlock]
while object:
x = None
x = x
if x:
x = x
[out]
MypyFile:1(
WhileStmt:1(
@@ -721,9 +727,13 @@ MypyFile:1(
AssignmentStmt:2(
NameExpr(x* [__main__.x])
NameExpr(None [builtins.None]))
AssignmentStmt:3(
NameExpr(x [__main__.x])
NameExpr(x [__main__.x])))))
IfStmt:3(
If(
NameExpr(x [__main__.x]))
Then(
AssignmentStmt:4(
NameExpr(x [__main__.x])
NameExpr(x [__main__.x])))))))

[case testVariableInExceptHandler]
try:
@@ -809,15 +819,15 @@ x, o = o, o
[out]
MypyFile:1(
AssignmentStmt:1(
NameExpr(o* [__main__.o])
NameExpr(o'* [__main__.o'])
NameExpr(None [builtins.None]))
AssignmentStmt:2(
TupleExpr:2(
NameExpr(x* [__main__.x])
NameExpr(o [__main__.o]))
NameExpr(o* [__main__.o]))
TupleExpr:2(
NameExpr(o [__main__.o])
NameExpr(o [__main__.o]))))
NameExpr(o' [__main__.o'])
NameExpr(o' [__main__.o']))))

[case testFunctionDecorator]
def decorate(f): pass