Skip to content

Draft: Solve intermediate variable bug #19399

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

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

randolf-scholz
Copy link
Contributor

@randolf-scholz randolf-scholz commented Jul 8, 2025

Attempted fix for #19304. Looking for feedback, as this was mostly a trial-and-error process.

  • Removed self.infer_function_type_arguments_using_context. Instead, we now use a function infer_constraints_from_context that only yields the constraints.
  • Modified infer_function_type_arguments to now include the context.
    We compute 2 sets of constraints: the "outer constraints", determined by the context, and the "inner constraints" determined by the callable type. From this, we compute 2 solutions:
    • the "outer solution", which only uses the outer constraints.
    • the "joint solution", which uses both the outer and inner constraints.
  • We prefer the "joint solution", unless:
    • it failed to solve some variables
    • the return type of the outer solution is a subtype (i.e. more precise) of the return type of the joint solution
    • the return type of the outer solution is a union, and any member of that union is a subtype of the joint return type.1
  • if the outer solution was selected, we essentially fall back to the original code from the master branch, and first apply the outer solution, and then recompute the inner constraints and apply the inner solution.

Modified tests

Footnotes

  1. This was needed to fix testLiteralAndGenericWithUnion, because the outer solution was int | Literal["foo"] whereas the joint solution was Literal["foo"]? which got converted into str later.

  2. previously, a=b followed by a=[[b]] made a be inferred as __main__.B followed by builtins.list[Union[__main__.A, typing.Sequence[Union[__main__.A, ...]]]]. Now, it gets more precisely inferred as builtins.list[builtins.list[__main__.B]]. And afterwards, join(a,b) get more precisely inferred as typing.Sequence[typing.Sequence[__main__.B]] rather than typing.Sequence[Union[__main__.A, typing.Sequence[Union[__main__.A, ...]]]] previously. See: https://mypy-play.net/?mypy=latest&python=3.12&gist=619a7fa6c3ec9d75bd1492bf8e68432c

Comment on lines +2155 to +2158
or ( # HACK to fix testLiteralAndGenericWithUnion
isinstance(outer_ret_type, UnionType)
and any(is_subtype(val, joint_ret_type) for val in outer_ret_type.items)
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this hack, testLiteralAndGenericWithUnion fails (see footnote 1 in OP). Not sure if this is the appropriate way to do it

lambda i: self.accept(args[i]),
)

# ??? QUESTION: Do we need to recompute arg_types and pass1_args here???
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to work both with/without recomputing arg_types here, but I am not sure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant