Skip to content

fix Conformance: Missing type alias validation #2451#3174

Draft
asukaminato0721 wants to merge 8 commits intofacebook:mainfrom
asukaminato0721:2451
Draft

fix Conformance: Missing type alias validation #2451#3174
asukaminato0721 wants to merge 8 commits intofacebook:mainfrom
asukaminato0721:2451

Conversation

@asukaminato0721
Copy link
Copy Markdown
Contributor

@asukaminato0721 asukaminato0721 commented Apr 18, 2026

Summary

Fixes #2451

factored the syntax check into a reusable helper.

detect NameAssign bindings that were never real implicit aliases and surface the syntax error at the annotation use site.

preserves normal runtime-value typing while fixing the implicit-alias false negatives.

Test Plan

update test

@meta-cla meta-cla Bot added the cla signed label Apr 18, 2026
@asukaminato0721 asukaminato0721 marked this pull request as ready for review April 18, 2026 08:34
Copilot AI review requested due to automatic review settings April 18, 2026 08:34
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes missing validation for “implicit type aliases” whose RHS is not a valid annotation/type-expression syntax, ensuring these now error at the annotation use site (conformance #2451). The PR also refactors annotation-syntax validation into a reusable helper and updates conformance baselines.

Changes:

  • Refactor annotation syntax validation into annotation_syntax_problem and reuse it for diagnostics.
  • Detect invalid implicit type-alias bindings (via NameAssign) and surface InvalidAnnotation at the annotation usage site.
  • Update tests and third-party conformance expectation/result artifacts to reflect the new diagnostics.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
pyrefly/lib/alt/solve.rs Adds reusable annotation-syntax helper and new implicit type-alias syntax validation that reports invalid-annotation at use sites.
pyrefly/lib/test/type_alias.rs Updates the conformance test case to expect the new, more specific annotation-syntax errors.
conformance/third_party/results.json Updates aggregated third-party conformance pass/fail counts.
conformance/third_party/conformance.result Updates per-test expectation summary to reflect aliases_implicit.py now passing.
conformance/third_party/conformance.exp Updates expected diagnostic outputs (messages/kinds) for the affected conformance cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pyrefly/lib/alt/solve.rs Outdated
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot added size/l and removed size/l labels Apr 18, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot added size/l and removed size/l labels Apr 18, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@migeed-z migeed-z self-assigned this Apr 20, 2026
@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync Bot commented Apr 20, 2026

@migeed-z has imported this pull request. If you are a Meta employee, you can view this in D101670073.

Comment thread pyrefly/lib/alt/solve.rs Outdated
Comment thread pyrefly/lib/test/type_alias.rs
Comment thread pyrefly/lib/test/type_alias.rs
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@migeed-z
Copy link
Copy Markdown
Contributor

Hmmm. I am not sure this approach is the right one. The reason is that something like this:

DynClass = type("DynClass", (), {})
def f(x: DynClass) -> None:  # E: Function call cannot be used in annotations
    pass

will fail and introduce false positives. The reason is that we are interpreting type(..) as a function call and rejecting it, but we should interpret the type of the value instead. So I think the approach needs to be modified to do that instead.

@github-actions github-actions Bot added size/l and removed size/l labels Apr 22, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@asukaminato0721 asukaminato0721 marked this pull request as draft April 22, 2026 08:31
@asukaminato0721 asukaminato0721 force-pushed the 2451 branch 2 times, most recently from d36f325 to 58df9a1 Compare April 22, 2026 15:03
@github-actions github-actions Bot added size/l and removed size/l labels Apr 22, 2026
@asukaminato0721 asukaminato0721 marked this pull request as ready for review April 22, 2026 15:11
@github-actions github-actions Bot added size/l and removed size/l labels Apr 22, 2026
@github-actions
Copy link
Copy Markdown

Diff from mypy_primer, showing the effect of this PR on open source code:

pytest-autoprofile (https://gitlab.com/TTsangSC/pytest-autoprofile)
- ERROR src/pytest_autoprofile/_typing.py:81:10-14: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR src/pytest_autoprofile/_typing.py:81:10-14: Function call cannot be used in annotations [invalid-annotation]

mypy (https://github.com/python/mypy)
- ERROR mypy/typeshed/stdlib/typing.pyi:410:20-22: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:410:27-29: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:411:24-26: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:411:31-33: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:410:20-22: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:410:27-29: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:411:24-26: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:411:31-33: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:421:34-37: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:421:42-45: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:421:34-37: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:421:42-45: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:466:28-31: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:466:36-39: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:466:28-31: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:466:36-39: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:501:26-31: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:501:26-31: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:511:45-50: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:511:45-50: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:534:27-32: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:534:27-32: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:548:27-37: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:550:27-40: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:550:48-58: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:555:10-20: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:558:98-108: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:548:27-37: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:550:27-40: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:550:48-58: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:555:10-20: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:558:98-108: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:592:27-43: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:592:51-61: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:597:10-20: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:600:98-108: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:592:27-43: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:592:51-61: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:597:10-20: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:600:98-108: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:630:28-41: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:630:28-41: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:658:45-50: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:658:45-50: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:671:41-43: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:674:45-47: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:671:41-43: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:674:45-47: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:680:46-48: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:680:46-48: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:691:29-31: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:691:29-31: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:695:42-44: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:696:29-31: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:695:42-44: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:696:29-31: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:719:26-28: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:721:30-32: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:724:22-24: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:725:29-31: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:719:26-28: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:721:30-32: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:724:22-24: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:725:29-31: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:780:32-35: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:780:43-49: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:783:24-27: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:780:32-35: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:780:43-49: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:783:24-27: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:787:24-27: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:787:38-40: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:787:24-27: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:787:38-40: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:796:32-35: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:796:44-47: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:798:32-35: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:801:24-27: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:801:35-38: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:803:24-27: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:803:38-41: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:803:49-52: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:805:24-27: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:805:38-40: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:796:32-35: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:796:44-47: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:798:32-35: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:801:24-27: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:801:35-38: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:803:24-27: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:803:38-41: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:803:49-52: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:805:24-27: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:805:38-40: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:814:63-66: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:814:63-66: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:816:31-34: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:816:45-48: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:816:56-59: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:816:31-34: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:816:45-48: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:816:56-59: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:840:99-102: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:840:99-102: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:844:92-95: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:844:92-95: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:846:62-65: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:846:62-65: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:877:39-45: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:881:47-53: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:877:39-45: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:881:47-53: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:899:24-30: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:899:24-30: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:907:27-33: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:907:27-33: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypy/typeshed/stdlib/typing.pyi:985:38-40: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:992:26-28: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:992:36-38: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:994:26-28: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:994:46-48: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:1051:39-41: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:1157:26-28: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypy/typeshed/stdlib/typing.pyi:1157:36-38: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypy/typeshed/stdlib/typing.pyi:985:38-40: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:992:26-28: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:992:36-38: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:994:26-28: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:994:46-48: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:1051:39-41: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:1157:26-28: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypy/typeshed/stdlib/typing.pyi:1157:36-38: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:69:27-31: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:69:27-31: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:73:27-28: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:73:33-34: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:76:26-29: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:76:36-39: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:76:50-53: Expected a type form, got instance of `object` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:73:27-28: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:73:33-34: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:76:26-29: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:76:36-39: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:76:50-53: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:89:28-29: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:89:28-29: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:92:27-30: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:92:37-40: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:92:51-54: Expected a type form, got instance of `object` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:92:27-30: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:92:37-40: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:92:51-54: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:110:27-28: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:110:33-34: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:113:26-29: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:113:36-39: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:113:50-53: Expected a type form, got instance of `object` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:110:27-28: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:110:33-34: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:113:26-29: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:113:36-39: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:113:50-53: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:131:30-33: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:131:38-42: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:131:30-33: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:131:38-42: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:135:32-33: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:135:38-42: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:135:32-33: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:135:38-42: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:137:22-23: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:137:22-23: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:139:22-23: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:139:22-23: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:146:30-31: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:146:36-37: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:146:30-31: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:146:36-37: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:154:28-29: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:154:34-35: Expected a type form, got instance of `TypeVar` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:154:28-29: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:154:34-35: Function call cannot be used in annotations [invalid-annotation]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:158:28-29: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:160:34-37: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:160:50-53: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:160:66-69: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:160:74-77: Expected a type form, got instance of `object` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:169:20-21: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:169:26-27: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:171:29-37: Expected a type form, got instance of `Literal[0]` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:173:22-30: Expected a type form, got instance of `Literal[0]` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:173:41-42: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:174:22-23: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:174:30-31: Expected a type form, got instance of `TypeVar` [not-a-type]
- ERROR mypyc/test-data/fixtures/typing-full.pyi:175:30-38: Expected a type form, got instance of `Literal[0]` [not-a-type]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:158:28-29: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:160:34-37: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:160:50-53: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:160:66-69: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:160:74-77: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:169:20-21: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:169:26-27: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:171:29-37: Number literal cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:173:22-30: Number literal cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:173:41-42: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:174:22-23: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:174:30-31: Function call cannot be used in annotations [invalid-annotation]
+ ERROR mypyc/test-data/fixtures/typing-full.pyi:175:30-38: Number literal cannot be used in annotations [invalid-annotation]

paasta (https://github.com/yelp/paasta)
+ ERROR paasta_tools/bounce_lib.py:81:17-39: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/bounce_lib.py:86:6-24: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/bounce_lib.py:110:17-39: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/bounce_lib.py:115:6-24: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/bounce_lib.py:128:17-39: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/bounce_lib.py:133:6-24: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/bounce_lib.py:155:17-39: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/bounce_lib.py:160:6-24: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/bounce_lib.py:173:17-39: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/bounce_lib.py:178:6-24: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/drain_lib.py:263:16-23: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/drain_lib.py:264:24-31: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/drain_lib.py:265:22-29: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/drain_lib.py:266:26-33: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/drain_lib.py:304:45-52: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/frameworks/native_service_config.py:96:14-20: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/frameworks/native_service_config.py:97:15-22: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/frameworks/native_service_config.py:102:16-29: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/frameworks/native_service_config.py:103:14-25: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/generate_deployments_for_service.py:132:18-29: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/generate_deployments_for_service.py:227:77-88: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/generate_deployments_for_service.py:228:6-21: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/hacheck.py:39:40-49: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/hacheck.py:67:19-28: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/kubernetes_tools.py:2346:22-40: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/kubernetes_tools.py:2454:17-30: Function call cannot be used in annotations [invalid-annotation]
+ ERROR paasta_tools/mesos/master.py:301:41-53: Function call cannot be used in annotations [invalid-annotation]

@github-actions
Copy link
Copy Markdown

Primer Diff Classification

❌ 2 regression(s) | ➖ 1 neutral | 3 project(s) total | +132, -105 errors

2 regression(s) across mypy, paasta. error kinds: invalid-annotation, not-a-type, invalid-annotation on functional TypedDict/NamedTuple. caused by implicit_type_alias_syntax_problem().

Project Verdict Changes Error Kinds Root Cause
pytest-autoprofile ➖ Neutral +1, -1 invalid-annotation, not-a-type implicit_type_alias_syntax_problem()
mypy ❌ Regression +104, -104 invalid-annotation, not-a-type implicit_type_alias_syntax_problem()
paasta ❌ Regression +27 invalid-annotation on functional TypedDict/NamedTuple implicit_type_alias_syntax_problem()
Detailed analysis

❌ Regression (2)

mypy (+104, -104)

This is a regression. The PR introduces a new check for bad implicit type aliases but fails to handle the case where TypeVar/ParamSpec/TypeVarTuple are defined locally (as in typing.pyi) rather than imported. The result is 104 false positive invalid-annotation errors on perfectly valid TypeVar usage like def overload(func: _F) -> _F where _F = TypeVar('_F', ...). The old not-a-type errors were also false positives, so this is a lateral move between two sets of false positives — but the error message changed from somewhat informative to actively misleading ('Function call cannot be used in annotations' for a TypeVar definition).
Attribution: The new implicit_type_alias_syntax_problem() method in pyrefly/lib/alt/solve.rs triggers invalid-annotation errors at annotation use sites. The implicit_alias_call_uses_runtime_type() method fails to recognize TypeVar when it's defined as a class in the same file (typing.pyi) rather than imported, because call_targets_special_export() can't trace the local class definition back to a known special export.

paasta (+27)

invalid-annotation on functional TypedDict/NamedTuple: The PR's new implicit alias validation doesn't recognize TypedDict() and similar functional-form type constructors as valid type-creating calls. The code uses mypy_extensions.TypedDict(...) to define types like BounceMethodConfigDict and BounceMethodResult, which are then used in parameter and return annotations. The functional form of TypedDict is explicitly supported by the typing spec. Notably, 27/27 errors also appear in pyright, suggesting this is a broader tooling limitation with mypy_extensions.TypedDict rather than a pyrefly-specific bug — but the code is semantically correct regardless. The allowlist needs to include TypedDict from all common sources (typing, typing_extensions, mypy_extensions), NamedTuple, and other type-creating callables. All 27 errors are false positives (regression).

Overall: The PR introduces a new check for 'bad implicit type aliases' that flags functional-form TypedDict calls used in annotations. The code uses mypy_extensions.TypedDict(...) to create types like BounceMethodConfigDict and BounceMethodResult, which are then used as parameter and return type annotations. The functional form of TypedDict is valid per the typing spec and creates legitimate types usable in annotations.

However, the cross-check shows 27/27 errors also appear in pyright, which complicates the analysis. This suggests the issue may not be a simple pyrefly-specific allowlist omission but rather a broader tooling limitation with mypy_extensions.TypedDict specifically (as opposed to typing.TypedDict or typing_extensions.TypedDict). Both checkers may not fully recognize mypy_extensions.TypedDict as a type-creating callable.

Nevertheless, the code is semantically correct — TypedDict(...) from any source creates a valid type that should be usable in annotations. The 27 errors are false positives in the sense that the annotated code is valid Python typing. The new invalid-annotation check needs to recognize TypedDict (from all common sources including mypy_extensions), NamedTuple, and other functional-form type constructors as valid type-creating calls.

Attribution: The new implicit_type_alias_syntax_problem() function in pyrefly/lib/alt/solve.rs walks NameAssign bindings and checks if the RHS call is in a hardcoded allowlist via implicit_alias_call_uses_runtime_type(). This allowlist includes TypeVar/ParamSpec/TypeVarTuple/builtins.type but omits TypedDict, NamedTuple, and other valid type-creating functional forms. The check at line 5796-5803 of solve.rs then fires ErrorKind::InvalidAnnotation for these legitimate patterns.

➖ Neutral (1)

pytest-autoprofile (+1, -1)

Without the source code, we cannot definitively determine whether these errors are false positives. The old error 'Expected a type form, got instance of TypeVar' indicates pyrefly detected a TypeVar being used where a type form was expected. The new error 'Function call cannot be used in annotations' indicates the updated checker now sees a function call in an annotation context. There are several possibilities: (1) The code uses a TypeVar() call directly inline in an annotation, which is genuinely invalid — you must assign TypeVar() to a variable first. In this case, both errors would be true positives with different messages. (2) The code uses a properly-defined TypeVar variable in an annotation, which should be valid. In this case, both would be false positives. (3) The code involves some intermediate pattern (e.g., a TypeVar created through a helper function or re-exported through a typing compatibility module like _typing.py suggests). Since the file is _typing.py, it likely defines typing utilities, and line 81 may involve TypeVar creation or aliasing patterns that the checker doesn't fully recognize. The transition from [not-a-type] to [invalid-annotation] represents a change in how the checker categorizes this construct. Without source code, we cannot confirm whether the new error is better, worse, or equivalent. If pyrefly's implicit_alias_call_uses_runtime_type() is meant to exempt TypeVar/ParamSpec/TypeVarTuple calls and is failing to do so, that would be a regression. If the old error was also wrong, it's a lateral move between two false positives. The net assessment depends entirely on the actual code pattern at line 81.
Attribution: The PR adds implicit_type_alias_syntax_problem() in pyrefly/lib/alt/solve.rs which checks if a name binding comes from a NameAssign with a Call expression. It has logic to exempt TypeVar/ParamSpec/TypeVarTuple calls via implicit_alias_call_uses_runtime_type(), but this exemption appears to be failing for the specific pattern in pytest_autoprofile/_typing.py. The test test_typevar_not_treated_as_bad_implicit_alias shows the PR author was aware of this edge case, but the exemption logic may not cover all patterns (e.g., re-exported TypeVar constructors, or TypeVar created through an intermediate import path). The new check at line 5793+ in solve.rs fires the invalid-annotation error before the normal type resolution can identify it as a TypeVar.

Suggested fixes

Summary: The new implicit_type_alias_syntax_problem() check fails to recognize TypeVar/ParamSpec/TypeVarTuple when defined as local classes (e.g., in typing.pyi) rather than imported, causing 66+ pyrefly-only false positive invalid-annotation errors.

1. In implicit_alias_call_uses_runtime_type() in pyrefly/lib/alt/solve.rs, after the existing call_targets_special_export() check, add a fallback that infers the type of the call expression and checks if the result is Type::TypeVar, Type::ParamSpec, or Type::TypeVarTuple. Currently this fallback exists in implicit_type_alias_syntax_problem() but it runs expr_infer on name_assign.expr (the full RHS), which may not always resolve correctly. Instead, move/duplicate this check into implicit_alias_call_uses_runtime_type() where it can directly evaluate the call result. Additionally, in call_targets_special_export_inner(), when handling Expr::Name that resolves to a ClassDef binding (not just NameAssign), check if the class name matches a known special export (TypeVar, ParamSpec, TypeVarTuple) — this handles the case in typing.pyi where TypeVar is a locally-defined class, not an import.

Files: pyrefly/lib/alt/solve.rs
Confidence: high
Affected projects: mypy, pytest-autoprofile
Fixes: invalid-annotation
In typing.pyi, TypeVar is defined as class TypeVar: locally. When code does _F = TypeVar('_F'), call_targets_special_export() follows the binding for TypeVar but hits a ClassDef binding (not a NameAssign with an import). The special_export_from_binding_idx() function only handles Forward, NameAssign, and Import bindings — it returns None for ClassDef. Adding a ClassDef arm that checks if the class name matches a SpecialExport would fix this. Specifically, in special_export_from_binding_idx(), add: Binding::ClassDef(class_def) => return SpecialExport::new(&class_def.name). This would allow the 66 pyrefly-only errors in mypy and the 1 pyrefly-only error in pytest-autoprofile to be resolved.

2. In special_export_from_binding_idx() in pyrefly/lib/alt/solve.rs, add a match arm for Binding::ClassDef that extracts the class name and checks it against SpecialExport::new(). Currently the function handles Forward, NameAssign, Import, and Phi bindings but falls through to None for ClassDef. Add: Binding::ClassDef(class_def) => { return SpecialExport::new(&class_def.name); } This handles the case where TypeVar/ParamSpec/TypeVarTuple are defined as classes in the current module (as in typing.pyi stubs).

Files: pyrefly/lib/alt/solve.rs
Confidence: high
Affected projects: mypy, pytest-autoprofile
Fixes: invalid-annotation
This is the precise missing case. In typing.pyi, TypeVar resolves to a local ClassDef binding. The special_export_from_binding_idx loop doesn't handle ClassDef, so it returns None, causing implicit_alias_call_uses_runtime_type to return false, which then triggers the invalid-annotation error. This fix eliminates 66 pyrefly-only errors in mypy and 1 in pytest-autoprofile.


Was this helpful? React with 👍 or 👎

Classification by primer-classifier (3 LLM)

@asukaminato0721 asukaminato0721 marked this pull request as draft April 22, 2026 17:43
@github-actions github-actions Bot added size/xl and removed size/l labels Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Conformance: Missing type alias validation

3 participants