77
88from __future__ import annotations
99
10- from typing import Callable , Sequence
10+ from typing import Callable
1111
1212from mypy import errorcodes as codes , message_registry
1313from mypy .errorcodes import ErrorCode
@@ -88,7 +88,7 @@ def visit_type_alias_type(self, t: TypeAliasType) -> None:
8888 return
8989 self .seen_aliases .add (t )
9090 assert t .alias is not None , f"Unfixed type alias { t .type_ref } "
91- is_error = self .validate_args (t .alias .name , t .args , t .alias .alias_tvars , t )
91+ is_error = self .validate_args (t .alias .name , tuple ( t .args ) , t .alias .alias_tvars , t )
9292 if not is_error :
9393 # If there was already an error for the alias itself, there is no point in checking
9494 # the expansion, most likely it will result in the same kind of error.
@@ -131,7 +131,7 @@ def visit_instance(self, t: Instance) -> None:
131131 t .args = unpacked .args
132132
133133 def validate_args (
134- self , name : str , args : Sequence [Type ], type_vars : list [TypeVarLikeType ], ctx : Context
134+ self , name : str , args : tuple [Type , ... ], type_vars : list [TypeVarLikeType ], ctx : Context
135135 ) -> bool :
136136 if any (isinstance (v , TypeVarTupleType ) for v in type_vars ):
137137 prefix = next (i for (i , v ) in enumerate (type_vars ) if isinstance (v , TypeVarTupleType ))
@@ -140,7 +140,7 @@ def validate_args(
140140 start , middle , end = split_with_prefix_and_suffix (
141141 tuple (args ), prefix , len (type_vars ) - prefix - 1
142142 )
143- args = list ( start ) + [ TupleType (list (middle ), tvt .tuple_fallback )] + list ( end )
143+ args = start + ( TupleType (list (middle ), tvt .tuple_fallback ),) + end
144144
145145 is_error = False
146146 for (i , arg ), tvar in zip (enumerate (args ), type_vars ):
@@ -174,7 +174,14 @@ def validate_args(
174174 arg_values = [arg ]
175175 if self .check_type_var_values (name , arg_values , tvar .name , tvar .values , ctx ):
176176 is_error = True
177- if not is_subtype (arg , tvar .upper_bound ):
177+ # Check against upper bound. Since it's object the vast majority of the time,
178+ # add fast path to avoid a potentially slow subtype check.
179+ upper_bound = tvar .upper_bound
180+ object_upper_bound = (
181+ type (upper_bound ) is Instance
182+ and upper_bound .type .fullname == "builtins.object"
183+ )
184+ if not object_upper_bound and not is_subtype (arg , upper_bound ):
178185 if self .in_type_alias_expr and isinstance (arg , TypeVarType ):
179186 # Type aliases are allowed to use unconstrained type variables
180187 # error will be checked at substitution point.
@@ -184,7 +191,7 @@ def validate_args(
184191 message_registry .INVALID_TYPEVAR_ARG_BOUND .format (
185192 format_type (arg , self .options ),
186193 name ,
187- format_type (tvar . upper_bound , self .options ),
194+ format_type (upper_bound , self .options ),
188195 ),
189196 ctx ,
190197 code = codes .TYPE_VAR ,
0 commit comments