Skip to content

Conversation

@sharkdp
Copy link
Contributor

@sharkdp sharkdp commented Oct 14, 2025

Summary

Dunder methods (at least the ones defined in the standard library) always take an instance of the class as the first parameter. So it seems reasonable to generally treat them as bound method descriptors if they are defined via a Callable type.

This removes just a few false positives from the ecosystem, but solves three user-reported issues:

closes astral-sh/ty#908
closes astral-sh/ty#1143
closes astral-sh/ty#1209

In addition to the change here, I also considered making ClassVars bound method descriptors. However, there was zero ecosystem impact. So I think we can also close astral-sh/ty#491 with this PR.

closes astral-sh/ty#491

Test Plan

Added regression test

@sharkdp sharkdp added ty Multi-file analysis & type inference ecosystem-analyzer labels Oct 14, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Oct 14, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@github-actions
Copy link
Contributor

github-actions bot commented Oct 14, 2025

mypy_primer results

Changes were detected when running on open source projects
pydantic (https://github.com/pydantic/pydantic)
- pydantic/v1/dataclasses.py:315:17: error[missing-argument] No argument provided for required parameter 1
- pydantic/v1/dataclasses.py:332:17: error[missing-argument] No argument provided for required parameter 1
- Found 767 diagnostics
+ Found 765 diagnostics

hydpy (https://github.com/hydpy-dev/hydpy)
- hydpy/core/testtools.py:1931:41: error[unresolved-attribute] Type `(...) -> Unknown` has no attribute `__code__`
- hydpy/cythons/modelutils.py:2110:44: error[unresolved-attribute] Type `(...) -> Unknown` has no attribute `__code__`
- Found 611 diagnostics
+ Found 609 diagnostics
No memory usage changes detected ✅

@github-actions
Copy link
Contributor

ecosystem-analyzer results

Lint rule Added Removed Changed
missing-argument 0 2 0
unresolved-attribute 0 2 0
Total 0 4 0

Full report with detailed diff (timing results)

@sharkdp sharkdp force-pushed the david/treat-dunder-method-callables-as-bound-method-descriptors branch from 1fa0788 to e20bb2c Compare October 14, 2025 10:58
return ""

class A:
__call__: Callable[[int], str] = call_impl
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The previous example here would have failed at runtime.

@sharkdp sharkdp force-pushed the david/treat-dunder-method-callables-as-bound-method-descriptors branch from e20bb2c to 70378c9 Compare October 14, 2025 11:43
@sharkdp sharkdp marked this pull request as ready for review October 14, 2025 11:48
Comment on lines +2025 to +2026
Type::Intersection(intersection) => intersection
.map_positive(db, |element| into_function_like_callable(db, *element)),
Copy link
Member

Choose a reason for hiding this comment

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

of course, if we just represented function-like callables as FunctionType & <some Callable type>, all we'd need to do here would be to insert FunctionType into the intersection; no need for a new Intersection::map_positive method!

...anyway, sorry for beating this drum, I'll try to shut up about beautiful refactors we could do until the beta's out 🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If things wouldn't always turn out to be more complicated than I initially think, I would have already started that project. But I'm almost certain this would reveal at least three issues with our intersection handling, lead to unexpected performance regressions, and probably uncover a new salsa concurrency bug. So it has to wait a little longer 😄.

@sharkdp sharkdp merged commit 6341bb7 into main Oct 14, 2025
41 checks passed
@sharkdp sharkdp deleted the david/treat-dunder-method-callables-as-bound-method-descriptors branch October 14, 2025 12:27
dcreager added a commit that referenced this pull request Oct 14, 2025
…able

* dcreager/non-inferable-api:
  just the api parts
  [ty] Fix further issues in `super()` inference logic (#20843)
  [ty] Document when a rule was added (#20859)
  [ty] Treat `Callable` dunder members as bound method descriptors (#20860)
  [ty] Handle decorators which return unions of `Callable`s (#20858)
  Fix false negatives in `Truthiness::from_expr` for lambdas, generators, and f-strings (#20704)
  [ty] Rename Type unwrapping methods (#20857)
  Update `lint.flake8-type-checking.quoted-annotations` docs (#20765)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecosystem-analyzer ty Multi-file analysis & type inference

Projects

None yet

2 participants