@@ -399,7 +399,7 @@ def __init__(self) -> None:
399399 self .unanalyzed_type = None # type: Optional[mypy.types.Type]
400400 # If method, reference to TypeInfo
401401 # TODO: Type should be Optional[TypeInfo]
402- self .info = cast ( TypeInfo , None )
402+ self .info = FUNC_NO_INFO
403403 self .is_property = False
404404 self .is_class = False
405405 self .is_static = False
@@ -727,7 +727,7 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None:
727727 # TODO: Should be Optional[str]
728728 self ._fullname = cast (str , None ) # Name with module prefix
729729 # TODO: Should be Optional[TypeInfo]
730- self .info = cast ( TypeInfo , None ) # Defining class (for member variables)
730+ self .info = VAR_NO_INFO
731731 self .type = type # type: Optional[mypy.types.Type] # Declared or inferred type, or None
732732 # Is this the first argument to an ordinary method (usually "self")?
733733 self .is_self = False
@@ -807,6 +807,7 @@ def __init__(self,
807807 self .type_vars = type_vars or []
808808 self .base_type_exprs = base_type_exprs or []
809809 self .removed_base_type_exprs = []
810+ self .info = CLASSDEF_NO_INFO
810811 self .metaclass = metaclass
811812 self .decorators = []
812813 self .keywords = OrderedDict (keywords or [])
@@ -1412,7 +1413,7 @@ class IndexExpr(Expression):
14121413 base = None # type: Expression
14131414 index = None # type: Expression
14141415 # Inferred __getitem__ method type
1415- method_type = None # type: mypy.types.Type
1416+ method_type = None # type: Optional[ mypy.types.Type]
14161417 # If not None, this is actually semantically a type application
14171418 # Class[type, ...] or a type alias initializer.
14181419 analyzed = None # type: Union[TypeApplication, TypeAliasExpr, None]
@@ -2154,7 +2155,7 @@ class is generic then it will be a type constructor of higher kind.
21542155 # type (NamedTuple or TypedDict) was generated, store the corresponding
21552156 # TypeInfo here. (This attribute does not need to be serialized, it is only
21562157 # needed during the semantic passes.)
2157- replaced = None # type: TypeInfo
2158+ replaced = None # type: Optional[ TypeInfo]
21582159
21592160 # This is a dictionary that will be serialized and un-serialized as is.
21602161 # It is useful for plugins to add their data to save in the cache.
@@ -2414,11 +2415,27 @@ class FakeInfo(TypeInfo):
24142415 # pass cleanly.
24152416 # 2. If NOT_READY value is accidentally used somewhere, it will be obvious where the value
24162417 # 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
24192431
24202432 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
24222439
24232440
24242441class TypeAlias (SymbolNode ):
@@ -2658,8 +2675,10 @@ def fullname(self) -> Optional[str]:
26582675 @property
26592676 def type (self ) -> 'Optional[mypy.types.Type]' :
26602677 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 ):
26632682 return node .type
26642683 elif isinstance (node , Decorator ):
26652684 return node .var .type
@@ -2764,7 +2783,8 @@ def get_member_expr_fullname(expr: MemberExpr) -> Optional[str]:
27642783deserialize_map = {
27652784 key : obj .deserialize # type: ignore
27662785 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
27682788}
27692789
27702790
0 commit comments