Skip to content

Commit

Permalink
Always freeze type variables that were previously freshen (#8075)
Browse files Browse the repository at this point in the history
Fixes #8072

The fix is straightforward, just copy the logic from the working case (see last test) to two other code paths. Note that only two first cases I added crash on master, but I also add the last one for completeness because I didn't find a similar existing test case.
  • Loading branch information
ilevkivskyi authored Dec 4, 2019
1 parent e05bd1c commit ce8951e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
4 changes: 3 additions & 1 deletion mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,9 +569,10 @@ def analyze_var(name: str,
dispatched_type = meet.meet_types(mx.original_type, itype)
signature = freshen_function_type_vars(functype)
signature = check_self_arg(signature, dispatched_type, var.is_classmethod,
mx.context, name, mx.msg)
mx.context, name, mx.msg)
signature = bind_self(signature, mx.self_type, var.is_classmethod)
expanded_signature = get_proper_type(expand_type_by_instance(signature, itype))
freeze_type_vars(expanded_signature)
if var.is_property:
# A property cannot have an overloaded type => the cast is fine.
assert isinstance(expanded_signature, CallableType)
Expand Down Expand Up @@ -854,6 +855,7 @@ class B(A[str]): pass
t = bind_self(t, original_type, is_classmethod=True)
assert isuper is not None
t = cast(CallableType, expand_type_by_instance(t, isuper))
freeze_type_vars(t)
return t.copy_modified(variables=tvars + t.variables)
elif isinstance(t, Overloaded):
return Overloaded([cast(CallableType, add_class_tvars(item, isuper,
Expand Down
58 changes: 58 additions & 0 deletions test-data/unit/check-serialize.test
Original file line number Diff line number Diff line change
Expand Up @@ -1336,3 +1336,61 @@ import b
def foo() -> None:
class Foo:
class Bar: pass

[case testSerializeGenericClassMethod]
import a
[file a.py]
import b
from typing import TypeVar

T = TypeVar('T')

class C:
@classmethod
def f(cls, x: T) -> T: ...

x = C.f
[file b.py]
x = 1
[file b.py.2]
x = 'yes'
[builtins fixtures/classmethod.pyi]

[case testSerializeGenericAbstractMethod]
import a
[file a.py]
import b
from typing import TypeVar
from abc import abstractmethod

T = TypeVar('T')

class C:
@abstractmethod
def f(self, x: T) -> T: ...

c: C
x = c.f
[file b.py]
x = 1
[file b.py.2]
x = 'yes'

[case testSerializeGenericNormalMethod]
import a
[file a.py]
import b
from typing import TypeVar
from abc import abstractmethod

T = TypeVar('T')

class C:
def f(self, x: T) -> T: ...

c: C
x = c.f
[file b.py]
x = 1
[file b.py.2]
x = 'yes'

0 comments on commit ce8951e

Please sign in to comment.