66 TupleType , TypedDictType , ErasedType , UnionType , PartialType , DeletedType ,
77 UninhabitedType , TypeType , TypeOfAny , Overloaded , FunctionLike , LiteralType ,
88 ProperType , get_proper_type , get_proper_types , TypeAliasType , TypeGuardedType ,
9- ParamSpecType , Parameters , UnpackType , TypeVarTupleType ,
9+ ParamSpecType , Parameters , UnpackType , TypeVarTupleType , TypeVarLikeType
1010)
1111from mypy .subtypes import is_equivalent , is_subtype , is_callable_compatible , is_proper_subtype
1212from mypy .erasetype import erase_type
@@ -117,8 +117,8 @@ def get_possible_variants(typ: Type) -> List[Type]:
117117 If this function receives any other type, we return a list containing just that
118118 original type. (E.g. pretend the type was contained within a singleton union).
119119
120- The only exception is regular TypeVars: we return a list containing that TypeVar's
121- upper bound.
120+ The only current exceptions are regular TypeVars and ParamSpecs. For these "TypeVarLike"s,
121+ we return a list containing that TypeVarLike's upper bound.
122122
123123 This function is useful primarily when checking to see if two types are overlapping:
124124 the algorithm to check if two unions are overlapping is fundamentally the same as
@@ -134,6 +134,8 @@ def get_possible_variants(typ: Type) -> List[Type]:
134134 return typ .values
135135 else :
136136 return [typ .upper_bound ]
137+ elif isinstance (typ , ParamSpecType ):
138+ return [typ .upper_bound ]
137139 elif isinstance (typ , UnionType ):
138140 return list (typ .items )
139141 elif isinstance (typ , Overloaded ):
@@ -244,36 +246,36 @@ def _is_overlapping_types(left: Type, right: Type) -> bool:
244246 right_possible = get_possible_variants (right )
245247
246248 # We start by checking multi-variant types like Unions first. We also perform
247- # the same logic if either type happens to be a TypeVar.
249+ # the same logic if either type happens to be a TypeVar/ParamSpec/TypeVarTuple .
248250 #
249- # Handling the TypeVars now lets us simulate having them bind to the corresponding
251+ # Handling the TypeVarLikes now lets us simulate having them bind to the corresponding
250252 # type -- if we deferred these checks, the "return-early" logic of the other
251253 # checks will prevent us from detecting certain overlaps.
252254 #
253- # If both types are singleton variants (and are not TypeVars ), we've hit the base case:
255+ # If both types are singleton variants (and are not TypeVarLikes ), we've hit the base case:
254256 # we skip these checks to avoid infinitely recursing.
255257
256- def is_none_typevar_overlap (t1 : Type , t2 : Type ) -> bool :
258+ def is_none_typevarlike_overlap (t1 : Type , t2 : Type ) -> bool :
257259 t1 , t2 = get_proper_types ((t1 , t2 ))
258- return isinstance (t1 , NoneType ) and isinstance (t2 , TypeVarType )
260+ return isinstance (t1 , NoneType ) and isinstance (t2 , TypeVarLikeType )
259261
260262 if prohibit_none_typevar_overlap :
261- if is_none_typevar_overlap (left , right ) or is_none_typevar_overlap (right , left ):
263+ if is_none_typevarlike_overlap (left , right ) or is_none_typevarlike_overlap (right , left ):
262264 return False
263265
264266 if (len (left_possible ) > 1 or len (right_possible ) > 1
265- or isinstance (left , TypeVarType ) or isinstance (right , TypeVarType )):
267+ or isinstance (left , TypeVarLikeType ) or isinstance (right , TypeVarLikeType )):
266268 for l in left_possible :
267269 for r in right_possible :
268270 if _is_overlapping_types (l , r ):
269271 return True
270272 return False
271273
272- # Now that we've finished handling TypeVars , we're free to end early
274+ # Now that we've finished handling TypeVarLikes , we're free to end early
273275 # if one one of the types is None and we're running in strict-optional mode.
274276 # (None only overlaps with None in strict-optional mode).
275277 #
276- # We must perform this check after the TypeVar checks because
278+ # We must perform this check after the TypeVarLike checks because
277279 # a TypeVar could be bound to None, for example.
278280
279281 if state .strict_optional and isinstance (left , NoneType ) != isinstance (right , NoneType ):
0 commit comments