1- from typing import Dict , Iterable , List , TypeVar , Mapping , cast , Union , Optional
1+ from typing import Dict , Iterable , List , TypeVar , Mapping , cast , Union , Optional , Sequence
22
33from mypy .types import (
44 Type , Instance , CallableType , TypeVisitor , UnboundType , AnyType ,
55 NoneType , Overloaded , TupleType , TypedDictType , UnionType ,
66 ErasedType , PartialType , DeletedType , UninhabitedType , TypeType , TypeVarId ,
77 FunctionLike , TypeVarType , LiteralType , get_proper_type , ProperType ,
88 TypeAliasType , ParamSpecType , TypeVarLikeType , Parameters , ParamSpecFlavor ,
9- UnpackType , TypeVarTupleType
9+ UnpackType , TypeVarTupleType , TypeList
1010)
11+ from mypy .typevartuples import split_with_instance , split_with_prefix_and_suffix
1112
1213
1314def expand_type (typ : Type , env : Mapping [TypeVarId , Type ]) -> Type :
@@ -26,8 +27,26 @@ def expand_type_by_instance(typ: Type, instance: Instance) -> Type:
2627 return typ
2728 else :
2829 variables : Dict [TypeVarId , Type ] = {}
29- for binder , arg in zip (instance .type .defn .type_vars , instance .args ):
30+ if instance .type .has_type_var_tuple_type :
31+ assert instance .type .type_var_tuple_prefix is not None
32+ assert instance .type .type_var_tuple_suffix is not None
33+
34+ args_prefix , args_middle , args_suffix = split_with_instance (instance )
35+ tvars_prefix , tvars_middle , tvars_suffix = split_with_prefix_and_suffix (
36+ tuple (instance .type .defn .type_vars ),
37+ instance .type .type_var_tuple_prefix ,
38+ instance .type .type_var_tuple_suffix ,
39+ )
40+ variables = {tvars_middle [0 ].id : TypeList (list (args_middle ))}
41+ instance_args = args_prefix + args_suffix
42+ tvars = tvars_prefix + tvars_suffix
43+ else :
44+ tvars = tuple (instance .type .defn .type_vars )
45+ instance_args = instance .args
46+
47+ for binder , arg in zip (tvars , instance_args ):
3048 variables [binder .id ] = arg
49+
3150 return expand_type (typ , variables )
3251
3352
@@ -46,6 +65,7 @@ def freshen_function_type_vars(callee: F) -> F:
4665 if isinstance (v , TypeVarType ):
4766 tv : TypeVarLikeType = TypeVarType .new_unification_variable (v )
4867 elif isinstance (v , TypeVarTupleType ):
68+ assert isinstance (v , TypeVarTupleType )
4969 tv = TypeVarTupleType .new_unification_variable (v )
5070 else :
5171 assert isinstance (v , ParamSpecType )
@@ -89,8 +109,11 @@ def visit_erased_type(self, t: ErasedType) -> Type:
89109 raise RuntimeError ()
90110
91111 def visit_instance (self , t : Instance ) -> Type :
92- args = self .expand_types (t .args )
93- return Instance (t .type , args , t .line , t .column )
112+ args = self .expand_types_with_unpack (list (t .args ))
113+ if isinstance (args , list ):
114+ return Instance (t .type , args , t .line , t .column )
115+ else :
116+ return args
94117
95118 def visit_type_var (self , t : TypeVarType ) -> Type :
96119 repl = get_proper_type (self .variables .get (t .id , t ))
@@ -153,6 +176,8 @@ def expand_unpack(self, t: UnpackType) -> Optional[Union[List[Type], Instance, A
153176 repl = get_proper_type (self .variables .get (proper_typ .id , t ))
154177 if isinstance (repl , TupleType ):
155178 return repl .items
179+ if isinstance (repl , TypeList ):
180+ return repl .items
156181 elif isinstance (repl , Instance ) and repl .type .fullname == "builtins.tuple" :
157182 return repl
158183 elif isinstance (repl , AnyType ):
@@ -166,9 +191,9 @@ def expand_unpack(self, t: UnpackType) -> Optional[Union[List[Type], Instance, A
166191 elif isinstance (repl , UninhabitedType ):
167192 return None
168193 else :
169- raise NotImplementedError (f"Invalid type to expand: { repl } " )
194+ raise NotImplementedError (f"Invalid type replacement to expand: { repl } " )
170195 else :
171- raise NotImplementedError
196+ raise NotImplementedError ( f"Invalid type to expand: { proper_typ } " )
172197
173198 def visit_parameters (self , t : Parameters ) -> Type :
174199 return t .copy_modified (arg_types = self .expand_types (t .arg_types ))
@@ -211,17 +236,25 @@ def visit_overloaded(self, t: Overloaded) -> Type:
211236 items .append (new_item )
212237 return Overloaded (items )
213238
214- def visit_tuple_type (self , t : TupleType ) -> Type :
215- items = []
216- for item in t .items :
239+ def expand_types_with_unpack (
240+ self , typs : Sequence [Type ]
241+ ) -> Union [List [Type ], AnyType , UninhabitedType , Instance ]:
242+ """Expands a list of types that has an unpack.
243+
244+ In corner cases, this can return a type rather than a list, in which case this
245+ indicates use of Any or some error occurred earlier. In this case callers should
246+ simply propagate the resulting type.
247+ """
248+ items : List [Type ] = []
249+ for item in typs :
217250 proper_item = get_proper_type (item )
218251 if isinstance (proper_item , UnpackType ):
219252 unpacked_items = self .expand_unpack (proper_item )
220253 if unpacked_items is None :
221254 # TODO: better error, something like tuple of unknown?
222255 return UninhabitedType ()
223256 elif isinstance (unpacked_items , Instance ):
224- if len (t . items ) == 1 :
257+ if len (typs ) == 1 :
225258 return unpacked_items
226259 else :
227260 assert False , "Invalid unpack of variable length tuple"
@@ -231,8 +264,14 @@ def visit_tuple_type(self, t: TupleType) -> Type:
231264 items .extend (unpacked_items )
232265 else :
233266 items .append (proper_item .accept (self ))
267+ return items
234268
235- return t .copy_modified (items = items )
269+ def visit_tuple_type (self , t : TupleType ) -> Type :
270+ items = self .expand_types_with_unpack (t .items )
271+ if isinstance (items , list ):
272+ return t .copy_modified (items = items )
273+ else :
274+ return items
236275
237276 def visit_typeddict_type (self , t : TypedDictType ) -> Type :
238277 return t .copy_modified (item_types = self .expand_types (t .items .values ()))
0 commit comments