Title: Type narrowing for a tuple is worse with match than with the equivalent isinstance check · Issue #19082 · python/mypy · GitHub
Open Graph Title: Type narrowing for a tuple is worse with match than with the equivalent isinstance check · Issue #19082 · python/mypy
X Title: Type narrowing for a tuple is worse with match than with the equivalent isinstance check · Issue #19082 · python/mypy
Description: Bug Report Type narrowing is worse in a match statement on a tuple than the equivalent isinstance check. With isinstance, mypy is able to determine that the type of a must be the tuple side of the union even though the check is only agai...
Open Graph Description: Bug Report Type narrowing is worse in a match statement on a tuple than the equivalent isinstance check. With isinstance, mypy is able to determine that the type of a must be the tuple side of the ...
X Description: Bug Report Type narrowing is worse in a match statement on a tuple than the equivalent isinstance check. With isinstance, mypy is able to determine that the type of a must be the tuple side of the ...
Opengraph URL: https://github.com/python/mypy/issues/19082
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Type narrowing for a tuple is worse with match than with the equivalent isinstance check","articleBody":"**Bug Report**\n\nType narrowing is worse in a match statement on a tuple than the equivalent isinstance check.\n\nWith isinstance, mypy is able to determine that the type of `a` must be the tuple side of the union even though the check is only against Sequence, and then correctly narrows the type of the second element. With match, mypy is unable to do so and gives a union of the two element types in the tuple.\n\n**To Reproduce**\n\nrepro.py\n```python\nfrom collections.abc import Sequence\n\nType = tuple[float, int] | None\n\n\ndef foo(a: int) -\u003e None:\n pass\n\n\ndef bar_match(a: Type) -\u003e None:\n match a:\n case _, int_a:\n foo(int_a)\n\n\ndef bar_isinstance(a: Type) -\u003e None:\n if isinstance(a, Sequence):\n _, int_a = a\n foo(int_a)\n```\n\n**Expected Behavior**\n\nNo errors\n\n**Actual Behavior**\n\n```\n$ mypy repro.py \nrepro.py:13: error: Argument 1 to \"foo\" has incompatible type \"float | int\"; expected \"int\" [arg-type]\nFound 1 error in 1 file (checked 1 source file)\n```\nNote that there is only one error, for the `bar_match` function, and no error for the `bar_isinstance` function.\n\n**Your Environment**\n\nI found this with 1.15 and reproduced it on the current master branch.\n\n- Mypy version used: 1.15 or 1.16.0+dev.ca609acabdc94ee973a53d62b8dcb7e55c789aec (compiled: no)\n- Mypy command-line flags: None\n- Mypy configuration options from `mypy.ini` (and other config files): None\n- Python version used: Python 3.12.3\n\nPossibly related issues:\nhttps://github.com/python/mypy/issues/19081\n","author":{"url":"https://github.com/mscheifer","@type":"Person","name":"mscheifer"},"datePublished":"2025-05-12T19:12:37.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/19082/mypy/issues/19082"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:c9596326-a453-fbd6-1156-b76a23cc95de |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | CB42:39A6E:78BEC8:A7686C:6A57DC5A |
| html-safe-nonce | c461c294dd6435819737d627d60f08a2a80dae708e89cd7af275d17cd5487fb8 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDQjQyOjM5QTZFOjc4QkVDODpBNzY4NkM6NkE1N0RDNUEiLCJ2aXNpdG9yX2lkIjoiMTY4NTA3NTgwOTg2MDU3NDI5OCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 255fe54c799d29c6a3dc40d8fd7e5bdbf77f7b5d2783ab59a4d365ddcfba8279 |
| hovercard-subject-tag | issue:3057892299 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/mypy/19082/issue_layout |
| twitter:image | https://opengraph.githubassets.com/1d7b1843ec8f8f96189ac84aba21820904105949bf82fc0cbf2302fcc86b2100/python/mypy/issues/19082 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/1d7b1843ec8f8f96189ac84aba21820904105949bf82fc0cbf2302fcc86b2100/python/mypy/issues/19082 |
| og:image:alt | Bug Report Type narrowing is worse in a match statement on a tuple than the equivalent isinstance check. With isinstance, mypy is able to determine that the type of a must be the tuple side of the ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | mscheifer |
| hostname | github.com |
| expected-hostname | github.com |
| None | 837767abbd14b05f219fd812ef2842c659968b63619e1b966dded83972ab5bca |
| turbo-cache-control | no-preview |
| go-import | github.com/python/mypy git https://github.com/python/mypy.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 7053637 |
| octolytics-dimension-repository_nwo | python/mypy |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 7053637 |
| octolytics-dimension-repository_network_root_nwo | python/mypy |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 36b9c371e4e031091f1b89adf913d9e6993943df |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width