Optimize type equality fast paths - #11420
Conversation
This comment has been minimized.
This comment has been minimized.
Rich Chiodo (rchiodo)
left a comment
There was a problem hiding this comment.
Approved via Review Center.
|
/benchmark |
|
/benchmark |
|
Diff from mypy_primer, showing the effect of this PR on open source code: sympy (https://github.com/sympy/sympy)
- An internal error occurred while type checking file ".../projects/sympy/sympy/simplify/tests/test_powsimp.py": TypeError: Cannot read properties of undefined (reading 'isStubFile')
+ An internal error occurred while type checking file ".../projects/sympy/sympy/solvers/deutils.py": TypeError: Cannot read properties of undefined (reading 'isStubFile')
- at a7 (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22204:9)
+ at eR (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1025:9)
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:1560:33
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:315:33
- at W.visitImportFrom (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:1559:28)
+ at W.visitStatementList (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:310:27)
- at W.visit (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:188:29)
+ at W.visit (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:290:29)
- at W.walk (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:296:19)
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:685:22
- at Array.forEach (<anonymous>)
- at W.walkMultiple (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:683:15)
- at W.walk (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:678:18)
- at a7 (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22204:9)
+ at eR (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1025:9)
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:1560:33
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:315:33
- at W.visitImportFrom (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:1559:28)
+ at W.visitStatementList (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:310:27)
- at W.visit (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:188:29)
+ at W.visit (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:290:29)
- at W.walk (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:296:19)
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:685:22
- at Array.forEach (<anonymous>)
- at W.walkMultiple (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:683:15)
- at W.walk (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:678:18)
core (https://github.com/home-assistant/core)
- An internal error occurred while type checking file ".../projects/core/homeassistant/components/ovhcloud_ai_endpoints/__init__.py": TypeError: Cannot read properties of undefined (reading 'diagnosticRuleSet')
+ An internal error occurred while type checking file ".../projects/core/homeassistant/components/websocket_api/auth.py": Error: Debug Failure. Did not find evaluation scope
+ at w (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeUtils.ts:1035:5)
+ at Object.t.getExecutionScopeNode (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeUtils.ts:1079:27)
+ at nt (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22416:46)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5231:44
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5312:5
+ at eB (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1617:5)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5987:32
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:6095:5
+ at eB (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1617:5)
+ at A (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/codeFlowEngine.ts:1784:46)
+ at t (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/codeFlowEngine.ts:517:29)
+ at Object.getTypeFromCodeFlow (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/codeFlowEngine.ts:941:13)
+ at nt (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22453:25)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5231:44
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5312:5
+ at eB (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1617:5)
+ at nI (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24342:44)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24797:32
+ at Array.forEach (<anonymous>)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24793:15
+ at nA (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24784:5)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5173:39
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5312:5
+ at eB (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1617:5)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:8911:31
+ at s (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:8926:5)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:8791:32
+ at Array.forEach (<anonymous>)
+ at tK (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:8790:22)
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:8218:46
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:8221:36
- at nS (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24527:16)
- at no (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:23174:24)
- at nl (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:23182:26)
- at aI (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:16909:22)
- at eW (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:2006:23)
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1831:32
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5173:39
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5312:5
+ at eB (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1617:5)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:7406:32
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:7502:5
+ at eB (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1617:5)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:18779:35
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:18763:30
+ at t.invalidateTypeCacheIfCanceled (...pyright_to_test/packages/pyright/dist/pyright-internal/src/common/cancellationUtils.ts:38:16)
+ at az (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:18731:16)
+ at n_ (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:23918:39)
+ at nI (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24310:30)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24797:32
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24793:15
+ at nA (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24784:5)
+ Error performing analysis: Error: Debug Failure. Did not find evaluation scope
+ at w (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeUtils.ts:1035:5)
+ at Object.t.getExecutionScopeNode (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeUtils.ts:1079:27)
+ at nt (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22416:46)
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1829:24
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5231:44
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1929:5
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5312:5
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5987:32
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:6095:5
- at aD (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:18379:35)
+ at eB (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1617:5)
- at a7 (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22220:25)
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24390:17
- at a9 (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22358:9)
- at a8 (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22327:16)
- at nI (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24389:32)
- at a5 (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:21792:16)
- at a1 (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:21492:26)
- at a7 (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22300:21)
+ at A (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/codeFlowEngine.ts:1784:46)
+ at t (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/codeFlowEngine.ts:517:29)
+ at Object.getTypeFromCodeFlow (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/codeFlowEngine.ts:941:13)
+ at nt (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:22453:25)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5231:44
- at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:1560:33
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5312:5
+ at eB (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:1617:5)
+ at nI (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24342:44)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24797:32
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24793:15
- at W.visitImportFrom (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/checker.ts:1559:28)
+ at nA (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:24784:5)
- at W.visit (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:188:29)
+ at ...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/typeEvaluator.ts:5173:39
- at W.visitNode (...pyright_to_test/packages/pyright/dist/pyright-internal/src/analyzer/parseTreeWalker.ts:694:21)
... (truncated 86 lines) ...
|
|
🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR. |
| assert.strictEqual(isTypeSame(clone1, distinctConstraints), false); | ||
| }); | ||
|
|
||
| function createClassType(name: string, flags = ClassTypeFlags.None) { |
There was a problem hiding this comment.
Warning · Non-blocking recommendation
Add cases for shared tuple arguments, overload arrays, and specialized function parameter metadata, plus structurally equal non-shared fallbacks. Include a function case with differing specialized return types to demonstrate that the parameter shortcut still reaches return-type comparison.
[verified]
|
Verification: The relevant tests could not be fully run in the isolated environment; this review is not fully verified. |
|
/benchmark |
|
Verification: The relevant tests could not be fully run in the isolated environment; this review is not fully verified. |
|
/benchmark |
|
/benchmark |
|
Recovered results from benchmark run 32891326101: Type checker benchmark🟢 No performance regressions detected. Regression threshold:
Pyright stats
Automatic chart posting is fixed by #11680. |
|
/benchmark |
Type checker benchmark🟢 No performance regressions detected. Regression threshold:
Pyright stats
|
Summary
This optimizes
isTypeSameby avoiding recursive comparisons when two types share the same immutable backing structures. The fast paths cover shared class type arguments, shared function parameter metadata, shared overload arrays, shared union subtype arrays, and shared TypeVar bound/constraint structures.Details
The change keeps the existing structural comparison behavior for non-shared data, but skips recursive walks when reference identity proves the relevant backing structure is identical. This commonly applies to shallow-cloned or decorated types.
Validation
npm run test:norebuild -- --runTestsByPath src/tests/typeEquality.test.ts --forceExitnpm run buildPerformance Notes
On a local full-project NumPy CPU profile,
isTypeSameself time dropped from about21.98sto19.02s(-13.5%) after these fast paths. A sampled heap profile did not show the edited helper functions as allocation sites. Whole-program wall-clock timing remains noisy, so this PR is presented as a targeted hotspot reduction rather than a claimed end-to-end throughput win.