Use a variadic tuple context to infer precise tuple types - #21779
Open
adhavan18 wants to merge 1 commit into
Open
Use a variadic tuple context to infer precise tuple types#21779adhavan18 wants to merge 1 commit into
adhavan18 wants to merge 1 commit into
Conversation
When a tuple expression is checked against a variadic tuple context, tuple_context_matches() only accepts the context if the structure lines up exactly, i.e. the star item sits at the same index as the context unpack. For (*a, "last") against tuple[str, *tuple[str, ...]] it does not, so no context was used, allow_precise_tuples stayed off, and the expression collapsed to tuple[str, ...] -- which is then not assignable back to the variadic context. Derive the 'is the context variadic' question separately from the exact structural match and use it to enable precise tuple inference. This is kept out of unpack_in_context, whose index bookkeeping still relies on a full structure match. Fixes python#21476.
Contributor
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #21476.
(*a, "last")wherea: tuple[str, ...]is not accepted against the contexttuple[str, *tuple[str, ...]], while the mirrored("first", *a)is:tuple_context_matches()only accepts a variadic context when the structure lines up exactly — the star item has to sit at the same index as the context unpack:For
(*a, "last")the unpack is at index 1 in the context but the star is at index 0, so the context is rejected.type_context_itemsis then never set,unpack_in_contextstaysFalse, and soallow_precise_tuplesisFalsetoo. The star item therefore skips the precise-tuple branch and falls through tocheck_lst_expr(e, "builtins.tuple", "<tuple>"), givingtuple[str, ...]— which is not assignable back to a context requiring at least one item.This decouples "is the context variadic" from "does the structure match exactly", and uses the former to enable precise tuple inference.
unpack_in_contextis deliberately left alone, because thejindex bookkeeping further down is explicitly documented as depending on a full structure match.With the change, the star item is inferred as
Unpack[tuple[str, ...]], so the expression types astuple[*tuple[str, ...], str]and the assignment is accepted. This matches what--enable-incomplete-feature=PreciseTupleTypesalready produced for this expression, and lines up with the existing# TODO: try using tuple type context in more cases.next to the structural check.It is a narrowing of what is rejected, not a widening of what is accepted — incompatible item types and too-short tuples still error, and the diagnostics get slightly better because the reported expression type is now precise:
Tests
Added
testVariadicTupleContextStarPositionMismatchtocheck-typevar-tuple.test, covering both star positions plus a wrong-item-type case and a too-short case so the change can't silently start accepting bad code. It fails on master and passes with this change.Full
mypy/test/testcheck.pysuite:8173 passed, 15 skipped, 7 xfailed.One case intentionally not addressed:
(*a, *a, "x")still collapses totuple[str, ...], since a tuple type can only carry one unpack. That behaves the same before and after this change.