Skip to content

Commit

Permalink
Replace TypeList in constraints with TupleType (#14257)
Browse files Browse the repository at this point in the history
Now that the fallback is available, we can construct TupleTypes instead
of TypeLists which will simplify constraint solving as it won't need to
know to match TupleTypes with TypeLists.
  • Loading branch information
jhance authored Dec 6, 2022
1 parent dde01d6 commit 7da2abf
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 14 deletions.
22 changes: 16 additions & 6 deletions mypy/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
Type,
TypeAliasType,
TypedDictType,
TypeList,
TypeOfAny,
TypeQuery,
TypeType,
Expand Down Expand Up @@ -135,7 +134,13 @@ def infer_constraints_for_callable(

unpacked_type = get_proper_type(unpack_type.type)
if isinstance(unpacked_type, TypeVarTupleType):
constraints.append(Constraint(unpacked_type, SUPERTYPE_OF, TypeList(actual_types)))
constraints.append(
Constraint(
unpacked_type,
SUPERTYPE_OF,
TupleType(actual_types, unpacked_type.tuple_fallback),
)
)
elif isinstance(unpacked_type, TupleType):
# Prefixes get converted to positional args, so technically the only case we
# should have here is like Tuple[Unpack[Ts], Y1, Y2, Y3]. If this turns out
Expand All @@ -147,12 +152,13 @@ def infer_constraints_for_callable(
suffix_len = len(unpacked_type.items) - 1
constraints.append(
Constraint(
inner_unpacked_type, SUPERTYPE_OF, TypeList(actual_types[:-suffix_len])
inner_unpacked_type,
SUPERTYPE_OF,
TupleType(actual_types[:-suffix_len], inner_unpacked_type.tuple_fallback),
)
)
else:
assert False, "mypy bug: unhandled constraint inference case"

else:
for actual in actuals:
actual_arg_type = arg_types[actual]
Expand Down Expand Up @@ -640,7 +646,9 @@ def visit_instance(self, template: Instance) -> list[Constraint]:
if isinstance(instance_unpack, TypeVarTupleType):
res.append(
Constraint(
instance_unpack, SUBTYPE_OF, TypeList(list(mapped_middle))
instance_unpack,
SUBTYPE_OF,
TupleType(list(mapped_middle), instance_unpack.tuple_fallback),
)
)
elif (
Expand Down Expand Up @@ -742,7 +750,9 @@ def visit_instance(self, template: Instance) -> list[Constraint]:
if isinstance(template_unpack, TypeVarTupleType):
res.append(
Constraint(
template_unpack, SUPERTYPE_OF, TypeList(list(mapped_middle))
template_unpack,
SUPERTYPE_OF,
TupleType(list(mapped_middle), template_unpack.tuple_fallback),
)
)
elif (
Expand Down
7 changes: 3 additions & 4 deletions mypy/expandtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
Type,
TypeAliasType,
TypedDictType,
TypeList,
TypeType,
TypeVarId,
TypeVarLikeType,
Expand Down Expand Up @@ -95,7 +94,9 @@ def expand_type_by_instance(typ: Type, instance: Instance) -> Type:
instance.type.type_var_tuple_prefix,
instance.type.type_var_tuple_suffix,
)
variables = {tvars_middle[0].id: TypeList(list(args_middle))}
tvar = tvars_middle[0]
assert isinstance(tvar, TypeVarTupleType)
variables = {tvar.id: TupleType(list(args_middle), tvar.tuple_fallback)}
instance_args = args_prefix + args_suffix
tvars = tvars_prefix + tvars_suffix
else:
Expand Down Expand Up @@ -447,8 +448,6 @@ def expand_unpack_with_variables(
repl = get_proper_type(variables.get(t.type.id, t))
if isinstance(repl, TupleType):
return repl.items
if isinstance(repl, TypeList):
return repl.items
elif isinstance(repl, Instance) and repl.type.fullname == "builtins.tuple":
return repl
elif isinstance(repl, AnyType):
Expand Down
16 changes: 12 additions & 4 deletions mypy/test/testconstraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from mypy.constraints import SUBTYPE_OF, SUPERTYPE_OF, Constraint, infer_constraints
from mypy.test.helpers import Suite
from mypy.test.typefixture import TypeFixture
from mypy.types import Instance, TupleType, TypeList, UnpackType
from mypy.types import Instance, TupleType, UnpackType


class ConstraintsSuite(Suite):
Expand All @@ -27,13 +27,19 @@ def test_basic_type_var_tuple_subtype(self) -> None:
fx = self.fx
assert infer_constraints(
Instance(fx.gvi, [UnpackType(fx.ts)]), Instance(fx.gvi, [fx.a, fx.b]), SUBTYPE_OF
) == [Constraint(type_var=fx.ts, op=SUBTYPE_OF, target=TypeList([fx.a, fx.b]))]
) == [
Constraint(type_var=fx.ts, op=SUBTYPE_OF, target=TupleType([fx.a, fx.b], fx.std_tuple))
]

def test_basic_type_var_tuple(self) -> None:
fx = self.fx
assert infer_constraints(
Instance(fx.gvi, [UnpackType(fx.ts)]), Instance(fx.gvi, [fx.a, fx.b]), SUPERTYPE_OF
) == [Constraint(type_var=fx.ts, op=SUPERTYPE_OF, target=TypeList([fx.a, fx.b]))]
) == [
Constraint(
type_var=fx.ts, op=SUPERTYPE_OF, target=TupleType([fx.a, fx.b], fx.std_tuple)
)
]

def test_type_var_tuple_with_prefix_and_suffix(self) -> None:
fx = self.fx
Expand All @@ -45,7 +51,9 @@ def test_type_var_tuple_with_prefix_and_suffix(self) -> None:
)
) == {
Constraint(type_var=fx.t, op=SUPERTYPE_OF, target=fx.a),
Constraint(type_var=fx.ts, op=SUPERTYPE_OF, target=TypeList([fx.b, fx.c])),
Constraint(
type_var=fx.ts, op=SUPERTYPE_OF, target=TupleType([fx.b, fx.c], fx.std_tuple)
),
Constraint(type_var=fx.s, op=SUPERTYPE_OF, target=fx.d),
}

Expand Down

0 comments on commit 7da2abf

Please sign in to comment.