Repository: python/mypy

Issue:
Internal error aliasing a typevar within a function
The following code will (correctly) not typecheck
```python
from typing import TypeVar, List
class Example(object):
    T = TypeVar("T")
    @staticmethod
    def example(t: T) -> List[T]:
        x = [t] # type: List[T]
        return x
```
```
test.py: note: In function "example":
test.py:6: error: Name 'T' is not defined
```

While it's possible to fix this by replacing the `T` in `List[T]` on line 6 with `Example.T`, sometimes this is prohibitively long, so a user might want to alias said type. The following code (an example of the way I attempted aliasing) does not typecheck, but instead causes an internal error
```python
from typing import TypeVar, List
class Example(object):
    T = TypeVar("T")
    @staticmethod
    def example(t: T) -> List[T]:
        # intentionally using a name other than T
        # if I do use T, the result is the same
        A = Example.T # line 8
        x = [t] # type: List[A]
        return x
```
```
test2.py: note: In function "example":
test2.py:9: error: Invalid type "A"
test2.py:8: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues
Traceback (most recent call last):
  File "/usr/local/bin/mypy", line 6, in <module>
    main(__file__)
  File "/usr/local/lib/python3.5/dist-packages/mypy/main.py", line 41, in main
    res = type_check_only(sources, bin_dir, options)
  File "/usr/local/lib/python3.5/dist-packages/mypy/main.py", line 86, in type_check_only
    options=options)
  File "/usr/local/lib/python3.5/dist-packages/mypy/build.py", line 183, in build
    dispatch(sources, manager)
  File "/usr/local/lib/python3.5/dist-packages/mypy/build.py", line 1512, in dispatch
    process_graph(graph, manager)
  File "/usr/local/lib/python3.5/dist-packages/mypy/build.py", line 1692, in process_graph
    process_stale_scc(graph, scc)
  File "/usr/local/lib/python3.5/dist-packages/mypy/build.py", line 1771, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/usr/local/lib/python3.5/dist-packages/mypy/build.py", line 1440, in type_check_first_pass
    self.type_checker.check_first_pass()
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 174, in check_first_pass
    self.accept(d)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 243, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/nodes.py", line 710, in accept
    return visitor.visit_class_def(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 992, in visit_class_def
    self.accept(defn.defs)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 243, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/nodes.py", line 771, in accept
    return visitor.visit_block(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 1087, in visit_block
    self.accept(s)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 243, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/nodes.py", line 597, in accept
    return visitor.visit_decorator(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 1882, in visit_decorator
    e.func.accept(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/nodes.py", line 532, in accept
    return visitor.visit_func_def(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 455, in visit_func_def
    self.check_func_item(defn, name=defn.name())
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 518, in check_func_item
    self.check_func_def(defn, typ, name)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 648, in check_func_def
    self.accept(item.body)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 243, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/nodes.py", line 771, in accept
    return visitor.visit_block(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 1087, in visit_block
    self.accept(s)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 243, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/nodes.py", line 812, in accept
    return visitor.visit_assignment_stmt(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 1095, in visit_assignment_stmt
    self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 1161, in check_assignment
    self.infer_variable_type(inferred, lvalue, self.accept(rvalue),
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 243, in accept
    typ = node.accept(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/nodes.py", line 1202, in accept
    return visitor.visit_member_expr(self)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checker.py", line 2054, in visit_member_expr
    return self.expr_checker.visit_member_expr(e)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checkexpr.py", line 889, in visit_member_expr
    result = self.analyze_ordinary_member_access(e, False)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checkexpr.py", line 904, in analyze_ordinary_member_access
    original_type=original_type, chk=self.chk)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checkmember.py", line 142, in analyze_member_access
    original_type=original_type)
  File "/usr/local/lib/python3.5/dist-packages/mypy/checkmember.py", line 387, in analyze_class_attribute_access
    return function_type(cast(FuncBase, node.node), builtin_type('builtins.function'))
  File "/usr/local/lib/python3.5/dist-packages/mypy/types.py", line 1508, in function_type
    if func.type:
AttributeError: 'TypeVarExpr' object has no attribute 'type'
```


Discussion:
As a note, the fix I ended up using was just to move the type variable outside the class, despite it only being used for that one function.

Also as a note, the line doing the aliasing is all that's required to cause an error, the code after it is irrelevant.
I was able to repro the crash. Thanks for reporting the bug!
Just found this: https://github.com/python/mypy/blob/master/mypy/semanal.py#L1235

Semantic analysis doesn't accept this as an alias, which means further down the track it just breaks.

Resolving patch:
diff --git a/mypy/checkmember.py b/mypy/checkmember.py
--- a/mypy/checkmember.py
+++ b/mypy/checkmember.py
@@ -7,7 +7,7 @@
     Overloaded, TypeVarType, UnionType, PartialType,
     DeletedType, NoneTyp, TypeType, function_type
 )
-from mypy.nodes import TypeInfo, FuncBase, Var, FuncDef, SymbolNode, Context, MypyFile
+from mypy.nodes import TypeInfo, FuncBase, Var, FuncDef, SymbolNode, Context, MypyFile, TypeVarExpr
 from mypy.nodes import ARG_POS, ARG_STAR, ARG_STAR2
 from mypy.nodes import Decorator, OverloadedFuncDef
 from mypy.messages import MessageBuilder
@@ -378,6 +378,9 @@ def analyze_class_attribute_access(itype: Instance,
         not_ready_callback(name, context)
         return AnyType()
 
+    if isinstance(node.node, TypeVarExpr):
+        return TypeVarType(node.tvar_def, node.tvar_def.line, node.tvar_def.column)
+
     if isinstance(node.node, TypeInfo):
         return type_object_type(node.node, builtin_type)
 


Test patch:
diff --git a/test-data/unit/check-typevar-values.test b/test-data/unit/check-typevar-values.test
--- a/test-data/unit/check-typevar-values.test
+++ b/test-data/unit/check-typevar-values.test
@@ -489,3 +489,11 @@ def outer(x: T) -> T:
         return inner1('a') # E: Argument 1 to "inner1" has incompatible type "str"; expected "int"
     return inner1(x)
 [out]
+
+[case testClassMemberTypeVarInFunctionBody]
+from typing import TypeVar
+class C:
+    T = TypeVar('T', int)
+    def f(self, x: T) -> T:
+        A = C.T
+        return x