Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge TypeVarDef and TypeVarType #9951

Merged
merged 13 commits into from
Aug 4, 2021
Merged
10 changes: 5 additions & 5 deletions mypy/applytype.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@
from mypy.expandtype import expand_type
from mypy.types import (
Type, TypeVarId, TypeVarType, CallableType, AnyType, PartialType, get_proper_types,
TypeVarDef, TypeVarLikeDef, ProperType, ParamSpecDef
TypeVarLikeType, ProperType, ParamSpecType
)
from mypy.nodes import Context


def get_target_type(
tvar: TypeVarLikeDef,
tvar: TypeVarLikeType,
type: ProperType,
callable: CallableType,
report_incompatible_typevar_value: Callable[[CallableType, Type, str, Context], None],
context: Context,
skip_unsatisfied: bool
) -> Optional[Type]:
# TODO(shantanu): fix for ParamSpecDef
if isinstance(tvar, ParamSpecDef):
# TODO(shantanu): fix for ParamSpecType
if isinstance(tvar, ParamSpecType):
return None
assert isinstance(tvar, TypeVarDef)
assert isinstance(tvar, TypeVarType)
values = get_proper_types(tvar.values)
if values:
if isinstance(type, AnyType):
Expand Down
6 changes: 3 additions & 3 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from mypy.types import (
Type, AnyType, CallableType, FunctionLike, Overloaded, TupleType, TypedDictType,
Instance, NoneType, strip_type, TypeType, TypeOfAny,
UnionType, TypeVarId, TypeVarType, PartialType, DeletedType, UninhabitedType, TypeVarDef,
UnionType, TypeVarId, TypeVarType, PartialType, DeletedType, UninhabitedType,
is_named_instance, union_items, TypeQuery, LiteralType,
is_optional, remove_optional, TypeTranslator, StarType, get_proper_type, ProperType,
get_proper_types, is_literal_type, TypeAliasType, TypeGuardType)
Expand Down Expand Up @@ -1403,7 +1403,7 @@ def expand_typevars(self, defn: FuncItem,
tvars += defn.info.defn.type_vars or []
# TODO(shantanu): audit for paramspec
for tvar in tvars:
if isinstance(tvar, TypeVarDef) and tvar.values:
if isinstance(tvar, TypeVarType) and tvar.values:
subst.append([(tvar.id, value) for value in tvar.values])
# Make a copy of the function to check for each combination of
# value restricted type variables. (Except when running mypyc,
Expand Down Expand Up @@ -5504,7 +5504,7 @@ def detach_callable(typ: CallableType) -> CallableType:
for var in set(all_type_vars):
if var.fullname not in used_type_var_names:
continue
new_variables.append(TypeVarDef(
new_variables.append(TypeVarType(
name=var.name,
fullname=var.fullname,
id=var.id,
Expand Down
68 changes: 31 additions & 37 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
make_optional_type,
)
from mypy.types import (
Type, AnyType, CallableType, Overloaded, NoneType, TypeGuardType, TypeVarDef,
TupleType, TypedDictType, Instance, TypeVarType, ErasedType, UnionType,
Type, AnyType, CallableType, Overloaded, NoneType, TypeVarType, TypeGuardType,
TupleType, TypedDictType, Instance, ErasedType, UnionType,
PartialType, DeletedType, UninhabitedType, TypeType, TypeOfAny, LiteralType, LiteralValue,
is_named_instance, FunctionLike, ParamSpecDef,
is_named_instance, FunctionLike, ParamSpecType,
StarType, is_optional, remove_optional, is_generic_instance, get_proper_type, ProperType,
get_proper_types, flatten_nested_unions
)
Expand Down Expand Up @@ -1904,8 +1904,8 @@ def combine_function_signatures(self, types: Sequence[Type]) -> Union[AnyType, C
# same thing.
#
# This function will make sure that all instances of that TypeVar 'T'
# refer to the same underlying TypeVarType and TypeVarDef objects to
# simplify the union-ing logic below.
# refer to the same underlying TypeVarType objects to simplify the union-ing
# logic below.
#
# (If the user did *not* mean for 'T' to be consistently bound to the
# same type in their overloads, well, their code is probably too
Expand Down Expand Up @@ -3277,16 +3277,15 @@ def check_lst_expr(self, items: List[Expression], fullname: str,
# Used for list and set expressions, as well as for tuples
# containing star expressions that don't refer to a
# Tuple. (Note: "lst" stands for list-set-tuple. :-)
tvdef = TypeVarDef('T', 'T', -1, [], self.object_type())
tv = TypeVarType(tvdef)
tv = TypeVarType('T', 'T', -1, [], self.object_type())
constructor = CallableType(
[tv],
[nodes.ARG_STAR],
[None],
self.chk.named_generic_type(fullname, [tv]),
self.named_type('builtins.function'),
name=tag,
variables=[tvdef])
variables=[tv])
out = self.check_call(constructor,
[(i.expr if isinstance(i, StarExpr) else i)
for i in items],
Expand Down Expand Up @@ -3435,10 +3434,8 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
tup.column = value.column
args.append(tup)
# Define type variables (used in constructors below).
ktdef = TypeVarDef('KT', 'KT', -1, [], self.object_type())
vtdef = TypeVarDef('VT', 'VT', -2, [], self.object_type())
kt = TypeVarType(ktdef)
vt = TypeVarType(vtdef)
kt = TypeVarType('KT', 'KT', -1, [], self.object_type())
vt = TypeVarType('VT', 'VT', -2, [], self.object_type())
rv = None
# Call dict(*args), unless it's empty and stargs is not.
if args or not stargs:
Expand All @@ -3452,7 +3449,7 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
self.chk.named_generic_type('builtins.dict', [kt, vt]),
self.named_type('builtins.function'),
name='<dict>',
variables=[ktdef, vtdef])
variables=[kt, vt])
rv = self.check_call(constructor, args, [nodes.ARG_POS] * len(args), e)[0]
else:
# dict(...) will be called below.
Expand All @@ -3469,7 +3466,7 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
self.chk.named_generic_type('builtins.dict', [kt, vt]),
self.named_type('builtins.function'),
name='<list>',
variables=[ktdef, vtdef])
variables=[kt, vt])
rv = self.check_call(constructor, [arg], [nodes.ARG_POS], arg)[0]
else:
self.check_method_call_by_name('update', rv, [arg], [nodes.ARG_POS], arg)
Expand Down Expand Up @@ -3759,16 +3756,16 @@ def check_generator_or_comprehension(self, gen: GeneratorExpr,

# Infer the type of the list comprehension by using a synthetic generic
# callable type.
tvdef = TypeVarDef('T', 'T', -1, [], self.object_type())
tv_list: List[Type] = [TypeVarType(tvdef)]
tv = TypeVarType('T', 'T', -1, [], self.object_type())
tv_list: List[Type] = [tv]
constructor = CallableType(
tv_list,
[nodes.ARG_POS],
[None],
self.chk.named_generic_type(type_name, tv_list + additional_args),
self.chk.named_type('builtins.function'),
name=id_for_messages,
variables=[tvdef])
variables=[tv])
return self.check_call(constructor,
[gen.left_expr], [nodes.ARG_POS], gen)[0]

Expand All @@ -3779,15 +3776,13 @@ def visit_dictionary_comprehension(self, e: DictionaryComprehension) -> Type:

# Infer the type of the list comprehension by using a synthetic generic
# callable type.
ktdef = TypeVarDef('KT', 'KT', -1, [], self.object_type())
vtdef = TypeVarDef('VT', 'VT', -2, [], self.object_type())
kt = TypeVarType(ktdef)
vt = TypeVarType(vtdef)
ktdef = TypeVarType('KT', 'KT', -1, [], self.object_type())
vtdef = TypeVarType('VT', 'VT', -2, [], self.object_type())
constructor = CallableType(
[kt, vt],
[ktdef, vtdef],
[nodes.ARG_POS, nodes.ARG_POS],
[None, None],
self.chk.named_generic_type('builtins.dict', [kt, vt]),
self.chk.named_generic_type('builtins.dict', [ktdef, vtdef]),
self.chk.named_type('builtins.function'),
name='<dictionary-comprehension>',
variables=[ktdef, vtdef])
Expand Down Expand Up @@ -4450,7 +4445,7 @@ def all_same_types(types: List[Type]) -> bool:


def merge_typevars_in_callables_by_name(
callables: Sequence[CallableType]) -> Tuple[List[CallableType], List[TypeVarDef]]:
callables: Sequence[CallableType]) -> Tuple[List[CallableType], List[TypeVarType]]:
"""Takes all the typevars present in the callables and 'combines' the ones with the same name.

For example, suppose we have two callables with signatures "f(x: T, y: S) -> T" and
Expand All @@ -4459,34 +4454,33 @@ def merge_typevars_in_callables_by_name(
distinct ids.)

If we pass in both callables into this function, it returns a a list containing two
new callables that are identical in signature, but use the same underlying TypeVarDef
and TypeVarType objects for T and S.
new callables that are identical in signature, but use the same underlying TypeVarType
for T and S.

This is useful if we want to take the output lists and "merge" them into one callable
in some way -- for example, when unioning together overloads.

Returns both the new list of callables and a list of all distinct TypeVarDef objects used.
Returns both the new list of callables and a list of all distinct TypeVarType objects used.
"""

output: List[CallableType] = []
unique_typevars: Dict[str, TypeVarType] = {}
variables: List[TypeVarDef] = []
variables: List[TypeVarType] = []

for target in callables:
if target.is_generic():
target = freshen_function_type_vars(target)

rename = {} # Dict[TypeVarId, TypeVar]
for tvdef in target.variables:
name = tvdef.fullname
for tv in target.variables:
name = tv.fullname
if name not in unique_typevars:
# TODO(shantanu): fix for ParamSpecDef
if isinstance(tvdef, ParamSpecDef):
# TODO(shantanu): fix for ParamSpecType
if isinstance(tv, ParamSpecType):
continue
assert isinstance(tvdef, TypeVarDef)
unique_typevars[name] = TypeVarType(tvdef)
variables.append(tvdef)
rename[tvdef.id] = unique_typevars[name]
assert isinstance(tv, TypeVarType)
unique_typevars[name] = tv
variables.append(tv)
rename[tv.id] = unique_typevars[name]

target = cast(CallableType, expand_type(target, rename))
output.append(target)
Expand Down
6 changes: 3 additions & 3 deletions mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from mypy.types import (
Type, Instance, AnyType, TupleType, TypedDictType, CallableType, FunctionLike,
TypeVarLikeDef, Overloaded, TypeVarType, UnionType, PartialType, TypeOfAny, LiteralType,
TypeVarLikeType, Overloaded, TypeVarType, UnionType, PartialType, TypeOfAny, LiteralType,
DeletedType, NoneType, TypeType, has_type_vars, get_proper_type, ProperType
)
from mypy.nodes import (
Expand Down Expand Up @@ -695,7 +695,7 @@ def analyze_class_attribute_access(itype: Instance,
name: str,
mx: MemberContext,
override_info: Optional[TypeInfo] = None,
original_vars: Optional[Sequence[TypeVarLikeDef]] = None
original_vars: Optional[Sequence[TypeVarLikeType]] = None
) -> Optional[Type]:
"""Analyze access to an attribute on a class object.

Expand Down Expand Up @@ -858,7 +858,7 @@ def analyze_enum_class_attribute_access(itype: Instance,
def add_class_tvars(t: ProperType, isuper: Optional[Instance],
is_classmethod: bool,
original_type: Type,
original_vars: Optional[Sequence[TypeVarLikeDef]] = None) -> Type:
original_vars: Optional[Sequence[TypeVarLikeType]] = None) -> Type:
"""Instantiate type variables during analyze_class_attribute_access,
e.g T and Q in the following:

Expand Down
20 changes: 10 additions & 10 deletions mypy/expandtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
Type, Instance, CallableType, TypeGuardType, TypeVisitor, UnboundType, AnyType,
NoneType, TypeVarType, Overloaded, TupleType, TypedDictType, UnionType,
ErasedType, PartialType, DeletedType, UninhabitedType, TypeType, TypeVarId,
FunctionLike, TypeVarDef, LiteralType, get_proper_type, ProperType,
TypeAliasType, ParamSpecDef
FunctionLike, TypeVarType, LiteralType, get_proper_type, ProperType,
TypeAliasType, ParamSpecType
)


Expand Down Expand Up @@ -38,17 +38,17 @@ def freshen_function_type_vars(callee: F) -> F:
if isinstance(callee, CallableType):
if not callee.is_generic():
return cast(F, callee)
tvdefs = []
tvs = []
tvmap: Dict[TypeVarId, Type] = {}
for v in callee.variables:
# TODO(shantanu): fix for ParamSpecDef
if isinstance(v, ParamSpecDef):
# TODO(shantanu): fix for ParamSpecType
if isinstance(v, ParamSpecType):
continue
assert isinstance(v, TypeVarDef)
tvdef = TypeVarDef.new_unification_variable(v)
tvdefs.append(tvdef)
tvmap[v.id] = TypeVarType(tvdef)
fresh = cast(CallableType, expand_type(callee, tvmap)).copy_modified(variables=tvdefs)
assert isinstance(v, TypeVarType)
tv = TypeVarType.new_unification_variable(v)
tvs.append(tv)
tvmap[v.id] = tv
fresh = cast(CallableType, expand_type(callee, tvmap)).copy_modified(variables=tvs)
return cast(F, fresh)
else:
assert isinstance(callee, Overloaded)
Expand Down
4 changes: 2 additions & 2 deletions mypy/fixup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from mypy.types import (
CallableType, Instance, Overloaded, TupleType, TypeGuardType, TypedDictType,
TypeVarType, UnboundType, UnionType, TypeVisitor, LiteralType,
TypeType, NOT_READY, TypeAliasType, AnyType, TypeOfAny, TypeVarDef
TypeType, NOT_READY, TypeAliasType, AnyType, TypeOfAny
)
from mypy.visitor import NodeVisitor
from mypy.lookup import lookup_fully_qualified
Expand Down Expand Up @@ -184,7 +184,7 @@ def visit_callable_type(self, ct: CallableType) -> None:
if ct.ret_type is not None:
ct.ret_type.accept(self)
for v in ct.variables:
if isinstance(v, TypeVarDef):
if isinstance(v, TypeVarType):
if v.values:
for val in v.values:
val.accept(self)
Expand Down
6 changes: 3 additions & 3 deletions mypy/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from mypy.errors import Errors
from mypy.types import (
Type, CallableType, Instance, TypeVarType, TupleType, TypedDictType, LiteralType,
UnionType, NoneType, AnyType, Overloaded, FunctionLike, DeletedType, TypeType, TypeVarDef,
UnionType, NoneType, AnyType, Overloaded, FunctionLike, DeletedType, TypeType, TypeVarType,
UninhabitedType, TypeOfAny, UnboundType, PartialType, get_proper_type, ProperType,
get_proper_types
)
Expand Down Expand Up @@ -1971,7 +1971,7 @@ def [T <: int] f(self, x: int, y: T) -> None
if tp.variables:
tvars = []
for tvar in tp.variables:
if isinstance(tvar, TypeVarDef):
if isinstance(tvar, TypeVarType):
upper_bound = get_proper_type(tvar.upper_bound)
if (isinstance(upper_bound, Instance) and
upper_bound.type.fullname != 'builtins.object'):
Expand All @@ -1983,7 +1983,7 @@ def [T <: int] f(self, x: int, y: T) -> None
else:
tvars.append(tvar.name)
else:
# For other TypeVarLikeDefs, just use the repr
# For other TypeVarLikeTypes, just use the repr
tvars.append(repr(tvar))
s = '[{}] {}'.format(', '.join(tvars), s)
return 'def {}'.format(s)
Expand Down
7 changes: 3 additions & 4 deletions mypy/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,11 +921,10 @@ def deserialize(cls, data: JsonDict) -> 'Var':

class ClassDef(Statement):
"""Class definition"""

name: str # Name of the class without module prefix
fullname: Bogus[str] = None # type: ignore # Fully qualified name of the class
defs: "Block"
type_vars: List["mypy.types.TypeVarDef"]
type_vars: List["mypy.types.TypeVarType"]
# Base class expressions (not semantically analyzed -- can be arbitrary expressions)
base_type_exprs: List[Expression]
# Special base classes like Generic[...] get moved here during semantic analysis
Expand All @@ -940,7 +939,7 @@ class ClassDef(Statement):
def __init__(self,
name: str,
defs: 'Block',
type_vars: Optional[List['mypy.types.TypeVarDef']] = None,
type_vars: Optional[List['mypy.types.TypeVarType']] = None,
base_type_exprs: Optional[List[Expression]] = None,
metaclass: Optional[Expression] = None,
keywords: Optional[List[Tuple[str, Expression]]] = None) -> None:
Expand Down Expand Up @@ -975,7 +974,7 @@ def deserialize(self, data: JsonDict) -> 'ClassDef':
assert data['.class'] == 'ClassDef'
res = ClassDef(data['name'],
Block([]),
[mypy.types.TypeVarDef.deserialize(v) for v in data['type_vars']],
[mypy.types.TypeVarType.deserialize(v) for v in data['type_vars']],
)
res.fullname = data['fullname']
return res
Expand Down
Loading