@@ -568,7 +568,9 @@ def try_analyze_special_unbound_type(self, t: UnboundType, fullname: str) -> Typ
568568 instance = self .named_type ("builtins.tuple" , [self .anal_type (t .args [0 ])])
569569 instance .line = t .line
570570 return instance
571- return self .tuple_type (self .anal_array (t .args , allow_unpack = True ))
571+ return self .tuple_type (
572+ self .anal_array (t .args , allow_unpack = True ), line = t .line , column = t .column
573+ )
572574 elif fullname == "typing.Union" :
573575 items = self .anal_array (t .args )
574576 return UnionType .make_union (items )
@@ -968,7 +970,10 @@ def visit_type_var_tuple(self, t: TypeVarTupleType) -> Type:
968970 return t
969971
970972 def visit_unpack_type (self , t : UnpackType ) -> Type :
971- raise NotImplementedError
973+ if not self .allow_unpack :
974+ self .fail (message_registry .INVALID_UNPACK_POSITION , t .type , code = codes .VALID_TYPE )
975+ return AnyType (TypeOfAny .from_error )
976+ return UnpackType (self .anal_type (t .type ))
972977
973978 def visit_parameters (self , t : Parameters ) -> Type :
974979 raise NotImplementedError ("ParamSpec literals cannot have unbound TypeVars" )
@@ -1364,12 +1369,22 @@ def analyze_callable_type(self, t: UnboundType) -> Type:
13641369 assert isinstance (ret , CallableType )
13651370 return ret .accept (self )
13661371
1372+ def refers_to_full_names (self , arg : UnboundType , names : Sequence [str ]) -> bool :
1373+ sym = self .lookup_qualified (arg .name , arg )
1374+ if sym is not None :
1375+ if sym .fullname in names :
1376+ return True
1377+ return False
1378+
13671379 def analyze_callable_args (
13681380 self , arglist : TypeList
13691381 ) -> tuple [list [Type ], list [ArgKind ], list [str | None ]] | None :
13701382 args : list [Type ] = []
13711383 kinds : list [ArgKind ] = []
13721384 names : list [str | None ] = []
1385+ seen_unpack = False
1386+ unpack_types : list [Type ] = []
1387+ invalid_unpacks = []
13731388 for arg in arglist .items :
13741389 if isinstance (arg , CallableArgument ):
13751390 args .append (arg .typ )
@@ -1390,20 +1405,42 @@ def analyze_callable_args(
13901405 if arg .name is not None and kind .is_star ():
13911406 self .fail (f"{ arg .constructor } arguments should not have names" , arg )
13921407 return None
1393- elif isinstance (arg , UnboundType ):
1394- kind = ARG_POS
1395- # Potentially a unpack.
1396- sym = self .lookup_qualified (arg .name , arg )
1397- if sym is not None :
1398- if sym .fullname in ("typing_extensions.Unpack" , "typing.Unpack" ):
1399- kind = ARG_STAR
1400- args .append (arg )
1401- kinds .append (kind )
1402- names .append (None )
1408+ elif (
1409+ isinstance (arg , UnboundType )
1410+ and self .refers_to_full_names (arg , ("typing_extensions.Unpack" , "typing.Unpack" ))
1411+ or isinstance (arg , UnpackType )
1412+ ):
1413+ if seen_unpack :
1414+ # Multiple unpacks, preserve them, so we can give an error later.
1415+ invalid_unpacks .append (arg )
1416+ continue
1417+ seen_unpack = True
1418+ unpack_types .append (arg )
1419+ else :
1420+ if seen_unpack :
1421+ unpack_types .append (arg )
1422+ else :
1423+ args .append (arg )
1424+ kinds .append (ARG_POS )
1425+ names .append (None )
1426+ if seen_unpack :
1427+ if len (unpack_types ) == 1 :
1428+ args .append (unpack_types [0 ])
14031429 else :
1404- args .append (arg )
1405- kinds .append (ARG_POS )
1406- names .append (None )
1430+ first = unpack_types [0 ]
1431+ if isinstance (first , UnpackType ):
1432+ # UnpackType doesn't have its own line/column numbers,
1433+ # so use the unpacked type for error messages.
1434+ first = first .type
1435+ args .append (
1436+ UnpackType (self .tuple_type (unpack_types , line = first .line , column = first .column ))
1437+ )
1438+ kinds .append (ARG_STAR )
1439+ names .append (None )
1440+ for arg in invalid_unpacks :
1441+ args .append (arg )
1442+ kinds .append (ARG_STAR )
1443+ names .append (None )
14071444 # Note that arglist below is only used for error context.
14081445 check_arg_names (names , [arglist ] * len (args ), self .fail , "Callable" )
14091446 check_arg_kinds (kinds , [arglist ] * len (args ), self .fail )
@@ -1713,9 +1750,11 @@ def check_unpacks_in_list(self, items: list[Type]) -> list[Type]:
17131750 self .fail ("More than one Unpack in a type is not allowed" , final_unpack )
17141751 return new_items
17151752
1716- def tuple_type (self , items : list [Type ]) -> TupleType :
1753+ def tuple_type (self , items : list [Type ], line : int , column : int ) -> TupleType :
17171754 any_type = AnyType (TypeOfAny .special_form )
1718- return TupleType (items , fallback = self .named_type ("builtins.tuple" , [any_type ]))
1755+ return TupleType (
1756+ items , fallback = self .named_type ("builtins.tuple" , [any_type ]), line = line , column = column
1757+ )
17191758
17201759
17211760TypeVarLikeList = List [Tuple [str , TypeVarLikeExpr ]]
0 commit comments