Skip to content

Conversation

@dhruvmanila
Copy link
Member

@dhruvmanila dhruvmanila commented Jun 3, 2025

Summary

Follow-up from #18401, I was looking at whether that would fix the issue at astral-sh/ty#247 (comment) and it didn't, which made me realize that the PR only inferred list[T] when the value type was tuple but it could be other types as well.

This PR fixes the actual issue by inferring list[T] for the non-tuple type case.

Test Plan

Add test cases for starred expression involved with non-tuple type. I also added a few test cases for list type and list literal.

I also verified that the example in the linked issue comment works:

def _(line: str):
    a, b, *c = line.split(maxsplit=2)
    c.pop()

@dhruvmanila dhruvmanila requested a review from carljm as a code owner June 3, 2025 09:42
@dhruvmanila dhruvmanila added the ty Multi-file analysis & type inference label Jun 3, 2025
@dhruvmanila dhruvmanila changed the title [ty] Infer list[T] when unpacking non-literal list [ty] Infer list[T] when unpacking non-tuple type Jun 3, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Jun 3, 2025

mypy_primer results

Changes were detected when running on open source projects
graphql-core (https://github.com/graphql-python/graphql-core)
- error[not-iterable] tests/utils/assert_matching_values.py:11:18: Object of type `T` is not iterable
- Found 441 diagnostics
+ Found 440 diagnostics

porcupine (https://github.com/Akuli/porcupine)
- error[invalid-argument-type] porcupine/menubar.py:166:19: Argument to function `_join` is incorrect: Expected `list[str]`, found `str`
- Found 81 diagnostics
+ Found 80 diagnostics

mypy (https://github.com/python/mypy)
- error[invalid-argument-type] mypyc/analysis/ircheck.py:363:16: Argument to function `len` is incorrect: Expected `Sized`, found `Unknown | list[Value] | Value`
- error[no-matching-overload] mypyc/analysis/ircheck.py:367:39: No overload of function `__new__` matches arguments
- error[no-matching-overload] mypyc/analysis/ircheck.py:367:39: No overload of function `__new__` matches arguments
- error[no-matching-overload] mypyc/analysis/ircheck.py:367:39: No overload of function `__new__` matches arguments
- error[not-iterable] mypyc/ir/pprint.py:189:60: Object of type `Unknown | list[Value] | Value` may not be iterable
- error[not-iterable] mypyc/transform/ir_transform.py:298:48: Object of type `Unknown | list[Value] | Value` may not be iterable
- Found 3268 diagnostics
+ Found 3262 diagnostics

prefect (https://github.com/PrefectHQ/prefect)
- error[not-iterable] src/prefect/utilities/collections.py:137:27: Object of type `KT` is not iterable
- Found 4495 diagnostics
+ Found 4494 diagnostics

meson (https://github.com/mesonbuild/meson)
- error[not-iterable] mesonbuild/backend/backends.py:565:18: Object of type `ExternalProgram | BuildTarget | CustomTarget | File | str` may not be iterable
- Found 1373 diagnostics
+ Found 1372 diagnostics

zulip (https://github.com/zulip/zulip)
- error[not-iterable] corporate/lib/decorator.py:142:41: Object of type `Parameter` is not iterable
- error[not-iterable] corporate/lib/decorator.py:229:41: Object of type `Parameter` is not iterable
- Found 6946 diagnostics
+ Found 6944 diagnostics

@AlexWaygood
Copy link
Member

Random thing I noticed while playing around with this branch locally just now: do you know why Never is given as the inlay type on the playground here? (This is a local deploy of the ty playground on your branch)

image

@dhruvmanila
Copy link
Member Author

Random thing I noticed while playing around with this branch locally just now: do you know why Never is given as the inlay type on the playground here? (This is a local deploy of the ty playground on your branch)

Yeah, I noticed that as well. I'm not exactly sure why that is happening. I plan to look at it in a bit.

@dhruvmanila
Copy link
Member Author

dhruvmanila commented Jun 3, 2025

All of the diagnostics removed in the ecosystem analysis are false positives because ty was inferring T instead of list[T] in cases like a, b, *c = some_value.

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

I'm not too familiar with the unpacking code, but this looks reasonable and the primer report looks great!

Some other edge cases that look like they're maybe not-yet covered in unpacking.md, and could be good to add as tests. It looks like we have the correct behaviour on all of them:

() = []
[] = ()

(*a,) = ()
reveal_type(a)  # revealed: list[Unknown]

(*a,) = (1,)
reveal_type(b)  # revealed: list[Literal[1]]

@dhruvmanila
Copy link
Member Author

Some other edge cases that look like they're maybe not-yet covered in unpacking.md, and could be good to add as tests. It looks like we have the correct behaviour on all of them:

Thanks!

I'm not exactly sure what's the value of the empty list / tuple test case. What is it that you had in mind to test that for? I remember there being similar test cases in the corpus source which seems more useful for these as it would test whether the inference is being done as expected or not.

The single unpacking elements examples that you've provided is being tested by way of being surrounded by other elements, not in isolation. For example, this is the list[Unknown] case and this is the list[Literal[1]] case in your example.

I'll go ahead and merge this PR but happy to follow-up with the empty list / tuple test cases if you think it's useful.

@dhruvmanila dhruvmanila merged commit 8d98c60 into main Jun 3, 2025
35 checks passed
@dhruvmanila dhruvmanila deleted the dhruv/list-unpacking branch June 3, 2025 13:47
@AlexWaygood
Copy link
Member

What is it that you had in mind to test that for?

It's just a weird edge case that only works by virtue of unpacking at runtime: a zero-length list on the right-hand side is assigned to a zero-length target list on the right-hand side. It's useful to show that we model the runtime accurately: that we understand such code as valid and do not emit any diagnostics on it.

dcreager added a commit that referenced this pull request Jun 3, 2025
…aration

* origin/main:
  [ty] Infer `list[T]` when unpacking non-tuple type (#18438)
  [ty] Meta-type of type variables should be type[..] (#18439)
  [`pyupgrade`] Make fix unsafe if it deletes comments (`UP050`) (#18390)
  [`pyupgrade`] Make fix unsafe if it deletes comments (`UP004`) (#18393)
  [ty] Support using legacy typing aliases for generic classes in type annotations (#18404)
  Use ty's completions in playground (#18425)
  Update editor setup docs about Neovim and Vim (#18324)
  Update NPM Development dependencies (#18423)
  Infer `list[T]` for starred target in unpacking (#18401)
  [`refurb`] Mark `FURB180` fix unsafe when class has bases (#18149)
  [`fastapi`] Avoid false positive for class dependencies (`FAST003`) (#18271)
dhruvmanila added a commit that referenced this pull request Jun 4, 2025
## Summary

This PR is to address this comment:
#18438 (comment)

## Test Plan

Run mdtest
carljm added a commit to mtshiba/ruff that referenced this pull request Jun 4, 2025
* main:
  [ty] Add tests for empty list/tuple unpacking (astral-sh#18451)
  [ty] Argument type expansion for overload call evaluation (astral-sh#18382)
  [ty] Minor cleanup for `site-packages` discovery logic (astral-sh#18446)
  [ty] Add generic inference for dataclasses (astral-sh#18443)
  [ty] dataclasses: Allow using dataclasses.dataclass as a function. (astral-sh#18440)
  [ty] Create separate `FunctionLiteral` and `FunctionType` types (astral-sh#18360)
  [ty] Infer `list[T]` when unpacking non-tuple type (astral-sh#18438)
  [ty] Meta-type of type variables should be type[..] (astral-sh#18439)
  [`pyupgrade`] Make fix unsafe if it deletes comments (`UP050`) (astral-sh#18390)
  [`pyupgrade`] Make fix unsafe if it deletes comments (`UP004`) (astral-sh#18393)
  [ty] Support using legacy typing aliases for generic classes in type annotations (astral-sh#18404)
  Use ty's completions in playground (astral-sh#18425)
  Update editor setup docs about Neovim and Vim (astral-sh#18324)
  Update NPM Development dependencies (astral-sh#18423)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants