Title: Incorrect type narrowing for select class hierarchies · Issue #16379 · python/mypy · GitHub
Open Graph Title: Incorrect type narrowing for select class hierarchies · Issue #16379 · python/mypy
X Title: Incorrect type narrowing for select class hierarchies · Issue #16379 · python/mypy
Description: Bug Report I've found that in an exhaustive isinstance if block, mypy still leaves a more general type resolution than it should. In the snippet of code, mypy should be able to understand that there is no attr-defined error. To Reproduce...
Open Graph Description: Bug Report I've found that in an exhaustive isinstance if block, mypy still leaves a more general type resolution than it should. In the snippet of code, mypy should be able to understand that ther...
X Description: Bug Report I've found that in an exhaustive isinstance if block, mypy still leaves a more general type resolution than it should. In the snippet of code, mypy should be able to understand that ...
Opengraph URL: https://github.com/python/mypy/issues/16379
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Incorrect type narrowing for select class hierarchies ","articleBody":"**Bug Report**\r\n\r\nI've found that in an exhaustive `isinstance` if block, mypy still leaves a more general type resolution than it should. In the snippet of code, mypy should be able to understand that there is no attr-defined error.\r\n\r\n**To Reproduce**\r\n\r\n```python\r\nfrom __future__ import annotations\r\n\r\n\r\nclass A:\r\n pass\r\n\r\n\r\nclass B(A):\r\n def get_x(self):\r\n pass\r\n\r\n\r\nclass C(A):\r\n def get_x(self):\r\n pass\r\n\r\n\r\nclass D(C):\r\n pass\r\n\r\n\r\nclass E(C):\r\n pass\r\n\r\n\r\nclass F(C):\r\n pass\r\n\r\n\r\ndef x(obj: A):\r\n value = \"\"\r\n if isinstance(obj, B):\r\n value = obj.__class__.__name__\r\n elif isinstance(obj, D):\r\n value = obj.__class__.__name__\r\n elif isinstance(obj, E):\r\n value = obj.__class__.__name__\r\n elif isinstance(obj, F):\r\n value = obj.__class__.__name__\r\n else:\r\n raise RuntimeError(\"unhandled type\")\r\n\r\n reveal_type(obj)\r\n obj.get_x()\r\n\r\n```\r\n\r\n**Expected Behavior**\r\n\r\n```\r\nx.py:43: note: Revealed type is \"B | D | E | F\"\r\n```\r\n\r\n**Actual Behavior**\r\n```\r\nx.py:43: note: Revealed type is \"x.A\"\r\nx.py:44: error: \"A\" has no attribute \"get_x\" [attr-defined]\r\n```\r\n\r\n**Your Environment**\r\n\r\n\r\n- Mypy version used: mypy 1.6.1 (compiled: yes)\r\n- Mypy command-line flags: default\r\n- Mypy configuration options from `mypy.ini` (and other config files): default\r\n- Python version used: 3.10.13\r\n\r\n","author":{"url":"https://github.com/Redoubts","@type":"Person","name":"Redoubts"},"datePublished":"2023-10-31T17:32:51.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2},"url":"https://github.com/16379/mypy/issues/16379"}
| 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:d0bcd05b-904b-3ecb-b487-ad9cb1297a9e |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 8486:F3B55:2930824:3992BED:6A5F6712 |
| html-safe-nonce | 4ec5758f559b3d065dc201ff80b83fbde79024c52066a6ce891e0a243d7da828 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4NDg2OkYzQjU1OjI5MzA4MjQ6Mzk5MkJFRDo2QTVGNjcxMiIsInZpc2l0b3JfaWQiOiI1NzQwMTg0Njc4NjIxNDcyNTMwIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | b1c30cab414b1494d46edbb14d3e1f7662f5cb91c7a8838e09ecacd668af3c6d |
| hovercard-subject-tag | issue:1970958262 |
| 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/16379/issue_layout |
| twitter:image | https://opengraph.githubassets.com/89ba8b7a8ae8352f31d01cd1e1427d3f7bf2e9bb03f79d17dcf8eef7fb142caf/python/mypy/issues/16379 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/89ba8b7a8ae8352f31d01cd1e1427d3f7bf2e9bb03f79d17dcf8eef7fb142caf/python/mypy/issues/16379 |
| og:image:alt | Bug Report I've found that in an exhaustive isinstance if block, mypy still leaves a more general type resolution than it should. In the snippet of code, mypy should be able to understand that ther... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Redoubts |
| hostname | github.com |
| expected-hostname | github.com |
| None | 00788ab1bca5e7741110f9acff93fb613e3960b647280b664f19a2f2727fc38a |
| 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 | 0f1c555eb8c0d65e8ad53f33a2a87d02583a75b0 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width