Skip to content

refactor: Use @overload for expand_type #13641

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

Merged
merged 2 commits into from
Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -6762,7 +6762,6 @@ def overload_can_never_match(signature: CallableType, other: CallableType) -> bo
exp_signature = expand_type(
signature, {tvar.id: erase_def_to_union_or_bound(tvar) for tvar in signature.variables}
)
assert isinstance(exp_signature, ProperType)
assert isinstance(exp_signature, CallableType)
return is_callable_compatible(
exp_signature, other, is_compat=is_more_precise, ignore_return=True
Expand Down
2 changes: 1 addition & 1 deletion mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1506,7 +1506,7 @@ def analyze_type_type_callee(self, item: ProperType, context: Context) -> Type:
res = type_object_type(item.type, self.named_type)
if isinstance(res, CallableType):
res = res.copy_modified(from_type_type=True)
expanded = get_proper_type(expand_type_by_instance(res, item))
expanded = expand_type_by_instance(res, item)
if isinstance(expanded, CallableType):
# Callee of the form Type[...] should never be generic, only
# proper class objects can be.
Expand Down
4 changes: 2 additions & 2 deletions mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ def analyze_var(
signature, dispatched_type, var.is_classmethod, mx.context, name, mx.msg
)
signature = bind_self(signature, mx.self_type, var.is_classmethod)
expanded_signature = get_proper_type(expand_type_by_instance(signature, itype))
expanded_signature = expand_type_by_instance(signature, itype)
freeze_type_vars(expanded_signature)
if var.is_property:
# A property cannot have an overloaded type => the cast is fine.
Expand Down Expand Up @@ -1111,7 +1111,7 @@ class B(A[str]): pass
]
)
if isuper is not None:
t = cast(ProperType, expand_type_by_instance(t, isuper))
t = expand_type_by_instance(t, isuper)
return t


Expand Down
25 changes: 21 additions & 4 deletions mypy/expandtype.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Iterable, Mapping, Sequence, TypeVar, cast
from typing import Iterable, Mapping, Sequence, TypeVar, cast, overload

from mypy.types import (
AnyType,
Expand Down Expand Up @@ -37,18 +37,36 @@
from mypy.typevartuples import split_with_instance, split_with_prefix_and_suffix


@overload
def expand_type(typ: ProperType, env: Mapping[TypeVarId, Type]) -> ProperType:
...


@overload
def expand_type(typ: Type, env: Mapping[TypeVarId, Type]) -> Type:
...


def expand_type(typ: Type, env: Mapping[TypeVarId, Type]) -> Type:
"""Substitute any type variable references in a type given by a type
environment.
"""
# TODO: use an overloaded signature? (ProperType stays proper after expansion.)
return typ.accept(ExpandTypeVisitor(env))


@overload
def expand_type_by_instance(typ: ProperType, instance: Instance) -> ProperType:
...


@overload
def expand_type_by_instance(typ: Type, instance: Instance) -> Type:
...


def expand_type_by_instance(typ: Type, instance: Instance) -> Type:
"""Substitute type variables in type using values from an Instance.
Type variables are considered to be bound by the class declaration."""
# TODO: use an overloaded signature? (ProperType stays proper after expansion.)
if not instance.args:
return typ
else:
Expand Down Expand Up @@ -87,7 +105,6 @@ def freshen_function_type_vars(callee: F) -> F:
tvs = []
tvmap: dict[TypeVarId, Type] = {}
for v in callee.variables:
# TODO(PEP612): fix for ParamSpecType
if isinstance(v, TypeVarType):
tv: TypeVarLikeType = TypeVarType.new_unification_variable(v)
elif isinstance(v, TypeVarTupleType):
Expand Down
15 changes: 2 additions & 13 deletions mypy/maptype.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,7 @@
import mypy.typeops
from mypy.expandtype import expand_type
from mypy.nodes import TypeInfo
from mypy.types import (
AnyType,
Instance,
ProperType,
TupleType,
Type,
TypeOfAny,
TypeVarId,
get_proper_type,
has_type_vars,
)
from mypy.types import AnyType, Instance, TupleType, Type, TypeOfAny, TypeVarId, has_type_vars


def map_instance_to_supertype(instance: Instance, superclass: TypeInfo) -> Instance:
Expand All @@ -37,7 +27,7 @@ def map_instance_to_supertype(instance: Instance, superclass: TypeInfo) -> Insta
# Unfortunately we can't support this for generic recursive tuples.
# If we skip this special casing we will fall back to tuple[Any, ...].
env = instance_to_type_environment(instance)
tuple_type = get_proper_type(expand_type(instance.type.tuple_type, env))
tuple_type = expand_type(instance.type.tuple_type, env)
if isinstance(tuple_type, TupleType):
return mypy.typeops.tuple_fallback(tuple_type)

Expand Down Expand Up @@ -101,7 +91,6 @@ def map_instance_to_direct_supertypes(instance: Instance, supertype: TypeInfo) -
if b.type == supertype:
env = instance_to_type_environment(instance)
t = expand_type(b, env)
assert isinstance(t, ProperType)
assert isinstance(t, Instance)
result.append(t)

Expand Down