@@ -2907,31 +2907,36 @@ def gen_unique_name(base: str, table: SymbolTable) -> str:
2907
2907
return base + str (i )
2908
2908
2909
2909
2910
- def intersect_instance_callable (type : Instance , callable_type : CallableType ,
2911
- typechecker : TypeChecker ) -> Type :
2910
+ def intersect_instance_callable (typ : Instance , callable_type : CallableType ,
2911
+ typechecker : TypeChecker ) -> Instance :
2912
2912
"""Creates a fake type that represents the intersection of an
2913
2913
Instance and a CallableType.
2914
2914
2915
2915
It operates by creating a bare-minimum dummy TypeInfo that
2916
- subclasses type and adds a __call__ method matching callable_type."""
2916
+ subclasses type and adds a __call__ method matching callable_type.
2917
+ """
2917
2918
2918
2919
# In order for this to work in incremental mode, the type we generate needs to
2919
2920
# have a valid fullname and a corresponding entry in a symbol table. We generate
2920
2921
# a unique name inside the symbol table of the current module.
2921
2922
cur_module = cast (MypyFile , typechecker .scope .stack [0 ])
2922
- gen_name = gen_unique_name ("<callable subtype of {}>" .format (type .type .name ()),
2923
+ gen_name = gen_unique_name ("<callable subtype of {}>" .format (typ .type .name ()),
2923
2924
cur_module .names )
2924
2925
2925
2926
# Build the fake ClassDef and TypeInfo together.
2926
2927
# The ClassDef is full of lies and doesn't actually contain a body.
2927
2928
# Use format_bare to generate a nice name for error messages.
2928
- short_name = typechecker .msg .format_bare (type )
2929
+ # We skip filling fully filling out a handful of TypeInfo fields because they
2930
+ # should be irrelevant for a generated type like this:
2931
+ # is_protocol, protocol_members, is_abstract
2932
+ short_name = typechecker .msg .format_bare (typ )
2929
2933
cdef = ClassDef (short_name , Block ([]))
2930
2934
cdef .fullname = cur_module .fullname () + '.' + gen_name
2931
2935
info = TypeInfo (SymbolTable (), cdef , cur_module .fullname ())
2932
2936
cdef .info = info
2933
- info .bases = [type ]
2937
+ info .bases = [typ ]
2934
2938
info .calculate_mro ()
2939
+ info .calculate_metaclass_type ()
2935
2940
2936
2941
# Build up a fake FuncDef so we can populate the symbol table.
2937
2942
func_def = FuncDef ('__call__' , [], Block ([]), callable_type )
@@ -2943,7 +2948,7 @@ def intersect_instance_callable(type: Instance, callable_type: CallableType,
2943
2948
return Instance (info , [])
2944
2949
2945
2950
2946
- def make_fake_callable (type : Instance , typechecker : TypeChecker ) -> Type :
2951
+ def make_fake_callable (typ : Instance , typechecker : TypeChecker ) -> Instance :
2947
2952
"""Produce a new type that makes type Callable with a generic callable type."""
2948
2953
2949
2954
fallback = typechecker .named_type ('builtins.function' )
@@ -2955,10 +2960,10 @@ def make_fake_callable(type: Instance, typechecker: TypeChecker) -> Type:
2955
2960
fallback = fallback ,
2956
2961
is_ellipsis_args = True )
2957
2962
2958
- return intersect_instance_callable (type , callable_type , typechecker )
2963
+ return intersect_instance_callable (typ , callable_type , typechecker )
2959
2964
2960
2965
2961
- def partition_by_callable (type : Type , typechecker : TypeChecker ,
2966
+ def partition_by_callable (typ : Type , typechecker : TypeChecker ,
2962
2967
unsound_partition : bool ) -> Tuple [List [Type ], List [Type ]]:
2963
2968
"""Takes in a type and partitions that type into callable subtypes and
2964
2969
uncallable subtypes.
@@ -2976,16 +2981,16 @@ def partition_by_callable(type: Type, typechecker: TypeChecker,
2976
2981
Guaranteed to not return [], []
2977
2982
2978
2983
"""
2979
- if isinstance (type , FunctionLike ) or isinstance (type , TypeType ):
2980
- return [type ], []
2984
+ if isinstance (typ , FunctionLike ) or isinstance (typ , TypeType ):
2985
+ return [typ ], []
2981
2986
2982
- if isinstance (type , AnyType ):
2983
- return [type ], [type ]
2987
+ if isinstance (typ , AnyType ):
2988
+ return [typ ], [typ ]
2984
2989
2985
- if isinstance (type , UnionType ):
2990
+ if isinstance (typ , UnionType ):
2986
2991
callables = []
2987
2992
uncallables = []
2988
- for subtype in type .relevant_items ():
2993
+ for subtype in typ .relevant_items ():
2989
2994
# Use unsound_partition when handling unions in order to
2990
2995
# allow the expected type discrimination.
2991
2996
subcallables , subuncallables = partition_by_callable (subtype , typechecker ,
@@ -2994,7 +2999,7 @@ def partition_by_callable(type: Type, typechecker: TypeChecker,
2994
2999
uncallables .extend (subuncallables )
2995
3000
return callables , uncallables
2996
3001
2997
- if isinstance (type , TypeVarType ):
3002
+ if isinstance (typ , TypeVarType ):
2998
3003
# We could do better probably?
2999
3004
# Refine the the type variable's bound as our type in the case that
3000
3005
# callable() is true. This unfortuantely loses the information that
@@ -3003,30 +3008,39 @@ def partition_by_callable(type: Type, typechecker: TypeChecker,
3003
3008
# do better.
3004
3009
# If it is possible for the false branch to execute, return the original
3005
3010
# type to avoid losing type information.
3006
- callables , uncallables = partition_by_callable (type .erase_to_union_or_bound (), typechecker ,
3011
+ callables , uncallables = partition_by_callable (typ .erase_to_union_or_bound (), typechecker ,
3007
3012
unsound_partition )
3008
- uncallables = [type ] if len (uncallables ) else []
3013
+ uncallables = [typ ] if len (uncallables ) else []
3009
3014
return callables , uncallables
3010
3015
3011
- if isinstance (type , Instance ):
3012
- method = type .type .get_method ('__call__' )
3016
+ # A TupleType is callable if its fallback is, but needs special handling
3017
+ # when we dummy up a new type.
3018
+ ityp = typ
3019
+ if isinstance (typ , TupleType ):
3020
+ ityp = typ .fallback
3021
+
3022
+ if isinstance (ityp , Instance ):
3023
+ method = ityp .type .get_method ('__call__' )
3013
3024
if method and method .type :
3014
3025
callables , uncallables = partition_by_callable (method .type , typechecker ,
3015
3026
unsound_partition = False )
3016
3027
if len (callables ) and not len (uncallables ):
3017
3028
# Only consider the type callable if its __call__ method is
3018
3029
# definitely callable.
3019
- return [type ], []
3030
+ return [typ ], []
3020
3031
3021
3032
if not unsound_partition :
3022
- ret = make_fake_callable (type , typechecker )
3023
- return [ret ], [type ]
3033
+ fake = make_fake_callable (ityp , typechecker )
3034
+ if isinstance (typ , TupleType ):
3035
+ fake .type .tuple_type = TupleType (typ .items , fake )
3036
+ return [fake .type .tuple_type ], [typ ]
3037
+ return [fake ], [typ ]
3024
3038
3025
3039
if unsound_partition :
3026
- return [], [type ]
3040
+ return [], [typ ]
3027
3041
else :
3028
3042
# We don't know how properly make the type callable.
3029
- return [type ], [type ]
3043
+ return [typ ], [typ ]
3030
3044
3031
3045
3032
3046
def conditional_callable_type_map (expr : Expression ,
@@ -3038,7 +3052,8 @@ def conditional_callable_type_map(expr: Expression,
3038
3052
Returns a 2-tuple: The first element is a map from the expression to
3039
3053
the restricted type if it were callable. The second element is a
3040
3054
map from the expression to the type it would hold if it weren't
3041
- callable."""
3055
+ callable.
3056
+ """
3042
3057
if not current_type :
3043
3058
return {}, {}
3044
3059
0 commit comments