Skip to content

[ty] check that starred arguments in function calls are iterable#22805

Merged
AlexWaygood merged 2 commits intoastral-sh:mainfrom
denyszhak:fix/starred-argument-iterability
Jan 24, 2026
Merged

[ty] check that starred arguments in function calls are iterable#22805
AlexWaygood merged 2 commits intoastral-sh:mainfrom
denyszhak:fix/starred-argument-iterability

Conversation

@denyszhak
Copy link
Contributor

@denyszhak denyszhak commented Jan 22, 2026

Summary

Closes #2582

some_fn(*None) incorrectly passed type checking. Now starred arguments in function calls are validated for iterability, matching the existing behavior for starred expressions in assignments.

Test Plan

Added test cases in call/function.md covering:

  • Definitely non-iterable type (*None)
  • Possibly non-iterable union type (*x where x: int | list[int])

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 22, 2026

Typing conformance results

No changes detected ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 22, 2026

mypy_primer results

Changes were detected when running on open source projects
ignite (https://github.com/pytorch/ignite)
- ignite/handlers/time_profilers.py:779:47: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- ignite/handlers/time_profilers.py:780:47: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- ignite/handlers/time_profilers.py:791:48: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- ignite/handlers/time_profilers.py:792:48: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- Found 2078 diagnostics
+ Found 2074 diagnostics

pytest (https://github.com/pytest-dev/pytest)
+ src/_pytest/terminal.py:665:52: error[not-iterable] Object of type `tuple[str, int | None, str] | None` may not be iterable
- Found 396 diagnostics
+ Found 397 diagnostics

psycopg (https://github.com/psycopg/psycopg)
+ psycopg_pool/psycopg_pool/pool_async.py:140:22: error[not-iterable] Object of type `CoroutineType[Any, Any, list[Task[None]]]` is not iterable
- Found 652 diagnostics
+ Found 653 diagnostics

antidote (https://github.com/Finistere/antidote)
+ src/antidote/core/_inject.py:348:71: error[not-iterable] Object of type `tuple[Any, ...] | None` may not be iterable
- Found 247 diagnostics
+ Found 248 diagnostics

apprise (https://github.com/caronc/apprise)
+ apprise/plugins/africas_talking.py:201:23: error[not-iterable] Object of type `Unknown | str | tuple[str, str] | bool` may not be iterable
+ apprise/plugins/africas_talking.py:212:22: error[not-iterable] Object of type `Unknown | str | tuple[str, str] | bool` may not be iterable
+ apprise/plugins/apprise_api.py:170:21: error[not-iterable] Object of type `Unknown | str | int | tuple[str, str]` may not be iterable
+ apprise/plugins/brevo.py:173:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/burstsms.py:189:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/burstsms.py:198:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/chanify.py:98:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/dingtalk.py:139:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/dingtalk.py:149:26: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/feishu.py:104:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/flock.py:155:21: error[not-iterable] Object of type `Unknown | str | tuple[str, str] | bool` may not be iterable
+ apprise/plugins/join.py:211:22: error[not-iterable] Object of type `Unknown | str | tuple[str, str] | bool | tuple[str, str, str, str, str, str, str]` may not be iterable
+ apprise/plugins/kavenegar.py:161:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/kumulos.py:114:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/kumulos.py:123:25: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/lametric.py:578:29: error[not-iterable] Object of type `Unknown | str | int | tuple[str, str]` may not be iterable
+ apprise/plugins/lametric.py:591:31: error[not-iterable] Object of type `Unknown | str | int | tuple[str, str]` may not be iterable
+ apprise/plugins/lark.py:86:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/messagebird.py:124:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/msg91.py:167:23: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/msg91.py:179:24: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/msteams.py:278:23: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/msteams.py:288:23: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/msteams.py:298:23: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/msteams.py:308:23: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/notificationapi.py:329:32: error[not-iterable] Object of type `Unknown | str | tuple[str, str] | bool` may not be iterable
+ apprise/plugins/notifico.py:167:26: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/notifico.py:178:23: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/ntfy.py:423:26: error[not-iterable] Object of type `Unknown | str | int | tuple[str, str]` may not be iterable
+ apprise/plugins/office365.py:194:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/office365.py:206:25: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/plivo.py:155:23: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/plivo.py:166:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/popcorn_notify.py:117:22: error[not-iterable] Object of type `Unknown | str | tuple[str, str] | bool` may not be iterable
+ apprise/plugins/prowl.py:169:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/prowl.py:179:31: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/pushdeer.py:100:23: error[not-iterable] Object of type `Unknown | str | int | tuple[str, str]` may not be iterable
+ apprise/plugins/pushplus.py:82:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/qq.py:84:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/reddit.py:302:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/reddit.py:310:26: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/resend.py:171:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/revolt.py:154:26: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/ryver.py:145:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/ryver.py:154:28: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/sendgrid.py:187:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/sendpulse.py:236:25: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/sendpulse.py:245:29: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/serverchan.py:85:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/ses.py:261:27: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/sinch.py:185:31: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/sinch.py:197:25: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/slack.py:375:27: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/slack.py:386:27: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/slack.py:397:27: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/slack.py:411:32: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/sns.py:195:27: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/spike.py:82:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/splunk.py:231:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/splunk.py:239:27: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/spugpush.py:82:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/streamlabs.py:200:28: error[not-iterable] Object of type `Unknown | bool | str | tuple[str, str]` may not be iterable
+ apprise/plugins/streamlabs.py:250:24: error[not-iterable] Object of type `Unknown | str | tuple[Unknown | str, Unknown | str] | tuple[Unknown | str, Unknown | str, Unknown | str, Unknown | str] | int` may not be iterable
+ apprise/plugins/streamlabs.py:261:43: error[not-iterable] Object of type `Unknown | str | tuple[Unknown | str, Unknown | str] | tuple[Unknown | str, Unknown | str, Unknown | str, Unknown | str] | int` may not be iterable
+ apprise/plugins/techuluspush.py:112:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/telegram.py:433:25: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/twilio.py:226:27: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/twilio.py:237:26: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/twilio.py:249:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[Unknown | str, Unknown | str]` may not be iterable
+ apprise/plugins/vonage.py:153:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/vonage.py:162:22: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/webexteams.py:140:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/wecombot.py:124:41: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/whatsapp.py:188:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/whatsapp.py:197:29: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/whatsapp.py:210:28: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/whatsapp.py:223:32: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/workflows.py:222:24: error[not-iterable] Object of type `Unknown | str | int | tuple[str, str]` may not be iterable
+ apprise/plugins/workflows.py:230:25: error[not-iterable] Object of type `Unknown | str | int | tuple[str, str]` may not be iterable
+ apprise/plugins/wxpusher.py:172:21: error[not-iterable] Object of type `Unknown | str | bool | tuple[str, str]` may not be iterable
+ apprise/plugins/zulip.py:228:21: error[not-iterable] Object of type `Unknown | str | tuple[str, str] | bool` may not be iterable
- Found 2652 diagnostics
+ Found 2733 diagnostics

prefect (https://github.com/PrefectHQ/prefect)
- src/integrations/prefect-docker/tests/test_containers.py:27:47: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `str | bool | dict[Unknown | str, Unknown | int] | None`
- src/integrations/prefect-docker/tests/test_containers.py:27:47: error[invalid-argument-type] Argument is incorrect: Expected `str | list[str] | None`, found `str | bool | dict[Unknown | str, Unknown | int] | None`
- src/integrations/prefect-docker/tests/test_containers.py:27:47: error[invalid-argument-type] Argument is incorrect: Expected `str | None`, found `str | bool | dict[Unknown | str, Unknown | int] | None`
- src/integrations/prefect-docker/tests/test_containers.py:27:47: error[invalid-argument-type] Argument is incorrect: Expected `bool | None`, found `str | bool | dict[Unknown | str, Unknown | int] | None`
- src/integrations/prefect-docker/tests/test_containers.py:27:47: error[invalid-argument-type] Argument is incorrect: Expected `str | list[str] | None`, found `str | bool | dict[Unknown | str, Unknown | int] | None`
- src/integrations/prefect-docker/tests/test_containers.py:27:47: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, str] | list[str] | None`, found `str | bool | dict[Unknown | str, Unknown | int] | None`
- src/integrations/prefect-docker/tests/test_containers.py:27:47: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str | bool | dict[Unknown | str, Unknown | int] | None`
- src/integrations/prefect-docker/tests/test_containers.py:42:47: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str`
- src/integrations/prefect-docker/tests/test_containers.py:55:47: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str`
- src/integrations/prefect-docker/tests/test_containers.py:68:47: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str`
- src/integrations/prefect-docker/tests/test_containers.py:81:47: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str`
- src/integrations/prefect-docker/tests/test_images.py:16:44: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:16:44: error[invalid-argument-type] Argument is incorrect: Expected `str | None`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:16:44: error[invalid-argument-type] Argument is incorrect: Expected `str | None`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:16:44: error[invalid-argument-type] Argument is incorrect: Expected `bool`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:16:44: error[invalid-argument-type] Argument is incorrect: Expected `DockerHost | None`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:16:44: error[invalid-argument-type] Argument is incorrect: Expected `DockerRegistryCredentials | None`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:16:44: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:21:16: warning[possibly-missing-attribute] Attribute `id` may be missing on object of type `Unknown | list[Unknown]`
- src/integrations/prefect-docker/tests/test_images.py:29:47: error[invalid-argument-type] Argument is incorrect: Expected `bool`, found `str`
- src/integrations/prefect-docker/tests/test_images.py:29:47: error[invalid-argument-type] Argument is incorrect: Expected `DockerRegistryCredentials | None`, found `str`
- src/integrations/prefect-docker/tests/test_images.py:29:47: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str`
- src/integrations/prefect-docker/tests/test_images.py:31:16: warning[possibly-missing-attribute] Attribute `id` may be missing on object of type `Unknown | list[Unknown]`
- src/integrations/prefect-docker/tests/test_images.py:51:17: error[invalid-argument-type] Argument is incorrect: Expected `bool`, found `str`
- src/integrations/prefect-docker/tests/test_images.py:51:17: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str`
- src/integrations/prefect-docker/tests/test_images.py:53:16: warning[possibly-missing-attribute] Attribute `id` may be missing on object of type `Unknown | list[Unknown]`
- src/integrations/prefect-docker/tests/test_images.py:64:47: error[invalid-argument-type] Argument is incorrect: Expected `str`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:64:47: error[invalid-argument-type] Argument is incorrect: Expected `str | None`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:64:47: error[invalid-argument-type] Argument is incorrect: Expected `str | None`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:64:47: error[invalid-argument-type] Argument is incorrect: Expected `bool`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:64:47: error[invalid-argument-type] Argument is incorrect: Expected `DockerRegistryCredentials | None`, found `str | bool`
- src/integrations/prefect-docker/tests/test_images.py:64:47: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str | bool`
- src/integrations/prefect-kubernetes/prefect_kubernetes/jobs.py:429:17: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `str`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:20:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `None`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:29:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `None`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:38:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `None`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:57:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:103:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:149:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:195:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:240:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:286:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_custom_objects.py:344:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_deployments.py:18:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_deployments.py:38:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_deployments.py:70:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_deployments.py:92:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_deployments.py:113:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_deployments.py:141:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_jobs.py:36:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_jobs.py:52:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_jobs.py:68:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_jobs.py:87:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_jobs.py:107:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_jobs.py:131:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_jobs.py:159:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_pods.py:29:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_pods.py:46:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_pods.py:78:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_pods.py:96:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_pods.py:115:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_pods.py:137:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/integrations/prefect-kubernetes/tests/test_pods.py:167:9: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Any]`, found `Literal["test"]`
- src/prefect/cache_policies.py:311:25: warning[possibly-missing-attribute] Attribute `__code__` may be missing on object of type `Unknown | ((...) -> Any)`
+ src/prefect/cache_policies.py:311:25: warning[possibly-missing-attribute] Attribute `__code__` may be missing on object of type `Unknown | (((...) -> Any) & ((*args: object, **kwargs: object) -> object))`
- src/prefect/deployments/runner.py:997:70: warning[possibly-missing-attribute] Attribute `__name__` may be missing on object of type `Unknown | (((...) -> Any) & ((*args: object, **kwargs: object) -> object))`
+ src/prefect/deployments/runner.py:997:70: warning[possibly-missing-attribute] Attribute `__name__` may be missing on object of type `Unknown | ((...) -> Any)`
+ src/prefect/flow_engine.py:989:32: error[invalid-await] `Unknown | R@FlowRunEngine | Coroutine[Any, Any, R@FlowRunEngine]` is not awaitable
+ src/prefect/flow_engine.py:1580:24: error[invalid-await] `Unknown | R@AsyncFlowRunEngine | Coroutine[Any, Any, R@AsyncFlowRunEngine]` is not awaitable
+ src/prefect/flow_engine.py:1661:43: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Unknown | R@run_generator_flow_sync`
+ src/prefect/flow_engine.py:1669:21: warning[possibly-missing-attribute] Attribute `throw` may be missing on object of type `Unknown | R@run_generator_flow_sync`
+ src/prefect/flow_engine.py:1703:44: warning[possibly-missing-attribute] Attribute `__anext__` may be missing on object of type `Unknown | R@run_generator_flow_async`
+ src/prefect/flow_engine.py:1710:25: warning[possibly-missing-attribute] Attribute `throw` may be missing on object of type `Unknown | R@run_generator_flow_async`
- src/prefect/flows.py:285:34: error[unresolved-attribute] Object of type `((**P@Flow) -> R@Flow) & ((*args: object, **kwargs: object) -> object)` has no attribute `__name__`
+ src/prefect/flows.py:285:34: error[unresolved-attribute] Object of type `(**P@Flow) -> R@Flow` has no attribute `__name__`
- src/prefect/flows.py:403:68: error[unresolved-attribute] Object of type `((**P@Flow) -> R@Flow) & ((*args: object, **kwargs: object) -> object)` has no attribute `__name__`
+ src/prefect/flows.py:403:68: error[unresolved-attribute] Object of type `(**P@Flow) -> R@Flow` has no attribute `__name__`
- src/prefect/flows.py:1877:53: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
+ src/prefect/flows.py:1937:21: error[no-matching-overload] No overload of function `run_coro_as_sync` matches arguments
- src/prefect/task_engine.py:1627:28: error[invalid-await] `Unknown | R@AsyncTaskRunEngine | Coroutine[Any, Any, R@AsyncTaskRunEngine]` is not awaitable
- src/prefect/task_engine.py:1735:47: error[invalid-argument-type] Argument to function `next` is incorrect: Expected `SupportsNext[Unknown]`, found `Unknown | R@run_generator_task_sync`
- src/prefect/task_engine.py:1748:25: warning[possibly-missing-attribute] Attribute `throw` may be missing on object of type `Unknown | R@run_generator_task_sync`
- src/prefect/task_engine.py:1794:48: warning[possibly-missing-attribute] Attribute `__anext__` may be missing on object of type `Unknown | R@run_generator_task_async`
- src/prefect/task_engine.py:1806:29: warning[possibly-missing-attribute] Attribute `throw` may be missing on object of type `Unknown | R@run_generator_task_async`
- src/prefect/tasks.py:185:9: warning[possibly-missing-attribute] Attribute `__code__` may be missing on object of type `Unknown | ((...) -> Any)`
+ src/prefect/tasks.py:185:9: warning[possibly-missing-attribute] Attribute `__code__` may be missing on object of type `Unknown | (((...) -> Any) & ((*args: object, **kwargs: object) -> object))`
- Found 5359 diagnostics
+ Found 5297 diagnostics

ibis (https://github.com/ibis-project/ibis)
+ ibis/expr/api.py:1853:30: error[not-iterable] Object of type `Unknown | None` may not be iterable
+ ibis/expr/api.py:1855:31: error[not-iterable] Object of type `Unknown | None` may not be iterable
+ ibis/expr/api.py:1857:33: error[not-iterable] Object of type `Unknown | None` may not be iterable
- Found 4603 diagnostics
+ Found 4606 diagnostics

sympy (https://github.com/sympy/sympy)
+ sympy/combinatorics/permutations.py:1016:24: error[not-iterable] Object of type `Unknown | list[Unknown | int] | int` may not be iterable
+ sympy/functions/elementary/tests/test_piecewise.py:491:23: error[not-iterable] Object of type `Basic` is not iterable
+ sympy/functions/special/hyper.py:302:23: error[not-iterable] Object of type `Basic` is not iterable
+ sympy/functions/special/hyper.py:307:23: error[not-iterable] Object of type `Basic` is not iterable
+ sympy/physics/mechanics/system.py:903:52: error[not-iterable] Object of type `Unknown | None` may not be iterable
+ sympy/physics/quantum/spin.py:788:39: error[not-iterable] Object of type `Basic` is not iterable
+ sympy/physics/quantum/spin.py:789:35: error[not-iterable] Object of type `Basic` is not iterable
+ sympy/stats/joint_rv.py:396:71: error[not-iterable] Object of type `tuple[Unknown, ...] | Dummy` may not be iterable
- Found 15662 diagnostics
+ Found 15670 diagnostics

pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
+ tests/frame/test_groupby.py:229:15: error[type-assertion-failure] Type `Series[Any]` does not match asserted type `Series[str | bytes | int | ... omitted 12 union elements]`
+ tests/frame/test_groupby.py:625:15: error[type-assertion-failure] Type `Series[Any]` does not match asserted type `Series[str | bytes | int | ... omitted 12 union elements]`
- Found 4411 diagnostics
+ Found 4413 diagnostics

jax (https://github.com/google/jax)
+ jax/_src/cudnn/fused_attention_stablehlo.py:1042:61: error[not-iterable] Object of type `Unknown | None` may not be iterable
+ jax/_src/custom_derivatives.py:1747:35: error[not-iterable] Object of type `ClosedJaxpr` is not iterable
+ jax/_src/custom_derivatives.py:1785:35: error[not-iterable] Object of type `ClosedJaxpr` is not iterable
+ jax/_src/pallas/fuser/block_spec.py:166:23: error[not-iterable] Object of type `Any | None` may not be iterable
+ jax/_src/pallas/fuser/block_spec.py:168:25: error[not-iterable] Object of type `tuple[int | Array, ...] | None` may not be iterable
+ jax/_src/pallas/fuser/block_spec.py:172:23: error[not-iterable] Object of type `Any | None` may not be iterable
+ jax/_src/pallas/fuser/block_spec.py:174:25: error[not-iterable] Object of type `tuple[int | Array, ...] | None` may not be iterable
+ jax/_src/pallas/fuser/fusible_dtype.py:543:57: error[not-iterable] Object of type `BlockSpec` is not iterable
- Found 2896 diagnostics
+ Found 2904 diagnostics

pandas (https://github.com/pandas-dev/pandas)
+ pandas/core/indexes/base.py:1845:32: error[not-iterable] Object of type `Unknown | FrozenList | list[Unknown | None] | None` may not be iterable
+ pandas/io/excel/_xlsxwriter.py:260:32: error[not-iterable] Object of type `tuple[int, int] | None` may not be iterable
+ pandas/io/formats/excel.py:785:34: error[not-iterable] Object of type `Unknown | (Top[list[Unknown]] & ~AlwaysFalsy) | (tuple[object, ...] & ~AlwaysFalsy) | (ndarray[tuple[object, ...], dtype[object]] & ~AlwaysFalsy) | (Index & ~AlwaysFalsy)` may not be iterable
- Found 3769 diagnostics
+ Found 3772 diagnostics

static-frame (https://github.com/static-frame/static-frame)
- static_frame/core/bus.py:671:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemLocReduces[Bus[Any], object_]`, found `InterGetItemLocReduces[Bus[Any] | IndexHierarchy | TypeBlocks | ... omitted 6 union elements, object_]`
- static_frame/core/bus.py:675:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[Bus[Any], object_]`, found `InterGetItemILocReduces[Bus[Any] | IndexHierarchy | TypeBlocks | ... omitted 7 union elements, object_ | Self@iloc]`
+ static_frame/core/bus.py:675:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[Bus[Any], object_]`, found `InterGetItemILocReduces[Self@iloc | Bus[Any], object_ | Self@iloc]`
+ static_frame/core/frame.py:2008:44: error[not-iterable] Object of type `int | integer[Any] | ndarray[Any, Any] | ... omitted 3 union elements` may not be iterable
- static_frame/core/series.py:772:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[Series[Any, Any], TVDtype@Series]`, found `InterGetItemILocReduces[Series[Any, Any] | IndexHierarchy | TypeBlocks | ... omitted 7 union elements, TVDtype@Series]`
- static_frame/core/series.py:4072:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[SeriesHE[Any, Any], TVDtype@SeriesHE]`, found `InterGetItemILocReduces[Bottom[Series[Any, Any]] | Bottom[Index[Any]] | TypeBlocks | ... omitted 8 union elements, TVDtype@SeriesHE]`
- static_frame/core/yarn.py:418:16: error[invalid-return-type] Return type does not match returned value: expected `InterGetItemILocReduces[Yarn[Any], object_]`, found `InterGetItemILocReduces[Yarn[Any] | Bottom[Index[Any]] | Bottom[Series[Any, Any]] | ... omitted 7 union elements, object_]`
- Found 1822 diagnostics
+ Found 1819 diagnostics

rotki (https://github.com/rotki/rotki)
+ rotkehlchen/chain/decoding/tools.py:96:44: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- rotkehlchen/chain/decoding/tools.py:97:13: error[invalid-argument-type] Argument to function `decode_transfer_direction` is incorrect: Expected `BTCAddress | ChecksumAddress | SubstrateAddress | SolanaAddress`, found `A@BaseDecoderTools`
+ rotkehlchen/chain/decoding/tools.py:99:13: error[invalid-argument-type] Argument to function `decode_transfer_direction` is incorrect: Expected `Sequence[A@BaseDecoderTools]`, found `Unknown | tuple[BTCAddress, ...] | tuple[ChecksumAddress, ...] | tuple[SubstrateAddress, ...] | tuple[SolanaAddress, ...]`
- rotkehlchen/chain/decoding/tools.py:98:13: error[invalid-argument-type] Argument to function `decode_transfer_direction` is incorrect: Expected `BTCAddress | ChecksumAddress | SubstrateAddress | SolanaAddress | None`, found `A@BaseDecoderTools | None`
+ rotkehlchen/chain/decoding/tools.py:100:62: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- Found 2051 diagnostics
+ Found 2052 diagnostics

core (https://github.com/home-assistant/core)
+ homeassistant/components/osramlightify/light.py:254:44: error[not-iterable] Object of type `Unknown | None | tuple[int, int, int]` may not be iterable
- Found 14478 diagnostics
+ Found 14479 diagnostics

scipy (https://github.com/scipy/scipy)
+ scipy/optimize/_differentiable_functions.py:76:41: error[not-iterable] Object of type `Unknown | None` may not be iterable
+ scipy/optimize/_zeros_py.py:1162:25: error[not-iterable] Object of type `Unknown | None | tuple[()]` may not be iterable
+ scipy/spatial/distance.py:2424:84: error[not-iterable] Object of type `Unknown | float` may not be iterable
+ scipy/stats/tests/test_distributions.py:3854:33: error[not-iterable] Object of type `Unknown | f_gen | tuple[int, int] | int | float` may not be iterable
+ scipy/stats/tests/test_distributions.py:3856:30: error[not-iterable] Object of type `Unknown | f_gen | tuple[int, int] | int | float` may not be iterable
+ scipy/stats/tests/test_distributions.py:8083:30: error[not-iterable] Object of type `Unknown | burr_gen | tuple[int] | ... omitted 5 union elements` may not be iterable
+ scipy/stats/tests/test_distributions.py:8087:33: error[not-iterable] Object of type `Unknown | burr_gen | tuple[int] | ... omitted 5 union elements` may not be iterable
- Found 8115 diagnostics
+ Found 8122 diagnostics

No memory usage changes detected ✅

@ntBre ntBre added the ty Multi-file analysis & type inference label Jan 22, 2026
@AlexWaygood
Copy link
Member

Thank you! Interestingly, we already emit a diagnostic if you attempt to ** something that is not a mapping into a function call, but we emit that error in a very different location:

} else {
let mut value_type_fallback = |argument_type: Type<'db>| {
let Some((key_type, value_type)) = argument_type.unpack_keys_and_items(self.db)
else {
self.errors.push(BindingError::KeywordsNotAMapping {
argument_index: adjusted_argument_index,
provided_ty: argument_type,
});
return None;
};
if !key_type
.when_assignable_to(
self.db,
KnownClass::Str.to_instance(self.db),
self.inferable_typevars,
)
.is_always_satisfied(self.db)
{
self.errors.push(BindingError::InvalidKeyType {
argument_index: adjusted_argument_index,
provided_ty: key_type,
});
}
Some(value_type)
};
I'm not totally sure if the location where we emit this new diagnostic is important or not -- it looks like KeywordNotAMapping is listed as one of the errors that affects overload resolution, so I'm not sure how this new error should interact with the overload evaluation call algorithm and whether it should also affect overload resolution...?

impl<'db> BindingError<'db> {
/// Returns `true` if this error indicates the overload didn't match the call arguments.
///
/// Returns `false` for semantic errors where the overload matched the types but the
/// usage is invalid for other reasons (e.g., applying `@dataclass` to a `NamedTuple`).
/// These semantic errors should be reported directly rather than causing "no matching
/// overload" errors.
fn affects_overload_resolution(&self) -> bool {
match self {
// Semantic errors: the overload matched, but the usage is invalid
Self::InvalidDataclassApplication(_)
| Self::PropertyHasNoSetter(_)
| Self::CalledTopCallable(_)
| Self::InternalCallError(_) => false,
// Matching errors: the overload doesn't apply to these arguments
Self::InvalidArgumentType { .. }
| Self::InvalidKeyType { .. }
| Self::KeywordsNotAMapping { .. }
| Self::MissingArguments { .. }
| Self::UnknownArgument { .. }
| Self::PositionalOnlyParameterAsKwarg { .. }
| Self::TooManyPositionalArguments { .. }
| Self::ParameterAlreadyAssigned { .. }
| Self::SpecializationError { .. }
| Self::UnmatchedOverload => true,
}
}

Paging @dhruvmanila as our expert in this area!

@denyszhak
Copy link
Contributor Author

@AlexWaygood
Thanks for the context! I'll wait for @dhruvmanila input on overload and whether this should move to bind.rs

Copy link
Member

@dhruvmanila dhruvmanila left a comment

Choose a reason for hiding this comment

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

It's an interesting point on how to think about whether it affects overload resolution. Looking at the KeywordsNotAMapping error in the following case:

from typing import overload

@overload
def h(**kwargs: int) -> int: ...
@overload
def h(**kwargs: str) -> str: ...
def h(**kwargs): ...

h(**None)

ty currently reports it as no-matching-overload but I think it'd be much better if we could report the actual error which is that the argument after ** isn't a mapping type. Another option is to report no-matching-overload and add the invalid-argument-type as a sub-diagnostic.

It's interesting that in the above case only mypy raises the actual error while other type checkers (Pyright, pyrefly) raises no-matching-overload.

I think the only way to have this behavior of raising the argument type error instead of no-matching-overload is to extract out the diagnostic reporting to where this PR has added the not-iterable diagnostic.

So, the location in this PR looks good to me.

reveal_type(f(**Foo(a=1, b="b"))) # revealed: int | str
```

## Non-iterable variadic argument
Copy link
Member

Choose a reason for hiding this comment

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

Can you add an example with overloads?


overloaded.pyi:

from typing import overload

@overload
def foo(a: int) -> tuple[int]: ...
@overload
def foo(a: int, b: int) -> tuple[int, int]: ...
from overloaded import foo

foo(*None)

def _(arg: int):
    foo(*arg)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@dhruvmanila
Copy link
Member

dhruvmanila commented Jan 23, 2026

Oh, actually, this would be problematic because it would pick some overload then which you can see in the revealed type.

Considering the example in my above comment related to overloads with variadic, the reveal type for foo(*None) gives me tuple[int] (by ty on this branch). Huh, and mypy reveals this type as well which looks like a bug.

@dhruvmanila
Copy link
Member

I think the reason it's picking the first overload is because none of the overloads got filtered out and at the end it fallback to picking the first overload.

I still think that the location of this and KeywordsNotAMapping should be in infer/builder.rs because it's not a binding error but rather an error at the call site.

If you're interested, a follow-up PR could be to move the KeywordsNotAMapping to infer_call_expression_impl as in this PR.

@denyszhak
Copy link
Contributor Author

I think the reason it's picking the first overload is because none of the overloads got filtered out and at the end it fallback to picking the first overload.

I still think that the location of this and KeywordsNotAMapping should be in infer/builder.rs because it's not a binding error but rather an error at the call site.

If you're interested, a follow-up PR could be to move the KeywordsNotAMapping to infer_call_expression_impl as in this PR.

Yes, would love to do that change in a follow-up PR

@denyszhak
Copy link
Contributor Author

@dhruvmanila to avoid confusion, do you want me to change anything as of now for this PR or it's fine as is?

@AlexWaygood
Copy link
Member

I think we'd still like you to add a test that uses overloads, as per #22805 (comment)! Just to demonstrate what our current behaviour is. But after that, this should be good to go.

@denyszhak denyszhak requested a review from dhruvmanila January 24, 2026 16:16
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.

Thank you!

@AlexWaygood AlexWaygood merged commit aaaaea2 into astral-sh:main Jan 24, 2026
49 checks passed
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.

Starred expression not checked when used in function argument

4 participants