Skip to content

Commit 8cc1c29

Browse files
renamed and moved function to subtypes
1 parent 5482d98 commit 8cc1c29

File tree

3 files changed

+49
-58
lines changed

3 files changed

+49
-58
lines changed

mypy/checkexpr.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from mypy.checkmember import analyze_member_access, has_operator
2020
from mypy.checkstrformat import StringFormatterChecker
2121
from mypy.constant_fold import constant_fold_expr
22-
from mypy.constraints import SUBTYPE_OF
2322
from mypy.erasetype import erase_type, remove_instance_last_known_values, replace_meta_vars
2423
from mypy.errors import ErrorInfo, ErrorWatcher, report_internal_error
2524
from mypy.expandtype import (
@@ -31,7 +30,7 @@
3130
from mypy.exprtotype import TypeTranslationError, expr_to_unanalyzed_type
3231
from mypy.infer import ArgumentInferContext, infer_function_type_arguments, infer_type_arguments
3332
from mypy.literals import literal
34-
from mypy.maptype import as_type, map_instance_to_supertype
33+
from mypy.maptype import map_instance_to_supertype
3534
from mypy.meet import is_overlapping_types, narrow_declared_type
3635
from mypy.message_registry import ErrorMessage
3736
from mypy.messages import MessageBuilder, format_type
@@ -127,6 +126,7 @@
127126
is_same_type,
128127
is_subtype,
129128
non_method_protocol_members,
129+
solve_as_subtype,
130130
)
131131
from mypy.traverser import (
132132
all_name_and_member_expressions,
@@ -6164,7 +6164,7 @@ def is_valid_keyword_var_arg(self, typ: Type) -> bool:
61646164
"_typeshed.SupportsKeysAndGetItem", [T, AnyType(TypeOfAny.special_form)]
61656165
)
61666166

6167-
return as_type(typ, SUBTYPE_OF, template) is not None
6167+
return solve_as_subtype(typ, template) is not None
61686168

61696169
def not_ready_callback(self, name: str, context: Context) -> None:
61706170
"""Called when we can't infer the type of a variable because it's not ready yet.

mypy/maptype.py

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,8 @@
11
from __future__ import annotations
22

3-
from typing import cast
4-
5-
from mypy.expandtype import expand_type, expand_type_by_instance
3+
from mypy.expandtype import expand_type_by_instance
64
from mypy.nodes import TypeInfo
7-
from mypy.types import AnyType, Instance, TupleType, Type, TypeOfAny, has_type_vars
8-
9-
10-
def as_type(typ: Type, direction: int, target: Type) -> Type | None:
11-
"""Attempts to solve type variables in `target` so that `typ` is a subtype/supertype of
12-
the resulting type.
13-
14-
Args:
15-
typ: The type to map from.
16-
direction: One of SUBTYPE_OF or SUPERTYPE_OF
17-
target: The target instance type to map to.
18-
19-
Returns:
20-
None: if the mapping is not possible.
21-
Type: the mapped type if the mapping is possible.
22-
23-
Examples:
24-
(list[int], Iterable[T]) -> Iterable[int]
25-
(list[list[int]], Iterable[list[T]]) -> Iterable[list[int]]
26-
(dict[str, int], Mapping[K, int]) -> Mapping[str, int]
27-
(list[int], Mapping[K, V]) -> None
28-
"""
29-
from mypy.subtypes import is_subtype
30-
from mypy.typeops import get_all_type_vars
31-
32-
# 1. get type vars of target
33-
tvars = get_all_type_vars(target)
34-
35-
# fast path: if no type vars, just check subtype
36-
if not tvars:
37-
return target if is_subtype(typ, target) else None
38-
39-
from mypy.constraints import SUBTYPE_OF, Constraint, infer_constraints
40-
from mypy.solve import solve_constraints
41-
42-
# 2. determine constraints
43-
constraints: list[Constraint] = infer_constraints(target, typ, not direction)
44-
for tvar in tvars:
45-
# need to manually include these because solve_constraints ignores them
46-
# apparently
47-
constraints.append(Constraint(tvar, SUBTYPE_OF, tvar.upper_bound))
48-
49-
# 3. solve constraints
50-
solution, _ = solve_constraints(tvars, constraints)
51-
52-
if None in solution:
53-
return None
54-
55-
# 4. build resulting Type by substituting type vars with solution
56-
env = {tvar.id: s for tvar, s in zip(tvars, cast("list[Type]", solution))}
57-
target = expand_type(target, env)
58-
return target if is_subtype(typ, target) else None
5+
from mypy.types import AnyType, Instance, TupleType, TypeOfAny, has_type_vars
596

607

618
def map_instance_to_supertype(instance: Instance, superclass: TypeInfo) -> Instance:

mypy/subtypes.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import mypy.constraints
99
import mypy.typeops
1010
from mypy.checker_state import checker_state
11+
from mypy.constraints import SUBTYPE_OF, SUPERTYPE_OF, Constraint, infer_constraints
1112
from mypy.erasetype import erase_type
1213
from mypy.expandtype import (
1314
expand_self_type,
@@ -35,6 +36,7 @@
3536
)
3637
from mypy.options import Options
3738
from mypy.state import state
39+
from mypy.typeops import get_all_type_vars
3840
from mypy.types import (
3941
MYPYC_NATIVE_INT_NAMES,
4042
TUPLE_LIKE_INSTANCE_NAMES,
@@ -2311,3 +2313,45 @@ def is_erased_instance(t: Instance) -> bool:
23112313
elif not isinstance(get_proper_type(arg), AnyType):
23122314
return False
23132315
return True
2316+
2317+
2318+
def solve_as_subtype(typ: Type, target: Type) -> Type | None:
2319+
"""Solves type variables in `target` so that `typ` becomes a subtype of `target`.
2320+
2321+
Returns:
2322+
None: if the mapping is not possible.
2323+
Type: the mapped type if the mapping is possible.
2324+
2325+
Examples:
2326+
(list[int], Iterable[T]) -> Iterable[int]
2327+
(list[list[int]], Iterable[list[T]]) -> Iterable[list[int]]
2328+
(dict[str, int], Mapping[K, int]) -> Mapping[str, int]
2329+
(list[int], Mapping[K, V]) -> None
2330+
"""
2331+
2332+
# 1. get type vars of target
2333+
tvars = get_all_type_vars(target)
2334+
2335+
# fast path: if no type vars, just check subtype
2336+
if not tvars:
2337+
return target if is_subtype(typ, target) else None
2338+
2339+
from mypy.solve import solve_constraints
2340+
2341+
# 2. determine constraints
2342+
constraints: list[Constraint] = infer_constraints(target, typ, SUPERTYPE_OF)
2343+
for tvar in tvars:
2344+
# need to manually include these because solve_constraints ignores them
2345+
# apparently
2346+
constraints.append(Constraint(tvar, SUBTYPE_OF, tvar.upper_bound))
2347+
2348+
# 3. solve constraints
2349+
solution, _ = solve_constraints(tvars, constraints)
2350+
2351+
if None in solution:
2352+
return None
2353+
2354+
# 4. build resulting Type by substituting type vars with solution
2355+
env = {tvar.id: s for tvar, s in zip(tvars, cast("list[Type]", solution))}
2356+
target = expand_type(target, env)
2357+
return target if is_subtype(typ, target) else None

0 commit comments

Comments
 (0)