[ty] tighten up handling of subscripts in type expressions#21503
[ty] tighten up handling of subscripts in type expressions#21503
Conversation
Diagnostic diff on typing conformance testsChanges were detected when running ty on typing conformance tests |
|
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-type-form |
222 | 1 | 0 |
invalid-argument-type |
0 | 2 | 9 |
unused-ignore-comment |
4 | 3 | 0 |
non-subscriptable |
0 | 5 | 0 |
unresolved-reference |
5 | 0 | 0 |
invalid-await |
0 | 0 | 3 |
invalid-return-type |
0 | 0 | 3 |
possibly-missing-attribute |
0 | 0 | 3 |
type-assertion-failure |
0 | 0 | 3 |
unsupported-operator |
0 | 2 | 0 |
invalid-assignment |
0 | 0 | 1 |
| Total | 231 | 13 | 22 |
e62ea73 to
45e98ea
Compare
45e98ea to
1e1cab0
Compare
| p: int | f"foo", # error: [invalid-type-form] "F-strings are not allowed in type expressions" | ||
| q: [1, 2, 3][1:2], # error: [invalid-type-form] "Slices are not allowed in type expressions" | ||
| # error: [invalid-type-form] "Slices are not allowed in type expressions" | ||
| # error: [invalid-type-form] "Cannot subscript object of type" |
There was a problem hiding this comment.
I don't think this makes grammatical sense -- cannot subscript object of type what, exactly? 😄
Also, you can subscript [1, 2, 3], right?
There was a problem hiding this comment.
That's because it's a partial match on the message string, it's not the full message; I didn't feel like writing out the full types :)
I can include the full message, or at least enough to make it less confusing.
Also, you can subscript
[1, 2, 3], right?
The full message includes "in a type expression"
crates/ty_python_semantic/resources/mdtest/annotations/literal.md
Outdated
Show resolved
Hide resolved
1e1cab0 to
d32b0d6
Compare
|
| # TODO should be Unknown | int | ||
| reveal_type(type_var_or_int) # revealed: T@_ | int | ||
| # TODO should be int | Unknown | ||
| reveal_type(int_or_type_var) # revealed: int | T@_ | ||
| # TODO should be Unknown | None | ||
| reveal_type(type_var_or_none) # revealed: T@_ | None | ||
| # TODO should be None | Unknown | ||
| reveal_type(none_or_type_var) # revealed: None | T@_ |
There was a problem hiding this comment.
I was actually going to ask if you wanted these tests here or in a separate "generics" section, since they are testing the combination of both generic aliases and unions :) Feel free to move them if you want in your PR.
* origin/main: [ty] Fix flaky tests on macos (#21524) [ty] Add tests for generic implicit type aliases (#21522) [ty] Semantic tokens: consistently add the `DEFINITION` modifier (#21521) Only render hyperlinks for terminals known to support them (#21519) [ty] Keep colorizing `mypy_primer` output (#21515) [ty] Exit with `2` if there's any IO error (#21508) [`ruff`] Fix false positive for complex conversion specifiers in `logging-eager-conversion` (`RUF065`) (#21464) [ty] tighten up handling of subscripts in type expressions (#21503)
* origin/main: [ty] Fix flaky tests on macos (#21524) [ty] Add tests for generic implicit type aliases (#21522) [ty] Semantic tokens: consistently add the `DEFINITION` modifier (#21521) Only render hyperlinks for terminals known to support them (#21519) [ty] Keep colorizing `mypy_primer` output (#21515) [ty] Exit with `2` if there's any IO error (#21508) [`ruff`] Fix false positive for complex conversion specifiers in `logging-eager-conversion` (`RUF065`) (#21464) [ty] tighten up handling of subscripts in type expressions (#21503)
Summary
Get rid of the catch-all todo type from subscripting a base type we haven't implemented handling for yet in a type expression, and turn it into a diagnostic instead.
Handle a few more cases explicitly, to avoid false positives from the above change:
Test Plan
Adjusted mdtests, ecosystem.
All new diagnostics in conformance suite are supposed to be diagnostics, so this PR is a strict improvement there.
New diagnostics in the ecosystem are surfacing cases where we already don't understand an annotation, but now we emit a diagnostic about it. They are mostly intentional choices. Analysis of particular cases:
attrs,bokeh,django-stubs,dulwich,ibis,kornia,mitmproxy,mongo-python-driver,mypy,pandas,poetry,prefect,pydantic,pytest,scrapy,trio,werkzeug, andxarrayare all cases where underfrom __future__ import annotationsor Python 3.14 deferred-annotations semantics, we follow normal name-scoping rules, whereas some other type checkers prefer global names over local names. This means we don't like it if e.g. you have a class with a method or attribute namedtypeortuple, and you also try to usetypeortuplein method/attribute annotations of that class. This PR isn't changing those semantics, just revealing them in more cases where previously we just silently fell back toUnknown. I think failing with a diagnostic (so authors can alias names as needed to avoid relying on scoping rules that differ between type checkers) is better than failing silently here.beartypeassumes we supportTypeForm(because it only supports mypy and pyright, it usesif MYPY:to hide theTypeFormfrom mypy, and pyright supportsTypeForm), and we don't yet.graphql-corelikes to use atry: ... except ImportError: ...pattern for importing special forms fromtypingwith fallback totyping_extensions, instead of usingsys.version_infochecks. We don't handle this well when type checking under an older Python version (where the import fromtypingis not found); we see the imported name as of type e.g.Unknown | SpecialFormType(...), and because of the union withUnknownwe fail to handle it as the special form type. Mypy and pyright also don't seem to support this pattern. They don't complain about subscripting such special forms, but they do silently fail to treat them as the desired special form. Again here, if we are going to fail I'd rather fail with a diagnostic rather than silently.ibisis trying to usefrozendict: type[FrozenDict]as a way to create a "type alias" toFrozenDict, but this is wrong: that meansfrozendict: type[FrozenDict[Any, Any]].mypyhas some errors due to the fact that type-checkingtyping.pyiitself (without knowing that it's the realtyping.pyi) doesn't work very well.mypy-protobufimports some types from the protobufs library that end up unioned withUnknownfor some reason, and so we don't allow explicit-specialization of them. Depending on the reason they end up unioned withUnknown, we might want to better support this? But it's orthogonal to this PR -- we aren't failing any worse here, just alerting the author that we didn't understand their annotation.pwndbghas unresolved references due to star-importing from a dependency that isn't installed, and uses un-imported names likeDictin annotation expressions. Some of the unresolved references were hidden by https://github.com/astral-sh/ruff/blob/main/crates/ty_python_semantic/src/types/infer/builder.rs#L7223-L7228 when some annotations previously resolved to a Todo type that no longer do.