@@ -140,7 +140,9 @@ def visit_type_alias_type(self, t: TypeAliasType) -> ProperType:
140140 raise RuntimeError ("Type aliases should be expanded before accepting this visitor" )
141141
142142
143- def erase_typevars (t : Type , ids_to_erase : Container [TypeVarId ] | None = None ) -> Type :
143+ def erase_typevars (
144+ t : Type , ids_to_erase : Container [TypeVarId ] | None = None , use_upper_bound : bool = False
145+ ) -> Type :
144146 """Replace all type variables in a type with any,
145147 or just the ones in the provided collection.
146148 """
@@ -150,7 +152,7 @@ def erase_id(id: TypeVarId) -> bool:
150152 return True
151153 return id in ids_to_erase
152154
153- return t .accept (TypeVarEraser (erase_id , AnyType (TypeOfAny .special_form )))
155+ return t .accept (TypeVarEraser (erase_id , AnyType (TypeOfAny .special_form ), use_upper_bound ))
154156
155157
156158def replace_meta_vars (t : Type , target_type : Type ) -> Type :
@@ -161,13 +163,21 @@ def replace_meta_vars(t: Type, target_type: Type) -> Type:
161163class TypeVarEraser (TypeTranslator ):
162164 """Implementation of type erasure"""
163165
164- def __init__ (self , erase_id : Callable [[TypeVarId ], bool ], replacement : Type ) -> None :
166+ def __init__ (
167+ self ,
168+ erase_id : Callable [[TypeVarId ], bool ],
169+ replacement : Type ,
170+ use_upper_bound : bool = False ,
171+ ) -> None :
165172 super ().__init__ ()
166173 self .erase_id = erase_id
167174 self .replacement = replacement
175+ self .use_upper_bound = use_upper_bound
168176
169177 def visit_type_var (self , t : TypeVarType ) -> Type :
170178 if self .erase_id (t .id ):
179+ if self .use_upper_bound :
180+ return t .upper_bound
171181 return self .replacement
172182 return t
173183
@@ -204,11 +214,16 @@ def visit_tuple_type(self, t: TupleType) -> Type:
204214 return result
205215
206216 def visit_callable_type (self , t : CallableType ) -> Type :
217+ use_upper_bound = self .use_upper_bound
218+ # This is to work around the fact that erased callables are not compatible
219+ # with non-erased ones (due to contravariance in arg types).
220+ self .use_upper_bound = False
207221 result = super ().visit_callable_type (t )
208222 assert isinstance (result , ProperType ) and isinstance (result , CallableType )
209223 # Usually this is done in semanal_typeargs.py, but erasure can create
210224 # a non-normal callable from normal one.
211225 result .normalize_trivial_unpack ()
226+ self .use_upper_bound = use_upper_bound
212227 return result
213228
214229 def visit_type_var_tuple (self , t : TypeVarTupleType ) -> Type :
0 commit comments