Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

New type inference: complete transitive closure#15754

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
16 commits
Select commitHold shift + click to select a range
e460189
Start with a plan (and a test)
ilevkivskyiJun 23, 2023
495259b
Make small progress
ilevkivskyiJul 2, 2023
52f0428
Merge remote-tracking branch 'upstream/master' into fix-generic-infer…
ilevkivskyiJul 2, 2023
c9e4454
Complete transitive closure (not used correctly yet)
ilevkivskyiJul 16, 2023
e30c057
Correctly use full algorithm
ilevkivskyiJul 20, 2023
71e46cc
Make some progress
ilevkivskyiJul 22, 2023
9b0aa19
Complete feature work
ilevkivskyiJul 22, 2023
b43f286
Fix partial types (and TypeVarTuple)
ilevkivskyiJul 23, 2023
b0ddd6d
Some simplifications; better docs/comments
ilevkivskyiJul 23, 2023
9dd613d
Merge remote-tracking branch 'upstream/master' into fix-generic-infer…
ilevkivskyiJul 23, 2023
49d5415
Add another comment
ilevkivskyiJul 23, 2023
99699c3
Fix xfail
ilevkivskyiJul 23, 2023
bfc7ffc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot]Jul 23, 2023
1018146
Fix infinite loop
ilevkivskyiJul 23, 2023
db9df71
Fix a bug in detach_callable
ilevkivskyiJul 26, 2023
ab8a6c2
Flip the default back
ilevkivskyiJul 26, 2023
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
PrevPrevious commit
NextNext commit
Make small progress
  • Loading branch information
@ilevkivskyi
ilevkivskyi committedJul 2, 2023
commit495259b9c3e43bdff719707c6936fcd407560b24
32 changes: 24 additions & 8 deletionsmypy/constraints.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -74,6 +74,10 @@ def __init__(self, type_var: TypeVarLikeType, op: int, target: Type) -> None:
self.op = op
self.target = target
self.origin_type_var = type_var
# These are additional type variables that should be solved for together with type_var.
# TODO: A cleaner solution may be to modify the return type of infer_constraints()
# to include these instead, but this is a rather big refactoring.
self.extra_tvars: list[TypeVarLikeType] = []

def __repr__(self) -> str:
op_str = "<:"
Expand DownExpand Up@@ -169,7 +173,9 @@ def infer_constraints_for_callable(
return constraints


def infer_constraints(template: Type, actual: Type, direction: int) -> list[Constraint]:
def infer_constraints(
template: Type, actual: Type, direction: int, skip_neg_op: bool = False
) -> list[Constraint]:
"""Infer type constraints.

Match a template type, which may contain type variable references,
Expand DownExpand Up@@ -203,13 +209,15 @@ def infer_constraints(template: Type, actual: Type, direction: int) -> list[Cons
# Return early on an empty branch.
return []
type_state.inferring.append((template, actual))
res = _infer_constraints(template, actual, direction)
res = _infer_constraints(template, actual, direction, skip_neg_op)
type_state.inferring.pop()
return res
return _infer_constraints(template, actual, direction)
return _infer_constraints(template, actual, direction, skip_neg_op)


def _infer_constraints(template: Type, actual: Type, direction: int) -> list[Constraint]:
def _infer_constraints(
template: Type, actual: Type, direction: int, skip_neg_op: bool
) -> list[Constraint]:
orig_template = template
template = get_proper_type(template)
actual = get_proper_type(actual)
Expand DownExpand Up@@ -285,7 +293,7 @@ def _infer_constraints(template: Type, actual: Type, direction: int) -> list[Con
return []

# Remaining cases are handled by ConstraintBuilderVisitor.
return template.accept(ConstraintBuilderVisitor(actual, direction))
return template.accept(ConstraintBuilderVisitor(actual, direction, skip_neg_op))


def infer_constraints_if_possible(
Expand DownExpand Up@@ -511,10 +519,14 @@ class ConstraintBuilderVisitor(TypeVisitor[List[Constraint]]):
# TODO: The value may be None. Is that actually correct?
actual: ProperType

def __init__(self, actual: ProperType, direction: int) -> None:
def __init__(self, actual: ProperType, direction: int, skip_neg_op: bool) -> None:
# Direction must be SUBTYPE_OF or SUPERTYPE_OF.
self.actual = actual
self.direction = direction
# Whether to skip polymorphic inference (involves inference in opposite direction)
# this is used to prevent infinite recursion when both template and actual are
# generic callables.
self.skip_neg_op = skip_neg_op

# Trivial leaf types

Expand DownExpand Up@@ -880,6 +892,7 @@ def visit_callable_type(self, template: CallableType) -> list[Constraint]:
# Note that non-normalized callables can be created in annotations
# using e.g. callback protocols.
template = template.with_unpacked_kwargs()
extra_tvars = False
if isinstance(self.actual, CallableType):
res: list[Constraint] = []
cactual = self.actual.with_unpacked_kwargs()
Expand All@@ -891,18 +904,18 @@ def visit_callable_type(self, template: CallableType) -> list[Constraint]:
type_state.infer_polymorphic
and cactual.variables
and cactual.param_spec() is None
and not self.skip_neg_op
# Technically, the correct inferred type for application of e.g.
# Callable[..., T] -> Callable[..., T] (with literal ellipsis), to a generic
# like U -> U, should be Callable[..., Any], but if U is a self-type, we can
# allow it to leak, to be later bound to self. A bunch of existing code
# depends on this old behaviour.
and not any(tv.id.raw_id == 0 for tv in cactual.variables)
):
# TODO: prevent infinite neg_op()
# TODO: notify solver of extra type vars
# TODO: implement secondary constraints
# TODO: fix polymorphic application to support new vars
res.extend(infer_constraints(cactual, template, neg_op(self.direction)))
extra_tvars = True

# We can't infer constraints from arguments if the template is Callable[..., T]
# (with literal '...').
Expand DownExpand Up@@ -972,6 +985,9 @@ def visit_callable_type(self, template: CallableType) -> list[Constraint]:
cactual_ret_type = cactual.type_guard

res.extend(infer_constraints(template_ret_type, cactual_ret_type, self.direction))
if extra_tvars:
for c in res:
c.extra_tvars = list(cactual.variables)
return res
elif isinstance(self.actual, AnyType):
param_spec = template.param_spec()
Expand Down
12 changes: 9 additions & 3 deletionsmypy/solve.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -48,14 +48,20 @@ def solve_constraints(
# represented differently. Normalize the constraint list w.r.t this equivalence.
constraints = normalize_constraints(constraints, vars)

extra_vars: list[TypeVarId] = []
if allow_polymorphic:
# Get additional variables from generic actuals.
for c in constraints:
extra_vars.extend([v.id for v in c.extra_tvars if v.id not in vars + extra_vars])

# Collect a list of constraints for each type variable.
cmap: dict[TypeVarId, list[Constraint]] = {tv: [] for tv in vars}
cmap: dict[TypeVarId, list[Constraint]] = {tv: [] for tv in vars + extra_vars}
for con in constraints:
if con.type_var in vars:
if con.type_var in vars + extra_vars:
cmap[con.type_var].append(con)

if allow_polymorphic:
solutions = solve_non_linear(vars, constraints, cmap)
solutions = solve_non_linear(vars + extra_vars, constraints, cmap)
else:
solutions = {}
for tv, cs in cmap.items():
Expand Down
1 change: 1 addition & 0 deletionsmypy_self_check.ini
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,6 +8,7 @@ always_false = MYPYC
plugins = misc/proper_plugin.py
python_version = 3.7
exclude = mypy/typeshed/|mypyc/test-data/|mypyc/lib-rt/
new_type_inference = True
enable_error_code = ignore-without-code,redundant-expr

[mypy-mypy.visitor]
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp