@@ -399,7 +399,7 @@ def __init__(self) -> None:
399
399
self .unanalyzed_type = None # type: Optional[mypy.types.Type]
400
400
# If method, reference to TypeInfo
401
401
# TODO: Type should be Optional[TypeInfo]
402
- self .info = cast ( TypeInfo , None )
402
+ self .info = FUNC_NO_INFO
403
403
self .is_property = False
404
404
self .is_class = False
405
405
self .is_static = False
@@ -727,7 +727,7 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None:
727
727
# TODO: Should be Optional[str]
728
728
self ._fullname = cast (str , None ) # Name with module prefix
729
729
# TODO: Should be Optional[TypeInfo]
730
- self .info = cast ( TypeInfo , None ) # Defining class (for member variables)
730
+ self .info = VAR_NO_INFO
731
731
self .type = type # type: Optional[mypy.types.Type] # Declared or inferred type, or None
732
732
# Is this the first argument to an ordinary method (usually "self")?
733
733
self .is_self = False
@@ -807,6 +807,7 @@ def __init__(self,
807
807
self .type_vars = type_vars or []
808
808
self .base_type_exprs = base_type_exprs or []
809
809
self .removed_base_type_exprs = []
810
+ self .info = CLASSDEF_NO_INFO
810
811
self .metaclass = metaclass
811
812
self .decorators = []
812
813
self .keywords = OrderedDict (keywords or [])
@@ -1412,7 +1413,7 @@ class IndexExpr(Expression):
1412
1413
base = None # type: Expression
1413
1414
index = None # type: Expression
1414
1415
# Inferred __getitem__ method type
1415
- method_type = None # type: mypy.types.Type
1416
+ method_type = None # type: Optional[ mypy.types.Type]
1416
1417
# If not None, this is actually semantically a type application
1417
1418
# Class[type, ...] or a type alias initializer.
1418
1419
analyzed = None # type: Union[TypeApplication, TypeAliasExpr, None]
@@ -2154,7 +2155,7 @@ class is generic then it will be a type constructor of higher kind.
2154
2155
# type (NamedTuple or TypedDict) was generated, store the corresponding
2155
2156
# TypeInfo here. (This attribute does not need to be serialized, it is only
2156
2157
# needed during the semantic passes.)
2157
- replaced = None # type: TypeInfo
2158
+ replaced = None # type: Optional[ TypeInfo]
2158
2159
2159
2160
# This is a dictionary that will be serialized and un-serialized as is.
2160
2161
# It is useful for plugins to add their data to save in the cache.
@@ -2414,11 +2415,27 @@ class FakeInfo(TypeInfo):
2414
2415
# pass cleanly.
2415
2416
# 2. If NOT_READY value is accidentally used somewhere, it will be obvious where the value
2416
2417
# is from, whereas a 'None' value could come from anywhere.
2417
- def __init__ (self , * args : Any , ** kwargs : Any ) -> None :
2418
- pass
2418
+ #
2419
+ # Additionally, this serves as a more general-purpose placeholder
2420
+ # for missing TypeInfos in a number of places where the excuses
2421
+ # for not being Optional are a little weaker.
2422
+ #
2423
+ # It defines a __bool__ method so that it can be conveniently
2424
+ # tested against in the same way that it would be if things were
2425
+ # properly optional.
2426
+ def __init__ (self , msg : str ) -> None :
2427
+ self .msg = msg
2428
+
2429
+ def __bool__ (self ) -> bool :
2430
+ return False
2419
2431
2420
2432
def __getattribute__ (self , attr : str ) -> None :
2421
- raise AssertionError ('De-serialization failure: TypeInfo not fixed' )
2433
+ raise AssertionError (object .__getattribute__ (self , 'msg' ))
2434
+
2435
+
2436
+ VAR_NO_INFO = FakeInfo ('Var is lacking info' ) # type: TypeInfo
2437
+ CLASSDEF_NO_INFO = FakeInfo ('ClassDef is lacking info' ) # type: TypeInfo
2438
+ FUNC_NO_INFO = FakeInfo ('FuncBase for non-methods lack info' ) # type: TypeInfo
2422
2439
2423
2440
2424
2441
class TypeAlias (SymbolNode ):
@@ -2658,8 +2675,10 @@ def fullname(self) -> Optional[str]:
2658
2675
@property
2659
2676
def type (self ) -> 'Optional[mypy.types.Type]' :
2660
2677
node = self .node
2661
- if ((isinstance (node , Var ) or isinstance (node , FuncBase ))
2662
- and node .type is not None ):
2678
+ if (isinstance (node , Var ) and node .type is not None ):
2679
+ return node .type
2680
+ # mypy thinks this branch is unreachable but it is wrong (#3603)
2681
+ elif (isinstance (node , FuncBase ) and node .type is not None ):
2663
2682
return node .type
2664
2683
elif isinstance (node , Decorator ):
2665
2684
return node .var .type
@@ -2764,7 +2783,8 @@ def get_member_expr_fullname(expr: MemberExpr) -> Optional[str]:
2764
2783
deserialize_map = {
2765
2784
key : obj .deserialize # type: ignore
2766
2785
for key , obj in globals ().items ()
2767
- if isinstance (obj , type ) and issubclass (obj , SymbolNode ) and obj is not SymbolNode
2786
+ if type (obj ) is not FakeInfo
2787
+ and isinstance (obj , type ) and issubclass (obj , SymbolNode ) and obj is not SymbolNode
2768
2788
}
2769
2789
2770
2790
0 commit comments