Skip to content

Complete TypeForm conformance - #11599

Merged
Rich Chiodo (rchiodo) merged 15 commits into
mainfrom
rchiodo-refresh-typeform-support
Aug 11, 2026
Merged

Complete TypeForm conformance#11599
Rich Chiodo (rchiodo) merged 15 commits into
mainfrom
rchiodo-refresh-typeform-support

Conversation

@rchiodo

Copy link
Copy Markdown
Collaborator

Summary

Merged #11412 safely enabled PEP 747 TypeForm support by default. This follow-up completes the remaining behavior required by the current typing specification on current main, without reusing the stale #11302 branch.

  • Isolate TypeForm-context evaluation in an expected-type-keyed cache so it cannot overwrite ordinary runtime-expression results.
  • Preserve contextual results for evaluator and language-service clients, including explicit TypeForm(...) calls.
  • Treat bare TypeForm as TypeForm[Any] and retain TypeForm metadata through nested Self and experimental inline TypedDict expressions.
  • Reject invalid root and nested special forms, empty TypeForm[()], annotation-only qualifiers, InitVar, bare ParamSpec, and bare TypeVarTuple forms.
  • Preserve valid nested Callable, Concatenate, unpack, forward-reference, and mixed-union behavior.
  • Recognize subscripted runtime builtins such as list[int] as types.GenericAlias conservatively, without accepting typing special forms.

String parsing and recursion safety

String literals are interpreted as quoted type expressions only when the active context specifically wants a TypeForm. Ordinary string-list evaluation remains unchanged. In particular, NamedTuple field-name strings are not speculatively evaluated as types, preserving the existing Call5 regression for the recursion/cycle reported against #11302.

Conformance

Using the current upstream python/typing conformance/tests/typeforms_typeform.py with the locally built CLI configured for Python 3.12 produces exactly 18 errors and no other diagnostics at:

23, 24, 59, 67, 68, 69, 70, 71, 72, 73, 74, 75, 86, 86, 88, 88, 98, 108

The current-main baseline produced an unwanted diagnostic at line 49 and missed required diagnostics at lines 70-72 and 74.

Validation

  • All eight type evaluator suites: 1,184 tests passed
  • Focused TypeForm, NamedTuple Call5, Sentinel, TypeVarTuple, and inline TypedDict regressions
  • packages/pyright-internal: npm run build
  • npm run check:eslint
  • npm run check:prettier
  • npm run build:cli:dev
  • Exact upstream conformance diagnostic-multiset check with --pythonversion 3.12

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@StellaHuang95

Stella Huang (StellaHuang95) commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

🔒 Automated review in progress — Stella Huang (@StellaHuang95) is auto-reviewing this PR.

@github-actions

This comment has been minimized.

@StellaHuang95

Copy link
Copy Markdown
Collaborator

getCachedType now bypasses required cache-read safeguards and can expose incomplete or flag-incompatible results. The TypeForm changes also lack the required Pylance async-path implementation and product-harness coverage.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@StellaHuang95 Stella Huang (StellaHuang95) added the review-auto:approved Automated review: no blocking findings (approval posted). label Aug 7, 2026
Rich Chiodo (rchiodo) and others added 2 commits August 6, 2026 17:45
…samples

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore the isIncomplete guard that readTypeCache provided so the
cache-only type dump does not expose partially-evaluated types, while
still using readTypeCacheEntryForNode to find TypeForm-cached entries.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rchiodo

Copy link
Copy Markdown
Collaborator Author

Thanks for the review.

getCachedType safeguards — Partially addressed in 2bbb136. Restored the incomplete-result guard so the cache-only type dump no longer exposes partially-evaluated types (matching the old readTypeCache behavior), while still routing through readTypeCacheEntryForNode so TypeForm-cached entries are found. The evaluator-flag verification is intentionally not reintroduced on this path: TypeForm entries are cached with TypeFormArg flags, so verifying against EvalFlags.None (as the old call did) would spuriously fail. Note this API is only consumed by languageInfoUtils.ts in cacheOnly debug-dump mode.

Pylance async-path / product-harness coverage — Not applicable here. This PR targets upstream microsoft/pyright (packages: pyright, pyright-internal, pyright-typeserver, vscode-pyright); there is no pylance-internal package or Pylance async program model in this repo, so there is no async path to mirror. Coverage follows Pyright's sample + validateResults convention, which the PR extends (typeForm2/3/4/6/8, typedDictInline1, and typeEvaluator8.test.ts). All TypeForm tests pass.

@github-actions

This comment has been minimized.

Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts
Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Extracts the duplicated incomplete-generation-count logic shared by the
regular type cache and the TypeForm type cache into a single
updateIncompleteGenerationCount helper so the two cache-invalidation
paths cannot drift. This also aligns the TypeForm path with the regular
path for the incomplete-result generation bump.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Consolidates the triplicated expected-type match predicate (readTypeFormTypeCacheEntry find, writeTypeCache oldEntry find, and writeTypeCache eviction filter) into a single entryMatchesExpectedType helper, deriving the eviction filter from its negation so the three sites can no longer drift.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@github-actions

This comment has been minimized.

Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts Outdated
Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Separate contextual TypeForm cache lookup from the runtime subnode evaluation API and cover both annotated and explicit TypeForm cache cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts
Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Avoid reporting an invalid TypeForm diagnostic for ordinary nested TypeAlias annotations and document contextual cache precedence.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@github-actions

This comment has been minimized.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts Outdated
Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts
Comment thread packages/pyright-internal/src/analyzer/typeEvaluator.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

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

sympy (https://github.com/sympy/sympy)
-   .../projects/sympy/sympy/simplify/powsimp.py:686:13 - error: Operator "*=" not supported for types "Unknown | Literal[1]" and "Basic | Unknown"
-     Operator "*" not supported for types "Literal[1]" and "Basic" (reportOperatorIssue)
-   .../projects/sympy/sympy/simplify/powsimp.py:688:24 - error: Argument of type "Basic | Unknown" cannot be assigned to parameter "b" of type "Expr | complex" in function "__new__"
-     Type "Basic | Unknown" is not assignable to type "Expr | complex"
-       Type "Basic" is not assignable to type "Expr | complex"
-         "Basic" is not assignable to "Expr"
-         "Basic" is not assignable to "complex" (reportArgumentType)
-   .../projects/sympy/sympy/simplify/powsimp.py:704:29 - error: Cannot access attribute "as_numer_denom" for class "GaussianRational"
-     Attribute "as_numer_denom" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/powsimp.py:704:29 - error: Cannot access attribute "as_numer_denom" for class "MPQ"
-     Attribute "as_numer_denom" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/powsimp.py:704:29 - error: Cannot access attribute "as_numer_denom" for class "GaussianInteger"
-     Attribute "as_numer_denom" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/powsimp.py:704:29 - error: Cannot access attribute "as_numer_denom" for class "MPZ"
-     Attribute "as_numer_denom" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/powsimp.py:713:24 - error: Cannot access attribute "as_coeff_Mul" for class "Basic"
-     Attribute "as_coeff_Mul" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/powsimp.py:714:46 - error: Operator "/" not supported for types "Basic | Unknown" and "Basic"
-     Operator "/" not supported for types "Basic" and "Basic" (reportOperatorIssue)
-   .../projects/sympy/sympy/simplify/radsimp.py:939:20 - error: Operator "/" not supported for types "Literal[1]" and "Unknown | Expr | None"
+   .../projects/sympy/sympy/simplify/radsimp.py:939:20 - error: Operator "/" not supported for types "Literal[1]" and "Expr | Unknown | None"
-   .../projects/sympy/sympy/simplify/radsimp.py:950:36 - error: Argument of type "Unknown | Expr | Basic | bool | None" cannot be assigned to parameter "expr" of type "Expr" in function "make_args"
+   .../projects/sympy/sympy/simplify/radsimp.py:950:36 - error: Argument of type "Expr | Unknown | Basic | bool | None" cannot be assigned to parameter "expr" of type "Expr" in function "make_args"
-     Type "Unknown | Expr | Basic | bool | None" is not assignable to type "Expr"
+     Type "Expr | Unknown | Basic | bool | None" is not assignable to type "Expr"
-   .../projects/sympy/sympy/simplify/radsimp.py:999:36 - error: Operator "/" not supported for types "Literal[1]" and "Unknown | Expr | Basic | bool | Add | None"
+   .../projects/sympy/sympy/simplify/radsimp.py:999:36 - error: Operator "/" not supported for types "Literal[1]" and "Expr | Unknown | Basic | bool | Add | None"
-   .../projects/sympy/sympy/simplify/radsimp.py:1196:14 - error: Operator "*" not supported for types "Unknown | GaussianRational | MPQ | GaussianInteger | MPZ | Expr | Rational | NaN | ComplexInfinity | One | NegativeOne | Zero | Integer | Infinity | NegativeInfinity | Float | Number | Poly | Any" and "Unknown | GaussianRational | MPQ | GaussianInteger | MPZ | Expr | Rational | NaN | ComplexInfinity | One | NegativeOne | Zero | Integer | Infinity | NegativeInfinity | Float | Number | Poly | Any"
-     Operator "*" not supported for types "GaussianRational" and "MPQ"
-     Operator "*" not supported for types "GaussianRational" and "GaussianInteger"
-     Operator "*" not supported for types "GaussianRational" and "MPZ"
-     Operator "*" not supported for types "GaussianRational" and "Expr"
-     Operator "*" not supported for types "GaussianRational" and "Rational"
-     Operator "*" not supported for types "GaussianRational" and "NaN"
-     Operator "*" not supported for types "GaussianRational" and "ComplexInfinity"
-     Operator "*" not supported for types "GaussianRational" and "Infinity"
-     ... (reportOperatorIssue)
-   .../projects/sympy/sympy/simplify/simplify.py:163:20 - error: Argument of type "dict[str, Unknown] | dict[Unknown, list[Unknown]] | Unknown | None" cannot be assigned to parameter "b" of type "Expr | complex" in function "__new__"
+   .../projects/sympy/sympy/simplify/simplify.py:163:20 - error: Argument of type "dict[str, Unknown] | dict[Unknown, list[Unknown]] | Expr | Abs | Unknown | None" cannot be assigned to parameter "b" of type "Expr | complex" in function "__new__"
-     Type "dict[str, Unknown] | dict[Unknown, list[Unknown]] | Unknown | None" is not assignable to type "Expr | complex"
+     Type "dict[str, Unknown] | dict[Unknown, list[Unknown]] | Expr | Abs | Unknown | None" is not assignable to type "Expr | complex"
+   .../projects/sympy/sympy/simplify/sqrtdenest.py:157:19 - error: Operator "**" not supported for types "Basic" and "Literal[2]" (reportOperatorIssue)
+   .../projects/sympy/sympy/simplify/sqrtdenest.py:200:48 - error: Argument of type "Basic" cannot be assigned to parameter "args" of type "Expr | complex" in function "__new__"
+     Type "Basic" is not assignable to type "Expr | complex"
+       "Basic" is not assignable to "Expr"
+       "Basic" is not assignable to "complex" (reportArgumentType)
+   .../projects/sympy/sympy/simplify/sqrtdenest.py:207:26 - error: Operator "**" not supported for types "Unknown | Mul | Basic" and "Literal[2]"
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:309:10 - error: Operator "+" not supported for types "Expr" and "Unknown | Expr | Mul | None"
-     Operator "+" not supported for types "Expr" and "None" (reportOperatorIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:340:19 - error: Operator "-" not supported for types "Expr | Unknown | GaussianRational | One | NegativeOne | Zero | Integer | Any | MPQ | GaussianInteger | MPZ | Poly | NotImplementedType" and "Expr | Unknown | Any | GaussianRational | One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Infinity | NegativeInfinity | Float | NotImplementedType | MPQ | GaussianInteger | MPZ | Poly"
-     Operator "-" not supported for types "Expr" and "GaussianRational"
-     Operator "-" not supported for types "Expr" and "MPQ"
-     Operator "-" not supported for types "Expr" and "GaussianInteger"
-     Operator "-" not supported for types "Expr" and "MPZ"
-     Operator "-" not supported for types "GaussianRational" and "Expr"
-     Operator "-" not supported for types "GaussianRational" and "NaN"
-     Operator "-" not supported for types "GaussianRational" and "ComplexInfinity"
-     Operator "-" not supported for types "GaussianRational" and "Rational"
-     ... (reportOperatorIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:340:26 - error: Operator "*" not supported for types "Expr | Unknown | GaussianRational | One | NegativeOne | Zero | Integer | Any | MPQ | GaussianInteger | MPZ | Poly | NotImplementedType" and "Expr | Unknown | GaussianRational | One | NegativeOne | Zero | Integer | NaN | ComplexInfinity | Rational | Any | MPQ | GaussianInteger | MPZ | Infinity | NegativeInfinity | Float | NotImplementedType | Poly | Number"
-     Operator "*" not supported for types "Expr" and "GaussianRational"
-     Operator "*" not supported for types "Expr" and "MPQ"
-     Operator "*" not supported for types "Expr" and "GaussianInteger"
-     Operator "*" not supported for types "Expr" and "MPZ"
-     Operator "*" not supported for types "GaussianRational" and "Expr"
-     Operator "*" not supported for types "GaussianRational" and "NaN"
-     Operator "*" not supported for types "GaussianRational" and "ComplexInfinity"
-     Operator "*" not supported for types "GaussianRational" and "Rational"
-     ... (reportOperatorIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:341:11 - error: Cannot access attribute "is_Rational" for class "GaussianRational"
-     Attribute "is_Rational" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:341:11 - error: Cannot access attribute "is_Rational" for class "MPQ"
-     Attribute "is_Rational" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:341:11 - error: Cannot access attribute "is_Rational" for class "GaussianInteger"
-     Attribute "is_Rational" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:341:11 - error: Cannot access attribute "is_Rational" for class "MPZ"
-     Attribute "is_Rational" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:342:15 - error: Cannot access attribute "is_positive" for class "GaussianRational"
-     Attribute "is_positive" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:342:15 - error: Cannot access attribute "is_positive" for class "MPQ"
-     Attribute "is_positive" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:342:15 - error: Cannot access attribute "is_positive" for class "GaussianInteger"
-     Attribute "is_positive" is unknown (reportAttributeAccessIssue)
-   .../projects/sympy/sympy/simplify/sqrtdenest.py:342:15 - error: Cannot access attribute "is_positive" for class "MPZ"
-     Attribute "is_positive" is unknown (reportAttributeAccessIssue)

... (truncated 605 lines) ...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@rchiodo
Rich Chiodo (rchiodo) merged commit 69c1b12 into main Aug 11, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-auto:approved Automated review: no blocking findings (approval posted).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants