Skip to content

[ty] fix goto definition for generic classes#24714

Merged
dcreager merged 9 commits intoastral-sh:mainfrom
felixscherz:fix/goto-definition-for-generic-base-class
Apr 21, 2026
Merged

[ty] fix goto definition for generic classes#24714
dcreager merged 9 commits intoastral-sh:mainfrom
felixscherz:fix/goto-definition-for-generic-base-class

Conversation

@felixscherz
Copy link
Copy Markdown
Contributor

Hi, this fixes astral-sh/ty#2854

Summary

Compare class literals instead of class bases for the purposes of skipping the MRO until the pivot class.
Also skip BoundSuperType when looking up definitions since we probably do not want to look up definitions on the super class itself.

Test Plan

Added snapshot tests

@astral-sh-bot astral-sh-bot Bot added the ty Multi-file analysis & type inference label Apr 19, 2026
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 19, 2026

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 87.94%. The percentage of expected errors that received a diagnostic held steady at 83.36%. The number of fully passing files held steady at 79/133.

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 19, 2026

Memory usage report

Summary

Project Old New Diff Outcome
prefect 702.58MB 702.72MB +0.02% (136.05kB)
trio 116.46MB 116.48MB +0.02% (23.82kB)
flake8 47.68MB 47.68MB -
sphinx 258.61MB 258.61MB -

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
Type<'db>::apply_specialization_ 3.67MB 3.69MB +0.56% (20.98kB)
FunctionType 8.92MB 8.94MB +0.23% (20.80kB)
Type<'db>::apply_specialization_::interned_arguments 2.94MB 2.96MB +0.41% (12.42kB)
Type<'db>::try_call_dunder_get_ 10.56MB 10.57MB +0.11% (12.14kB)
FunctionType<'db>::signature_ 4.09MB 4.10MB +0.25% (10.67kB)
CallableType 2.15MB 2.15MB +0.26% (5.62kB)
FunctionType<'db>::last_definition_signature_ 811.24kB 816.72kB +0.68% (5.48kB)
infer_expression_types_impl 62.71MB 62.72MB +0.01% (4.45kB)
Type<'db>::member_lookup_with_policy_ 17.25MB 17.25MB +0.02% (4.35kB)
BoundMethodType<'db>::into_callable_type_ 314.78kB 318.95kB +1.33% (4.17kB)
Specialization 2.11MB 2.11MB +0.18% (3.95kB)
Type<'db>::class_member_with_policy_ 17.65MB 17.65MB +0.02% (3.38kB)
Type<'db>::class_member_with_policy_::interned_arguments 9.81MB 9.82MB +0.03% (3.25kB)
GenericContext 294.71kB 297.47kB +0.94% (2.76kB)
Type<'db>::try_call_dunder_get_::interned_arguments 2.93MB 2.93MB +0.09% (2.64kB)
... 33 more

trio

Name Old New Diff Outcome
Type<'db>::try_call_dunder_get_ 1.33MB 1.34MB +0.26% (3.50kB)
Type<'db>::apply_specialization_ 705.04kB 707.42kB +0.34% (2.38kB)
FunctionType 1.49MB 1.49MB +0.14% (2.06kB)
is_redundant_with_impl::interned_arguments 289.52kB 291.07kB +0.53% (1.55kB)
Type<'db>::member_lookup_with_policy_ 1.94MB 1.94MB +0.07% (1.34kB)
Type<'db>::apply_specialization_::interned_arguments 625.00kB 626.33kB +0.21% (1.33kB)
FunctionType<'db>::signature_ 1.06MB 1.06MB +0.11% (1.22kB)
IntersectionType 130.77kB 131.94kB +0.90% (1.17kB)
Type<'db>::class_member_with_policy_ 2.03MB 2.03MB +0.05% (1.03kB)
is_redundant_with_impl 247.50kB 248.39kB +0.36% (912.00B)
Type<'db>::class_member_with_policy_::interned_arguments 1.12MB 1.12MB +0.07% (832.00B)
Type<'db>::try_call_dunder_get_::interned_arguments 348.05kB 348.77kB +0.20% (728.00B)
infer_scope_types_impl 4.71MB 4.71MB +0.01% (612.00B)
Specialization 455.67kB 456.27kB +0.13% (608.00B)
try_call_bin_op_return_type_impl 49.93kB 50.47kB +1.10% (560.00B)
... 16 more

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 19, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-argument-type 9 0 0
invalid-assignment 9 0 0
unused-type-ignore-comment 0 8 0
invalid-return-type 4 0 0
no-matching-overload 4 0 0
unknown-argument 2 0 0
unresolved-attribute 1 1 0
call-non-callable 1 0 0
not-subscriptable 1 0 0
Total 31 9 0
Raw diff (40 changes)
anyio (https://github.com/agronholm/anyio)
+ src/anyio/_core/_tempfile.py:423:22 error[no-matching-overload] No overload of bound method `AsyncFile.write` matches arguments
+ src/anyio/_core/_tempfile.py:451:22 error[no-matching-overload] No overload of bound method `AsyncFile.writelines` matches arguments

beartype (https://github.com/beartype/beartype)
- beartype/typing/_typingpep544.py:520:31 error[unresolved-attribute] Object of type `<super: <class 'Protocol'>, type[Self@__class_getitem__]>` has no attribute `__class_getitem__`
+ beartype/typing/_typingpep544.py:568:25 error[call-non-callable] Object of type `object` is not callable
+ beartype/typing/_typingpep544.py:585:9 error[invalid-assignment] Object of type `type[Self@__class_getitem__]` is not assignable to attribute `__origin__` on type `Unknown | type[Self@__class_getitem__]`

bokeh (https://github.com/bokeh/bokeh)
+ src/bokeh/core/property/container.py:136:37 error[invalid-argument-type] Argument to `Seq.__init__` is incorrect: Expected `list[Never] | UndefinedType | IntrinsicType`, found `list[list[Never]] | UndefinedType | IntrinsicType`

core (https://github.com/home-assistant/core)
+ homeassistant/components/ring/binary_sensor.py:162:9 error[invalid-assignment] Cannot assign to a subscript on an object of type `Mapping[str, Any]`
+ homeassistant/components/ring/binary_sensor.py:166:9 error[invalid-assignment] Cannot assign to a subscript on an object of type `Mapping[str, Any]`

discord.py (https://github.com/Rapptz/discord.py)
- discord/ext/commands/context.py:1120:16 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ext/commands/hybrid.py:349:52 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ui/select.py:494:32 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ui/select.py:676:32 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ui/select.py:776:32 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ui/select.py:888:32 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive
- discord/ui/select.py:1009:32 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive

hydra-zen (https://github.com/mit-ll-responsible-ai/hydra-zen)
- src/hydra_zen/funcs.py:102:41 warning[unused-type-ignore-comment] Unused blanket `type: ignore` directive

ibis (https://github.com/ibis-project/ibis)
+ ibis/expr/operations/generic.py:148:26 error[unknown-argument] Argument `value` does not match any known parameter
+ ibis/expr/operations/generic.py:148:39 error[unknown-argument] Argument `dtype` does not match any known parameter

prefect (https://github.com/PrefectHQ/prefect)
+ src/integrations/prefect-ray/prefect_ray/task_runners.py:314:28 error[invalid-argument-type] Argument to bound method `TaskRunner.map` is incorrect: Expected `Task[P@map, R@RayTaskRunner | CoroutineType[Any, Any, R@RayTaskRunner]]`, found `Task[P@map, R@RayTaskRunner]`
+ src/prefect/input/run_input.py:448:16 error[unresolved-attribute] Attribute `value` is not defined on `Coroutine[Any, Any, Self@load]` in union `Self@load | Coroutine[Any, Any, Self@load]`

werkzeug (https://github.com/pallets/werkzeug)
+ src/werkzeug/datastructures/mixins.py:260:14 error[no-matching-overload] No overload of bound method `MutableMapping.setdefault` matches arguments
+ src/werkzeug/datastructures/mixins.py:309:13 error[invalid-argument-type] Argument to bound method `MutableMapping.update` is incorrect: Expected `SupportsGetItem[str, V@UpdateDictMixin]`, found `Self@update`
+ src/werkzeug/datastructures/structures.py:238:20 error[invalid-argument-type] Argument to function `len` is incorrect: Expected `Sized`, found `V@MultiDict`
+ src/werkzeug/datastructures/structures.py:239:24 error[not-subscriptable] Cannot subscript object of type `V@MultiDict` with no `__getitem__` method
+ src/werkzeug/datastructures/structures.py:248:34 error[invalid-argument-type] Argument to bound method `dict.__setitem__` is incorrect: Expected `V@MultiDict`, found `list[V@MultiDict]`
+ src/werkzeug/datastructures/structures.py:258:9 error[no-matching-overload] No overload of bound method `MutableMapping.setdefault` matches arguments
+ src/werkzeug/datastructures/structures.py:281:27 error[invalid-assignment] Object of type `V@MultiDict` is not assignable to `list[V@MultiDict]`
+ src/werkzeug/datastructures/structures.py:310:34 error[invalid-argument-type] Argument to bound method `dict.__setitem__` is incorrect: Expected `V@MultiDict`, found `list[V@MultiDict]`
+ src/werkzeug/datastructures/structures.py:349:38 error[invalid-argument-type] Argument to bound method `dict.__setitem__` is incorrect: Expected `V@MultiDict`, found `list[Unknown]`
+ src/werkzeug/datastructures/structures.py:351:16 error[invalid-return-type] Return type does not match returned value: expected `list[V@MultiDict]`, found `V@MultiDict`
+ src/werkzeug/datastructures/structures.py:362:18 error[invalid-assignment] Object of type `V@MultiDict` is not assignable to `list[V@MultiDict]`
+ src/werkzeug/datastructures/structures.py:374:18 error[invalid-assignment] Object of type `V@MultiDict` is not assignable to `list[V@MultiDict]`
+ src/werkzeug/datastructures/structures.py:381:13 error[invalid-assignment] Object of type `V@MultiDict` is not assignable to `list[V@MultiDict]`
+ src/werkzeug/datastructures/structures.py:392:16 error[invalid-return-type] Return type does not match returned value: expected `Iterable[list[V@MultiDict]]`, found `dict_values[K@MultiDict, V@MultiDict]`
+ src/werkzeug/datastructures/structures.py:498:19 error[invalid-assignment] Object of type `V@MultiDict` is not assignable to `list[V@MultiDict]`
+ src/werkzeug/datastructures/structures.py:515:20 error[invalid-assignment] Object of type `tuple[K@MultiDict, V@MultiDict]` is not assignable to `tuple[K@MultiDict, list[V@MultiDict]]`
+ src/werkzeug/datastructures/structures.py:532:16 error[invalid-return-type] Return type does not match returned value: expected `list[V@MultiDict]`, found `V@MultiDict | list[Unknown]`
+ src/werkzeug/datastructures/structures.py:537:20 error[invalid-return-type] Return type does not match returned value: expected `tuple[K@MultiDict, list[V@MultiDict]]`, found `tuple[K@MultiDict, V@MultiDict]`

xarray (https://github.com/pydata/xarray)
+ xarray/core/resample.py:59:13 error[invalid-argument-type] Argument to bound method `DataArray.rename` is incorrect: Argument type `T_Xarray@Resample` does not satisfy upper bound `DataArray` of type variable `Self`
+ xarray/core/resample.py:59:13 error[invalid-argument-type] Argument to bound method `Dataset.rename` is incorrect: Argument type `T_Xarray@Resample` does not satisfy upper bound `Dataset` of type variable `Self`

Full report with detailed diff (timing results)

@AlexWaygood AlexWaygood removed their request for review April 19, 2026 16:00
@carljm carljm removed their request for review April 20, 2026 21:13
reveal_type(super()) # revealed: <super: <class 'MyProtocol'>, type[Self@__class_getitem__]>
parent_method = super().__class_getitem__
reveal_type(parent_method) # revealed: @Todo(super in generic class)
parent_method = super().__class_getitem__ # error: [unresolved-attribute] "Object of type `<super: <class 'MyProtocol'>, type[Self@__class_getitem__]>` has no attribute `__class_getitem__`"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The strawberry ecosystem changes are related to this. I think this new expectation is not correct; __class_getitem__ should be resolvable. I'm taking a quick look to see if there's an easy fix.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Latest patches remove the ecosystem changes for strawberry

@dcreager dcreager force-pushed the fix/goto-definition-for-generic-base-class branch from ed067d4 to e08bed1 Compare April 21, 2026 17:51
@dcreager
Copy link
Copy Markdown
Member

ecosystem: The bokeh change looks like a new true positive. All of the others look like existing false positives that are exposed in new places, but that aren't in scope for this PR.

@dcreager dcreager merged commit 4add3b1 into astral-sh:main Apr 21, 2026
56 checks passed
@felixscherz
Copy link
Copy Markdown
Contributor Author

Thank you for the review and fixing the __class_getitem__ lookup:)

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.

Generic class with typevar inheriting from other class does not resolve super().__init__() call for go to definition

2 participants