Skip to content

[ty] Emit diagnostic when specializing a non-generic class - #26883

Merged
dhruvmanila merged 3 commits into
mainfrom
dhruv/non-generic-class-diagnostic
Jul 30, 2026
Merged

[ty] Emit diagnostic when specializing a non-generic class#26883
dhruvmanila merged 3 commits into
mainfrom
dhruv/non-generic-class-diagnostic

Conversation

@dhruvmanila

@dhruvmanila dhruvmanila commented Jul 16, 2026

Copy link
Copy Markdown
Member

Summary

Emit not-subscriptable when a non-generic class is specialized in a type expression, and recover as Unknown instead of an internal @Todo type.

This highlighted some scenarios in the ecosystem result where not-subscriptable is being emitted but it might not be ideal, refer to my inline comments. I've added mdtest cases for these looking at the ecosystem result.

Closes astral-sh/ty#2439.

Test plan

Update the mdtest

@dhruvmanila dhruvmanila added the ty Multi-file analysis & type inference label Jul 16, 2026
@astral-sh-bot

astral-sh-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

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

@astral-sh-bot

astral-sh-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

Memory usage report

Summary

Project Old New Diff Outcome
prefect 449.89MB 449.90MB +0.00% (10.91kB)
flake8 28.73MB 28.73MB -
sphinx 166.01MB 166.01MB -
trio 69.92MB 69.92MB -

Significant changes

Click to expand detailed breakdown

prefect

Name Old New Diff Outcome
check_file_impl 17.71MB 17.72MB +0.06% (10.24kB)
infer_deferred_types 5.97MB 5.98MB +0.05% (3.05kB)
CallableType 3.29MB 3.29MB -0.01% (480.00B) ⬇️
TypePair 3.17MB 3.17MB -0.01% (264.00B) ⬇️
FunctionType 4.96MB 4.96MB -0.00% (224.00B) ⬇️
ProtocolInterface 558.41kB 558.22kB -0.03% (192.00B) ⬇️
IntersectionType 1.03MB 1.03MB -0.02% (184.00B) ⬇️
is_redundant_with_impl 1.34MB 1.34MB -0.01% (152.00B) ⬇️
Type<'db>::class_member_with_policy_inner_ 9.20MB 9.20MB -0.00% (144.00B) ⬇️
FunctionType<'db>::signature_ 2.84MB 2.84MB -0.00% (112.00B) ⬇️
UnionType 1.08MB 1.08MB -0.01% (112.00B) ⬇️
MemberLookupKey 6.59MB 6.59MB -0.00% (96.00B) ⬇️
cached_protocol_interface 219.49kB 219.40kB -0.04% (96.00B) ⬇️
member_lookup_with_policy_inner 10.69MB 10.69MB -0.00% (88.00B) ⬇️
Type<'db>::apply_specialization_inner_::interned_arguments 2.95MB 2.95MB -0.00% (80.00B) ⬇️
... 4 more

@astral-sh-bot

astral-sh-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

ecosystem-analyzer results

Lint rule Added Removed Changed
not-subscriptable 249 0 0
invalid-argument-type 0 0 8
unresolved-attribute 0 0 1
Total 249 0 9

Flaky changes detected. This PR summary excludes flaky changes; see the HTML report for details.

Raw diff (258 changes)
artigraph (https://github.com/artigraph/artigraph)
+ tests/arti/internal/test_type_hints.py:122:16 error[not-subscriptable] Cannot subscript non-generic type `<class 'MyTuple'>`
+ tests/arti/internal/test_type_hints.py:123:16 error[not-subscriptable] Cannot subscript non-generic type `<class 'MyTuple'>`
+ tests/arti/internal/test_type_hints.py:154:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'MyTuple'>`
+ tests/arti/internal/test_type_hints.py:157:35 error[not-subscriptable] Cannot subscript non-generic type `<class 'MyTuple'>`

bokeh (https://github.com/bokeh/bokeh)
+ src/bokeh/plotting/_legends.py:75:30 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataSpec'>`

check-jsonschema (https://github.com/python-jsonschema/check-jsonschema)
+ src/check_jsonschema/schema_loader/resolver.py:47:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'Resource'>`
+ src/check_jsonschema/schema_loader/resolver.py:59:41 error[not-subscriptable] Cannot subscript non-generic type `<class 'Resource'>`
+ src/check_jsonschema/schema_loader/resolver.py:93:34 error[not-subscriptable] Cannot subscript non-generic type `<class 'Resource'>`
+ src/check_jsonschema/schema_loader/resolver.py:95:53 error[not-subscriptable] Cannot subscript non-generic type `<class 'Resource'>`
+ src/check_jsonschema/schema_loader/resolver.py:102:40 error[not-subscriptable] Cannot subscript non-generic type `<class 'Resource'>`

django-modern-rest (https://github.com/wemake-services/django-modern-rest)
+ dmr/throttling/backends/redis.py:56:14 error[not-subscriptable] Cannot subscript non-generic type `<class 'Redis'>`
+ dmr/throttling/backends/redis.py:158:14 error[not-subscriptable] Cannot subscript non-generic type `<class 'Redis'>`

ibis (https://github.com/ibis-project/ibis)
+ ibis/expr/operations/temporal_windows.py:22:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/operations/temporal_windows.py:23:14 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/backends/polars/rewrites.py:17:14 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/backends/sql/rewrites.py:53:17 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/common/grounds.py:107:30 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/common/patterns.py:708:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/common/patterns.py:861:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/common/patterns.py:1271:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/common/patterns.py:1309:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/common/tests/test_grounds.py:131:11 error[not-subscriptable] Cannot subscript non-generic type `<class 'List'>`
+ ibis/common/tests/test_grounds.py:169:11 error[not-subscriptable] Cannot subscript non-generic type `<class 'Map'>`
+ ibis/common/tests/test_grounds.py:199:8 error[not-subscriptable] Cannot subscript non-generic type `<class 'List'>`
+ ibis/common/tests/test_grounds.py:200:8 error[not-subscriptable] Cannot subscript non-generic type `<class 'Map'>`
+ ibis/expr/datatypes/core.py:828:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/datatypes/tests/test_core.py:282:9 error[not-subscriptable] Cannot subscript non-generic type `<class 'MyList'>`
+ ibis/expr/datatypes/tests/test_core.py:284:9 error[not-subscriptable] Cannot subscript non-generic type `<class 'MyDict'>`
+ ibis/expr/datatypes/tests/test_core.py:286:9 error[not-subscriptable] Cannot subscript non-generic type `<class 'MyTuple'>`
+ ibis/expr/operations/relations.py:52:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/operations/relations.py:70:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/operations/relations.py:125:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/operations/relations.py:227:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/operations/relations.py:310:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/operations/relations.py:311:14 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/operations/relations.py:462:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/operations/relations.py:473:63 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/expr/rewrites.py:66:21 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/expr/rewrites.py:69:20 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
+ ibis/expr/rewrites.py:72:22 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenDict'>`
- ibis/expr/rewrites.py:177:37 error[unresolved-attribute] Attribute `__contains__` is not defined on `None` in union `@Todo | None`
+ ibis/expr/rewrites.py:177:37 error[unresolved-attribute] Attribute `__contains__` is not defined on `None` in union `Unknown | None`
+ ibis/expr/schema.py:30:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
- ibis/expr/types/joins.py:166:54 error[invalid-argument-type] Argument to bound method `DerefMap.from_targets` is incorrect: Expected `Mapping[Node, Node] | None`, found `dict[Field, @Todo & Field]`
+ ibis/expr/types/joins.py:166:54 error[invalid-argument-type] Argument to bound method `DerefMap.from_targets` is incorrect: Expected `Mapping[Node, Node] | None`, found `dict[Field, Unknown & Field]`
- ibis/expr/types/joins.py:167:64 error[invalid-argument-type] Argument to bound method `DerefMap.from_targets` is incorrect: Expected `Mapping[Node, Node] | None`, found `dict[Field, @Todo & Field]`
+ ibis/expr/types/joins.py:167:64 error[invalid-argument-type] Argument to bound method `DerefMap.from_targets` is incorrect: Expected `Mapping[Node, Node] | None`, found `dict[Field, Unknown & Field]`
+ ibis/expr/types/temporal.py:425:32 error[not-subscriptable] Cannot subscript non-generic type `<class 'Value'>`
+ ibis/expr/types/temporal.py:431:11 error[not-subscriptable] Cannot subscript non-generic type `<class 'Value'>`
+ ibis/expr/types/temporal.py:676:32 error[not-subscriptable] Cannot subscript non-generic type `<class 'Value'>`
+ ibis/expr/types/temporal.py:679:68 error[not-subscriptable] Cannot subscript non-generic type `<class 'Value'>`
+ ibis/expr/types/temporal.py:1158:36 error[not-subscriptable] Cannot subscript non-generic type `<class 'Value'>`
+ ibis/expr/types/temporal.py:1174:11 error[not-subscriptable] Cannot subscript non-generic type `<class 'Value'>`
- ibis/expr/types/temporal.py:490:41 error[invalid-argument-type] Argument is incorrect: Expected `Value[Time, Any]`, found `time | @Todo`
+ ibis/expr/types/temporal.py:490:41 error[invalid-argument-type] Argument is incorrect: Expected `Value[Time, Any]`, found `time | Unknown`
- ibis/expr/types/temporal.py:490:54 error[invalid-argument-type] Argument is incorrect: Expected `Value[String, Any]`, found `Literal["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"] | @Todo`
+ ibis/expr/types/temporal.py:490:54 error[invalid-argument-type] Argument is incorrect: Expected `Value[String, Any]`, found `Literal["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"] | Unknown`
- ibis/expr/types/temporal.py:734:41 error[invalid-argument-type] Argument is incorrect: Expected `Value[Date, Any]`, found `date | @Todo`
+ ibis/expr/types/temporal.py:734:41 error[invalid-argument-type] Argument is incorrect: Expected `Value[Date, Any]`, found `date | Unknown`
- ibis/expr/types/temporal.py:734:54 error[invalid-argument-type] Argument is incorrect: Expected `Value[String, Any]`, found `Literal["year", "quarter", "month", "week", "day"] | @Todo`
+ ibis/expr/types/temporal.py:734:54 error[invalid-argument-type] Argument is incorrect: Expected `Value[String, Any]`, found `Literal["year", "quarter", "month", "week", "day"] | Unknown`
- ibis/expr/types/temporal.py:1231:46 error[invalid-argument-type] Argument is incorrect: Expected `Value[Timestamp, Any]`, found `datetime | @Todo`
+ ibis/expr/types/temporal.py:1231:46 error[invalid-argument-type] Argument is incorrect: Expected `Value[Timestamp, Any]`, found `datetime | Unknown`
- ibis/expr/types/temporal.py:1231:59 error[invalid-argument-type] Argument is incorrect: Expected `Value[String, Any]`, found `Literal["year", "quarter", "month", "week", "day", ... omitted 6 literals] | @Todo`
+ ibis/expr/types/temporal.py:1231:59 error[invalid-argument-type] Argument is incorrect: Expected `Value[String, Any]`, found `Literal["year", "quarter", "month", "week", "day", ... omitted 6 literals] | Unknown`
+ ibis/expr/types/temporal_windows.py:29:22 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`
+ ibis/expr/types/temporal_windows.py:30:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'FrozenOrderedDict'>`

mypy (https://github.com/python/mypy)
+ mypy/typeshed/stdlib/builtins.pyi:108:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/builtins.pyi:110:31 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/builtins.pyi:151:44 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/builtins.pyi:165:48 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/builtins.pyi:168:48 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/builtins.pyi:171:44 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/builtins.pyi:173:46 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/builtins.pyi:176:51 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/builtins.pyi:879:19 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/builtins.pyi:217:14 error[not-subscriptable] Cannot subscript non-generic type `<class 'type'>`
+ mypy/typeshed/stdlib/typing.pyi:649:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'Coroutine'>`
+ mypy/typeshed/stdlib/typing.pyi:651:49 error[not-subscriptable] Cannot subscript non-generic type `<class 'Coroutine'>`
+ mypy/typeshed/stdlib/typing.pyi:657:10 error[not-subscriptable] Cannot subscript non-generic type `<class 'Coroutine'>`
+ mypy/typeshed/stdlib/typing.pyi:662:10 error[not-subscriptable] Cannot subscript non-generic type `<class 'Coroutine'>`
+ mypy/typeshed/stdlib/typing.pyi:664:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'Coroutine'>`
+ mypy/typeshed/stdlib/typing.pyi:684:59 error[not-subscriptable] Cannot subscript non-generic type `<class 'Sequence'>`
+ mypy/typeshed/stdlib/typing.pyi:702:59 error[not-subscriptable] Cannot subscript non-generic type `<class 'MutableSequence'>`
+ mypy/typeshed/stdlib/typing.pyi:733:53 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:734:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:735:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:736:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:737:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:738:30 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:738:54 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:739:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:739:52 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:740:30 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:740:54 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:741:30 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:741:53 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:754:27 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:755:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:756:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:757:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'AbstractSet'>`
+ mypy/typeshed/stdlib/typing.pyi:818:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'ItemsView'>`
+ mypy/typeshed/stdlib/typing.pyi:819:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'KeysView'>`
+ mypy/typeshed/stdlib/typing.pyi:820:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'ValuesView'>`
+ mypy/typeshed/stdlib/typing.pyi:847:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'MutableMapping'>`
+ mypy/typeshed/stdlib/typing.pyi:931:21 error[not-subscriptable] Cannot subscript non-generic type `<class 'IO'>`
+ mypy/typeshed/stdlib/typing.pyi:938:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'IO'>`
+ mypy/typeshed/stdlib/typing.pyi:948:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'IO'>`
+ mypy/typeshed/stdlib/typing.pyi:1005:18 error[not-subscriptable] Cannot subscript non-generic type `<class 'Mapping'>`
+ mypy/typeshed/stdlib/typing.pyi:1181:65 error[not-subscriptable] Cannot subscript non-generic type `<class 'Mapping'>`
+ mypyc/test-data/fixtures/typing-full.pyi:82:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'Generator'>`
+ mypyc/test-data/fixtures/typing-full.pyi:98:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'AsyncGenerator'>`
+ mypyc/test-data/fixtures/typing-full.pyi:103:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'Generator'>`

prefect (https://github.com/PrefectHQ/prefect)
+ src/prefect/server/orchestration/rules.py:278:34 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:327:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:328:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:473:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:474:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:582:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:583:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:690:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:691:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:733:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:734:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:856:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:857:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:963:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:964:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:983:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:984:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1016:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1017:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1064:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1065:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1146:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1147:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1194:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1195:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1228:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1229:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1260:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1261:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1293:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1294:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1331:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1332:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1354:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1355:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1401:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1402:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1420:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1421:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1475:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1476:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1494:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1495:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1526:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1527:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1567:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1568:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1591:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1592:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1662:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1663:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1684:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1685:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1738:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1739:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1782:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1783:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1820:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1821:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1879:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1880:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1923:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1924:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1955:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:1956:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:2029:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ src/prefect/server/orchestration/core_policy.py:2030:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`

pytest-autoprofile (https://gitlab.com/TTsangSC/pytest-autoprofile)
+ src/pytest_autoprofile/option_hooks.py:293:32 error[not-subscriptable] Cannot subscript non-generic type `<class 'Parser'>`

spark (https://github.com/apache/spark)
+ python/pyspark/pandas/tests/test_typedef.py:96:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:114:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:129:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:147:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:157:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:174:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:190:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:208:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:218:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:228:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:240:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:250:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:261:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:269:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`
+ python/pyspark/pandas/tests/test_typedef.py:280:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataFrame'>`

speedrun.com_global_scoreboard_webapp (https://github.com/Avasam/speedrun.com_global_scoreboard_webapp)
+ backend/api/global_scoreboard_api.py:70:33 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/core_models.py:73:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/core_models.py:74:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/core_models.py:75:33 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/core_models.py:76:34 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/core_models.py:77:32 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/core_models.py:78:34 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/game_search_models.py:24:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/game_search_models.py:25:32 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/game_search_models.py:26:27 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/game_search_models.py:27:32 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/game_search_models.py:28:40 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/game_search_models.py:29:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/game_search_models.py:30:30 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/game_search_models.py:31:30 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:20:17 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:23:23 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:24:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:33:21 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:34:18 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:39:37 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:40:32 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:41:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:44:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:45:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:46:31 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:47:34 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:48:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:87:17 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:89:18 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:94:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:95:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:96:26 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:97:29 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:124:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:125:27 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:126:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:127:35 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:139:35 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:140:36 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:141:43 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:142:32 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:144:33 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:214:33 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:215:36 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:231:28 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:236:17 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:243:36 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`
+ backend/models/tournament_scheduler_models.py:244:25 error[not-subscriptable] Cannot subscript non-generic type `<class 'Column'>`

sphinx (https://github.com/sphinx-doc/sphinx)
+ sphinx/highlighting.py:116:34 error[not-subscriptable] Cannot subscript non-generic type `<class 'Formatter'>`
+ sphinx/highlighting.py:132:47 error[not-subscriptable] Cannot subscript non-generic type `<class 'Formatter'>`
+ sphinx/util/docutils.py:432:32 error[not-subscriptable] Cannot subscript non-generic type `<class 'State'>`
+ sphinx/util/docutils.py:439:24 error[not-subscriptable] Cannot subscript non-generic type `<class 'StateMachine'>`

steam.py (https://github.com/Gobot1234/steam.py)
+ steam/types/achievement.py:17:12 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/achievement.py:64:11 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:41:19 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:56:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:57:17 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:73:17 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:79:12 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:106:33 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:137:12 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:261:30 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:308:13 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:309:15 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`
+ steam/types/manifest.py:310:15 error[not-subscriptable] Cannot subscript non-generic type `<class 'VDFList'>`

streamlit (https://github.com/streamlit/streamlit)
+ lib/streamlit/runtime/caching/cache_data_api.py:168:59 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataCache'>`
+ lib/streamlit/runtime/caching/cache_data_api.py:182:10 error[not-subscriptable] Cannot subscript non-generic type `<class 'DataCache'>`
+ lib/streamlit/runtime/caching/cache_resource_api.py:97:59 error[not-subscriptable] Cannot subscript non-generic type `<class 'ResourceCache'>`
+ lib/streamlit/runtime/caching/cache_resource_api.py:112:10 error[not-subscriptable] Cannot subscript non-generic type `<class 'ResourceCache'>`
+ lib/streamlit/runtime/caching/cache_resource_api.py:195:31 error[not-subscriptable] Cannot subscript non-generic type `<class 'ResourceCache'>`

Full report with detailed diff (timing results)

@dhruvmanila dhruvmanila changed the title [ty] Diagnose non-generic class specialization [ty] Emit diagnostic when specializing a non-generic class Jul 17, 2026
@dhruvmanila
dhruvmanila force-pushed the dhruv/non-generic-class-diagnostic branch from 75660b2 to 764bae1 Compare July 22, 2026 08:26
Comment on lines +173 to +187
```py
try:
import typing_extensions as typing
except ImportError:
import typing

T = typing.TypeVar("T")

# TODO: Fix the conditional typing import in https://github.com/astral-sh/ty/issues/1585.
# error: [invalid-argument-type] "`typing_extensions.TypeVar | typing.TypeVar` is not a valid argument to `Generic`"
class Parser(typing.Protocol, typing.Generic[T]): ...

# TODO: Remove this cascading error when https://github.com/astral-sh/ty/issues/1585 is fixed.
parser: Parser[int] # error: [not-subscriptable] "Cannot subscript non-generic type `<class 'Parser'>`"
```

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This definitely seems like a false positive which should be fixed by astral-sh/ty#1585 if I'm not wrong.

Comment on lines +194 to +214
```py
import collections.abc
from typing import Generic, TypeVar
from ty_extensions._internal import generic_context

K = TypeVar("K")
V = TypeVar("V")

# error: [unresolved-attribute] "Class `Mapping` has no attribute `register`"
@collections.abc.Mapping.register
class Mapping(Generic[K, V]): ...

# TODO: Invalid decorator causes us to lose the generic context from the class...
reveal_type(generic_context(Mapping)) # revealed: None

class FrozenDict(Mapping[K, V]): ...

# TODO: ...which then causes us to emit this
# error: [not-subscriptable] "Cannot subscript non-generic type `<class 'FrozenDict'>`"
mapping: FrozenDict[str, int]
```

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Pyright retains the generic context in this case but specializes to Unknown:

# Type of "FrozenDict" is "type[FrozenDict[Unknown, Unknown]]"
reveal_type(FrozenDict)

which is why I've added a similar TODO. Let me know if this is not the right solution and we should do something else.

Comment on lines +218 to +231
```py
from typing import TypeVar

from missing import Base # error: [unresolved-import]

reveal_type(Base) # revealed: Unknown

T = TypeVar("T")

class Child(Base[T]): ...

# error: [not-subscriptable] "Cannot subscript non-generic type `<class 'Child'>`"
child: Child[int]
```

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This looks fine which is why I've not added a TODO comment here. Only Pyright emits this diagnostic, none of the other type checkers do.

Comment on lines +256 to +269
from typing import TypeVar

try:
from base1 import Base
except ImportError:
from base2 import Base

T = TypeVar("T")

# error: [unsupported-base]
class Child(Base[T]): ...

# error: [not-subscriptable] "Cannot subscript non-generic type `<class 'Child'>`"
child: Child[int]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This looks fine which is why I've not added a TODO comment here. Only Pyright emits this diagnostic, none of the other type checkers do.

@dhruvmanila
dhruvmanila force-pushed the dhruv/non-generic-class-diagnostic branch from 764bae1 to d6ab44d Compare July 22, 2026 08:37
@dhruvmanila dhruvmanila added the diagnostics Related to reporting of diagnostics. label Jul 22, 2026
@dhruvmanila
dhruvmanila marked this pull request as ready for review July 22, 2026 08:38
@dhruvmanila
dhruvmanila requested a review from a team as a code owner July 22, 2026 08:38
@astral-sh-bot
astral-sh-bot Bot requested a review from ibraheemdev July 22, 2026 08:38
@dhruvmanila
dhruvmanila merged commit 4d4c8fa into main Jul 30, 2026
63 checks passed
@dhruvmanila
dhruvmanila deleted the dhruv/non-generic-class-diagnostic branch July 30, 2026 05:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

diagnostics Related to reporting of diagnostics. ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Emit diagnostic when specializing a non-generic class

2 participants