1
1
from __future__ import annotations
2
2
3
+ from contextlib import contextmanager
3
4
from typing import Final , Iterable , Mapping , Sequence , TypeVar , cast , overload
4
5
5
6
from mypy .nodes import ARG_STAR , FakeInfo , Var
@@ -185,6 +186,16 @@ def __init__(self, variables: Mapping[TypeVarId, Type]) -> None:
185
186
super ().__init__ ()
186
187
self .variables = variables
187
188
self .recursive_tvar_guard : dict [TypeVarId , Type | None ] = {}
189
+ self ._erase_literals = False
190
+
191
+ @contextmanager
192
+ def erase_literals (self ):
193
+ _erase_literals = self ._erase_literals
194
+ self ._erase_literals = True
195
+ try :
196
+ yield
197
+ finally :
198
+ self ._erase_literals = _erase_literals
188
199
189
200
def visit_unbound_type (self , t : UnboundType ) -> Type :
190
201
return t
@@ -211,7 +222,8 @@ def visit_erased_type(self, t: ErasedType) -> Type:
211
222
return t
212
223
213
224
def visit_instance (self , t : Instance ) -> Type :
214
- args = self .expand_types_with_unpack (list (t .args ))
225
+ with self .erase_literals ():
226
+ args = self .expand_types_with_unpack (list (t .args ))
215
227
216
228
if isinstance (t .type , FakeInfo ):
217
229
# The type checker expands function definitions and bodies
@@ -238,7 +250,7 @@ def visit_type_var(self, t: TypeVarType) -> Type:
238
250
if t .id .is_self ():
239
251
t = t .copy_modified (upper_bound = t .upper_bound .accept (self ))
240
252
repl = self .variables .get (t .id , t )
241
- if isinstance (repl , ProperType ) and isinstance (repl , Instance ):
253
+ if self . _erase_literals and isinstance (repl , ProperType ) and isinstance (repl , Instance ):
242
254
# TODO: do we really need to do this?
243
255
# If I try to remove this special-casing ~40 tests fail on reveal_type().
244
256
return repl .copy_modified (last_known_value = None )
@@ -410,17 +422,18 @@ def visit_callable_type(self, t: CallableType) -> CallableType:
410
422
411
423
var_arg = t .var_arg ()
412
424
needs_normalization = False
413
- if var_arg is not None and isinstance (var_arg .typ , UnpackType ):
414
- needs_normalization = True
415
- arg_types = self .interpolate_args_for_unpack (t , var_arg .typ )
416
- else :
417
- arg_types = self .expand_types (t .arg_types )
418
- expanded = t .copy_modified (
419
- arg_types = arg_types ,
420
- ret_type = t .ret_type .accept (self ),
421
- type_guard = t .type_guard and cast (TypeGuardType , t .type_guard .accept (self )),
422
- type_is = (t .type_is .accept (self ) if t .type_is is not None else None ),
423
- )
425
+ with self .erase_literals ():
426
+ if var_arg is not None and isinstance (var_arg .typ , UnpackType ):
427
+ needs_normalization = True
428
+ arg_types = self .interpolate_args_for_unpack (t , var_arg .typ )
429
+ else :
430
+ arg_types = self .expand_types (t .arg_types )
431
+ expanded = t .copy_modified (
432
+ arg_types = arg_types ,
433
+ ret_type = t .ret_type .accept (self ),
434
+ type_guard = t .type_guard and cast (TypeGuardType , t .type_guard .accept (self )),
435
+ type_is = (t .type_is .accept (self ) if t .type_is is not None else None ),
436
+ )
424
437
if needs_normalization :
425
438
return expanded .with_normalized_var_args ()
426
439
return expanded
@@ -467,7 +480,9 @@ def visit_typeddict_type(self, t: TypedDictType) -> Type:
467
480
return cached
468
481
fallback = t .fallback .accept (self )
469
482
assert isinstance (fallback , ProperType ) and isinstance (fallback , Instance )
470
- result = t .copy_modified (item_types = self .expand_types (t .items .values ()), fallback = fallback )
483
+ with self .erase_literals ():
484
+ # TODO: we don't want to erase literals for `ReadOnly` keys
485
+ result = t .copy_modified (item_types = self .expand_types (t .items .values ()), fallback = fallback )
471
486
self .set_cached (t , result )
472
487
return result
473
488
0 commit comments