Skip to content

[ty] Fix descriptor lookups for most types that overlap with None#19120

Merged
AlexWaygood merged 2 commits intomainfrom
alex/none-descr
Jul 5, 2025
Merged

[ty] Fix descriptor lookups for most types that overlap with None#19120
AlexWaygood merged 2 commits intomainfrom
alex/none-descr

Conversation

@AlexWaygood
Copy link
Member

@AlexWaygood AlexWaygood commented Jul 3, 2025

Summary

Helps with astral-sh/ty#737. The problem remains for calling methods on None itself, but no longer applies to object, AlwaysTruthy, AlwaysFalsy, or protocols that are not disjoint from None.

Test Plan

mdtests

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

github-actions bot commented Jul 3, 2025

mypy_primer results

Changes were detected when running on open source projects
parso (https://github.com/davidhalter/parso)
-     memo fields = ~54MB
+     memo fields = ~49MB

async-utils (https://github.com/mikeshardmind/async-utils)
- TOTAL MEMORY USAGE: ~45MB
+ TOTAL MEMORY USAGE: ~49MB

beartype (https://github.com/beartype/beartype)
- TOTAL MEMORY USAGE: ~88MB
+ TOTAL MEMORY USAGE: ~97MB

werkzeug (https://github.com/pallets/werkzeug)
- error[non-subscriptable] src/werkzeug/utils.py:91:13: Cannot subscript object of type `property` with no `__getitem__` method
+ error[non-subscriptable] src/werkzeug/utils.py:91:13: Cannot subscript object of type `object` with no `__getitem__` method
- error[non-subscriptable] src/werkzeug/utils.py:118:17: Cannot subscript object of type `property` with no `__getitem__` method
+ error[non-subscriptable] src/werkzeug/utils.py:118:17: Cannot subscript object of type `object` with no `__getitem__` method

discord.py (https://github.com/Rapptz/discord.py)
-     memo fields = ~189MB
+     memo fields = ~207MB

rich (https://github.com/Textualize/rich)
-     memo fields = ~117MB
+     memo fields = ~106MB

isort (https://github.com/pycqa/isort)
-     memo metadata = ~5MB
+     memo metadata = ~6MB

pylox (https://github.com/sco1/pylox)
-     memo fields = ~49MB
+     memo fields = ~54MB

poetry (https://github.com/python-poetry/poetry)
-     memo fields = ~189MB
+     memo fields = ~171MB

jinja (https://github.com/pallets/jinja)
-     memo fields = ~80MB
+     memo fields = ~88MB

pytest (https://github.com/pytest-dev/pytest)
- TOTAL MEMORY USAGE: ~276MB
+ TOTAL MEMORY USAGE: ~251MB

vision (https://github.com/pytorch/vision)
- error[missing-argument] torchvision/datasets/vision.py:81:17: No argument provided for required parameter `self` of function `__repr__`
- error[missing-argument] torchvision/datasets/vision.py:101:17: No argument provided for required parameter `self` of function `__repr__`
- Found 1474 diagnostics
+ Found 1472 diagnostics

psycopg (https://github.com/psycopg/psycopg)
-     memo metadata = ~25MB
+     memo metadata = ~28MB

openlibrary (https://github.com/internetarchive/openlibrary)
-     memo fields = ~171MB
+     memo fields = ~189MB

bokeh (https://github.com/bokeh/bokeh)
- TOTAL MEMORY USAGE: ~251MB
+ TOTAL MEMORY USAGE: ~276MB

prefect (https://github.com/PrefectHQ/prefect)
- error[missing-argument] src/prefect/settings/legacy.py:80:16: No argument provided for required parameter `value` of function `__eq__`
- Found 3753 diagnostics
+ Found 3752 diagnostics

scipy (https://github.com/scipy/scipy)
- TOTAL MEMORY USAGE: ~1399MB
+ TOTAL MEMORY USAGE: ~1271MB

@AlexWaygood AlexWaygood marked this pull request as ready for review July 3, 2025 13:28
.with_annotated_type(descriptor),
Parameter::positional_only(Some(Name::new_static("instance")))
.with_annotated_type(not_none),
.with_annotated_type(Type::object(db)),
Copy link
Member Author

Choose a reason for hiding this comment

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

this means that we now selected overload 2 rather than overload 1 for types such as object that are not subtypes of None, but are also not disjoint from None

@AlexWaygood AlexWaygood added the bug Something isn't working label Jul 3, 2025
// TODO: Consider merging this signature with the one in the previous match clause,
// since the previous one is just this signature with the `self` parameters
// removed.
let not_none = Type::none(db).negate(db);
Copy link
Contributor

@sharkdp sharkdp Jul 3, 2025

Choose a reason for hiding this comment

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

I think you may want to apply the same change to the match case just above, right? It's slightly harder to write a test for, because you might need to call __get__ manually? Let me know if you need help.

Copy link
Member Author

Choose a reason for hiding this comment

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

thanks, yes, you're correct that we emitted false positive diagnostics for object.__str__.__get__(object(), None)() as well as object().__str__() 😆

I added a regression test!

Copy link
Contributor

Choose a reason for hiding this comment

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

object.__str__.__get__(object(), None)()

Just imagine how happy users will be that this finally works correctly.

@AlexWaygood AlexWaygood merged commit 08d8819 into main Jul 5, 2025
35 checks passed
@AlexWaygood AlexWaygood deleted the alex/none-descr branch July 5, 2025 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants