Skip to content

Conversation

@AlexWaygood
Copy link
Member

@AlexWaygood AlexWaygood commented Jul 31, 2025

Summary

This PR extends the isinstance() truthiness inference (added in #19503) so that it works better for instances of generic types. Specifically, we now infer Literal[True] here, whereas on main we infer bool:

def f(x: list[int]):
    reveal_type(isinstance(x, list))

The motivation for improving our logic here is that the logic on main breaks for tuples if we remove the Type::Tuple variant and treat them simply as instances of a (very special) generic class. I.e., we have tests asserting that we infer isinstance((1, 2), tuple) as Literal[True]; those break on the branch for #19669 without this change.

I've split this out into a separate PR from #19669 as it seems like a useful change on its own merits, however. We can see from the ecosystem report that it gets rid of two false positives from bokeh: we now correctly infer two branches of code as unreachable, and therefore do not emit any invalid-return-type diagnostics on those branches anymore. (See https://github.com/bokeh/bokeh/blob/adef0157284696ce86961b2089c75fddda53c15c/src/bokeh/core/property/container.py#L130-L140.)

I can't quite figure out what's going on in the sympy ecosystem hit (https://github.com/sympy/sympy/blob/3c817ed8ab551d71e36907ce869afe5e4ca789ff/sympy/polys/polyclasses.py#L308-L317) -- it seems like we used to infer the type of g as DMP[Es] & DMP[Unknown] at the point of the return statement, whereas we now infer the type of g as DMP[Es]. I don't quite understand why we now get to that answer; but still, our new inference seems better here -- intersecting with DMP[Unknown] as a result of the isinstance() check in that function is incorrect (astral-sh/ty#456).

Test Plan

I added mdtests for the direct functionality being added, and for the false positives that this PR removes from bokeh. I also extended the reachability tests added in #19503 to include some examples of generic types. Most of these tests currently fail, so there are many TODO comments added -- they require astral-sh/ty#456 for them to be fixed. If this is merged, I'll add a comment to that issue saying that we now have some failing tests on main that should naturally be fixed if and when that issue is fixed.

@github-actions
Copy link
Contributor

github-actions bot commented Jul 31, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Jul 31, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Jul 31, 2025

mypy_primer results

Changes were detected when running on open source projects
bokeh (https://github.com/bokeh/bokeh)
- src/bokeh/core/property/container.py:140:20: error[invalid-return-type] Return type does not match returned value: expected `PropertyValueList[T]`, found `list[T] & ~list[Unknown]`
- src/bokeh/core/property/container.py:165:20: error[invalid-return-type] Return type does not match returned value: expected `PropertyValueSet[T]`, found `set[T] & ~set[Unknown]`
- Found 836 diagnostics
+ Found 834 diagnostics

sympy (https://github.com/sympy/sympy)
- sympy/polys/polyclasses.py:314:25: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- Found 12938 diagnostics
+ Found 12937 diagnostics
No memory usage changes detected ✅

@AlexWaygood AlexWaygood changed the title [ty] Improve isinstance() reachability analysis for generic types [ty] Improve isinstance() truthiness analysis for generic types Aug 1, 2025
@AlexWaygood AlexWaygood marked this pull request as ready for review August 1, 2025 13:25
@AlexWaygood AlexWaygood force-pushed the alex/isinstance-truthiness-3 branch from 20cd78f to 83ea2df Compare August 1, 2025 13:27
Copy link
Contributor

@sharkdp sharkdp left a comment

Choose a reason for hiding this comment

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

Looks good — Thank you!

@AlexWaygood AlexWaygood merged commit 18aae21 into main Aug 1, 2025
38 checks passed
@AlexWaygood AlexWaygood deleted the alex/isinstance-truthiness-3 branch August 1, 2025 13:44
dcreager added a commit that referenced this pull request Aug 1, 2025
* main: (39 commits)
  [ty] Initial test suite for `TypedDict` (#19686)
  [ty] Improve debuggability of protocol types (#19662)
  [ty] Simplify lifetime requirements for `PySlice` trait (#19687)
  [ty] Improve `isinstance()` truthiness analysis for generic types (#19668)
  [`refurb`] Make example error out-of-the-box (`FURB164`) (#19673)
  Fix link: unused_import.rs (#19648)
  [ty] Remove `Specialization::display` (full) (#19682)
  [ty] Remove `KnownModule::is_enum` (#19681)
  [ty] Support `__setitem__` and improve `__getitem__` related diagnostics (#19578)
  [ty] Sync vendored typeshed stubs (#19676)
  [`flake8-use-pathlib`] Expand `PTH201` to check all `PurePath` subclasses (#19440)
  [`refurb`] Make example error out-of-the-box (`FURB180`) (#19672)
  [`pyupgrade`] Prevent infinite loop with `I002` (`UP010`, `UP035`) (#19413)
  [ty] Improve the `Display` for generic `type[]` types (#19667)
  [ty] Refactor `TypeInferenceBuilder::infer_subscript_expression_types` (#19658)
  Fix tests on 32-bit architectures (#19652)
  [ty] Move `pandas-stubs` to bad.txt (#19659)
  [ty] Remove special casing for string-literal-in-tuple `__contains__` (#19642)
  Update pre-commit's `ruff` id (#19654)
  Update salsa (#19449)
  ...
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