blob: e871973104a2dd5b32c54d1519fc85ed5d971be1 [file] [log] [blame]
from __future__ import annotations
from mypy.erasetype import erase_typevars
from mypy.nodes import TypeInfo
from mypy.types import (
Instance,
ParamSpecType,
ProperType,
TupleType,
Type,
TypeOfAny,
TypeVarLikeType,
TypeVarTupleType,
TypeVarType,
UnpackType,
)
from mypy.typevartuples import erased_vars
def fill_typevars(typ: TypeInfo) -> Instance | TupleType:
"""For a non-generic type, return instance type representing the type.
For a generic G type with parameters T1, .., Tn, return G[T1, ..., Tn].
"""
tvs: list[Type] = []
# TODO: why do we need to keep both typ.type_vars and typ.defn.type_vars?
for i in range(len(typ.defn.type_vars)):
tv: TypeVarLikeType | UnpackType = typ.defn.type_vars[i]
# Change the line number
if isinstance(tv, TypeVarType):
tv = tv.copy_modified(line=-1, column=-1)
elif isinstance(tv, TypeVarTupleType):
tv = UnpackType(
TypeVarTupleType(
tv.name,
tv.fullname,
tv.id,
tv.upper_bound,
tv.tuple_fallback,
tv.default,
line=-1,
column=-1,
)
)
else:
assert isinstance(tv, ParamSpecType)
tv = ParamSpecType(
tv.name,
tv.fullname,
tv.id,
tv.flavor,
tv.upper_bound,
tv.default,
line=-1,
column=-1,
)
tvs.append(tv)
inst = Instance(typ, tvs)
# TODO: do we need to also handle typeddict_type here and below?
if typ.tuple_type is None:
return inst
return typ.tuple_type.copy_modified(fallback=inst)
def fill_typevars_with_any(typ: TypeInfo) -> Instance | TupleType:
"""Apply a correct number of Any's as type arguments to a type."""
inst = Instance(typ, erased_vars(typ.defn.type_vars, TypeOfAny.special_form))
if typ.tuple_type is None:
return inst
erased_tuple_type = erase_typevars(typ.tuple_type, {tv.id for tv in typ.defn.type_vars})
assert isinstance(erased_tuple_type, ProperType)
if isinstance(erased_tuple_type, TupleType):
return typ.tuple_type.copy_modified(fallback=inst)
return inst
def has_no_typevars(typ: Type) -> bool:
# We test if a type contains type variables by erasing all type variables
# and comparing the result to the original type. We use comparison by equality that
# in turn uses `__eq__` defined for types. Note: we can't use `is_same_type` because
# it is not safe with unresolved forward references, while this function may be called
# before forward references resolution patch pass. Note also that it is not safe to use
# `is` comparison because `erase_typevars` doesn't preserve type identity.
return typ == erase_typevars(typ)