Skip to content

Commit

Permalink
Fix meta level on member access (#2809)
Browse files Browse the repository at this point in the history
Fixes #2804

The problem is that analyze_member_access calls freshen_function_type_vars 
if the member is a function (i.e. method). This is necessary to not mix the type 
variables during type inference of generic methods inside generic functions. 
However, if the method does not participate in type inference, type variables 
are left in meta_level = 1 state. This causes the error, since the types could not 
be serialized in the middle of type inference.

In this PR I propose to restore meta_level = 0 on member access, this is safe, 
since anyway, check_call always calls freshen_function_type_vars on callee (for 
generic functions, generic methods, etc).
  • Loading branch information
ilevkivskyi authored and JukkaL committed Feb 7, 2017
1 parent b4492b7 commit a2d654b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 1 deletion.
7 changes: 7 additions & 0 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,13 @@ def analyze_ordinary_member_access(self, e: MemberExpr,
e.name, original_type, e, is_lvalue, False, False,
self.named_type, self.not_ready_callback, self.msg,
original_type=original_type, chk=self.chk)
if isinstance(member_type, CallableType):
for v in member_type.variables:
v.id.meta_level = 0
if isinstance(member_type, Overloaded):
for it in member_type.items():
for v in it.variables:
v.id.meta_level = 0
if is_lvalue:
return member_type
else:
Expand Down
19 changes: 19 additions & 0 deletions test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -1767,6 +1767,25 @@ main:2: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=typing.Mapp
main:3: error: Revealed type is 'TypedDict(x=builtins.int, _fallback=ntcrash.C.A@4)'
main:4: error: Revealed type is 'def () -> ntcrash.C.A@4'

[case testGenericMethodRestoreMetaLevel]
from typing import Dict

d = {} # type: Dict[str, int]
g = d.get # This should not crash: see https://github.com/python/mypy/issues/2804
[builtins fixtures/dict.pyi]

[case testGenericMethodRestoreMetaLevel2]
from typing import TypeVar

T = TypeVar('T')

class D:
def m(self, x: T) -> T:
return x

g = D().m # This should not crash: see https://github.com/python/mypy/issues/2804
[builtins fixtures/dict.pyi]

[case testIncrementalPerFileFlags]
# flags: --config-file tmp/mypy.ini
import a
Expand Down
6 changes: 5 additions & 1 deletion test-data/unit/fixtures/dict.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Builtins stub used in dictionary-related test cases.

from typing import TypeVar, Generic, Iterable, Iterator, Mapping, Tuple, overload
from typing import TypeVar, Generic, Iterable, Iterator, Mapping, Tuple, overload, Optional, Union

T = TypeVar('T')
KT = TypeVar('KT')
Expand All @@ -19,6 +19,10 @@ class dict(Iterable[KT], Mapping[KT, VT], Generic[KT, VT]):
def __setitem__(self, k: KT, v: VT) -> None: pass
def __iter__(self) -> Iterator[KT]: pass
def update(self, a: Mapping[KT, VT]) -> None: pass
@overload
def get(self, k: KT) -> Optional[VT]: pass
@overload
def get(self, k: KT, default: Union[KT, T]) -> Union[VT, T]: pass

class int: # for convenience
def __add__(self, x: int) -> int: pass
Expand Down

0 comments on commit a2d654b

Please sign in to comment.