@zzzen/pyright-internal 1.2.0-dev.20261101 → 1.2.0-dev.20261108

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/dist/analyzer/binder.js +9 -3
  2. package/dist/analyzer/binder.js.map +1 -1
  3. package/dist/analyzer/constructorTransform.js +12 -0
  4. package/dist/analyzer/constructorTransform.js.map +1 -1
  5. package/dist/analyzer/constructors.d.ts +1 -1
  6. package/dist/analyzer/constructors.js +1 -1
  7. package/dist/analyzer/constructors.js.map +1 -1
  8. package/dist/analyzer/decorators.d.ts +1 -1
  9. package/dist/analyzer/decorators.js.map +1 -1
  10. package/dist/analyzer/functionTransform.d.ts +5 -0
  11. package/dist/analyzer/functionTransform.js +6 -3
  12. package/dist/analyzer/functionTransform.js.map +1 -1
  13. package/dist/analyzer/missingBindingMetadata.d.ts +6 -0
  14. package/dist/analyzer/missingBindingMetadata.js +22 -0
  15. package/dist/analyzer/missingBindingMetadata.js.map +1 -0
  16. package/dist/analyzer/namedTuples.d.ts +4 -1
  17. package/dist/analyzer/namedTuples.js +1 -0
  18. package/dist/analyzer/namedTuples.js.map +1 -1
  19. package/dist/analyzer/patternMatching.d.ts +5 -1
  20. package/dist/analyzer/patternMatching.js +3 -0
  21. package/dist/analyzer/patternMatching.js.map +1 -1
  22. package/dist/analyzer/program.d.ts +3 -0
  23. package/dist/analyzer/program.js +71 -1
  24. package/dist/analyzer/program.js.map +1 -1
  25. package/dist/analyzer/tuples.d.ts +1 -1
  26. package/dist/analyzer/tuples.js.map +1 -1
  27. package/dist/analyzer/typeCacheUtils.d.ts +1 -0
  28. package/dist/analyzer/typeCacheUtils.js +10 -0
  29. package/dist/analyzer/typeCacheUtils.js.map +1 -1
  30. package/dist/analyzer/typeEvaluator/boundMethodSpecialization.d.ts +15 -0
  31. package/dist/analyzer/typeEvaluator/boundMethodSpecialization.js +98 -0
  32. package/dist/analyzer/typeEvaluator/boundMethodSpecialization.js.map +1 -0
  33. package/dist/analyzer/typeEvaluator/classConstruction.d.ts +25 -0
  34. package/dist/analyzer/typeEvaluator/classConstruction.js +251 -0
  35. package/dist/analyzer/typeEvaluator/classConstruction.js.map +1 -0
  36. package/dist/analyzer/typeEvaluator/collectionInference.d.ts +41 -0
  37. package/dist/analyzer/typeEvaluator/collectionInference.js +695 -0
  38. package/dist/analyzer/typeEvaluator/collectionInference.js.map +1 -0
  39. package/dist/analyzer/typeEvaluator/diagnostics.d.ts +33 -0
  40. package/dist/analyzer/typeEvaluator/diagnostics.js +198 -0
  41. package/dist/analyzer/typeEvaluator/diagnostics.js.map +1 -0
  42. package/dist/analyzer/typeEvaluator/evaluatorCore.d.ts +80 -0
  43. package/dist/analyzer/typeEvaluator/evaluatorCore.js +1126 -0
  44. package/dist/analyzer/typeEvaluator/evaluatorCore.js.map +1 -0
  45. package/dist/analyzer/typeEvaluator/evaluatorNarrowing.d.ts +17 -0
  46. package/dist/analyzer/typeEvaluator/evaluatorNarrowing.js +370 -0
  47. package/dist/analyzer/typeEvaluator/evaluatorNarrowing.js.map +1 -0
  48. package/dist/analyzer/typeEvaluator/expressionEvaluation.d.ts +81 -0
  49. package/dist/analyzer/typeEvaluator/expressionEvaluation.js +1802 -0
  50. package/dist/analyzer/typeEvaluator/expressionEvaluation.js.map +1 -0
  51. package/dist/analyzer/typeEvaluator/flowAnalysis.d.ts +33 -0
  52. package/dist/analyzer/typeEvaluator/flowAnalysis.js +217 -0
  53. package/dist/analyzer/typeEvaluator/flowAnalysis.js.map +1 -0
  54. package/dist/analyzer/typeEvaluator/internals.d.ts +137 -0
  55. package/dist/analyzer/typeEvaluator/internals.js +10 -0
  56. package/dist/analyzer/typeEvaluator/internals.js.map +1 -0
  57. package/dist/analyzer/typeEvaluator/literalTypes.d.ts +3 -0
  58. package/dist/analyzer/typeEvaluator/literalTypes.js +52 -0
  59. package/dist/analyzer/typeEvaluator/literalTypes.js.map +1 -0
  60. package/dist/analyzer/typeEvaluator/memberResolution.d.ts +79 -0
  61. package/dist/analyzer/typeEvaluator/memberResolution.js +1007 -0
  62. package/dist/analyzer/typeEvaluator/memberResolution.js.map +1 -0
  63. package/dist/analyzer/typeEvaluator/overrideValidation.d.ts +15 -0
  64. package/dist/analyzer/typeEvaluator/overrideValidation.js +422 -0
  65. package/dist/analyzer/typeEvaluator/overrideValidation.js.map +1 -0
  66. package/dist/analyzer/typeEvaluator/returnTypeInference.d.ts +33 -0
  67. package/dist/analyzer/typeEvaluator/returnTypeInference.js +226 -0
  68. package/dist/analyzer/typeEvaluator/returnTypeInference.js.map +1 -0
  69. package/dist/analyzer/typeEvaluator/specialFormCreation.d.ts +39 -0
  70. package/dist/analyzer/typeEvaluator/specialFormCreation.js +1728 -0
  71. package/dist/analyzer/typeEvaluator/specialFormCreation.js.map +1 -0
  72. package/dist/analyzer/typeEvaluator/tupleUnpacking.d.ts +2 -0
  73. package/dist/analyzer/typeEvaluator/tupleUnpacking.js +36 -0
  74. package/dist/analyzer/typeEvaluator/tupleUnpacking.js.map +1 -0
  75. package/dist/analyzer/typeEvaluator/typeCompatibility.d.ts +36 -0
  76. package/dist/analyzer/typeEvaluator/typeCompatibility.js +1320 -0
  77. package/dist/analyzer/typeEvaluator/typeCompatibility.js.map +1 -0
  78. package/dist/analyzer/typeEvaluator/typeGuardNarrowing.d.ts +186 -0
  79. package/dist/analyzer/typeEvaluator/typeGuardNarrowing.js +1683 -0
  80. package/dist/analyzer/typeEvaluator/typeGuardNarrowing.js.map +1 -0
  81. package/dist/analyzer/typeEvaluator/typeVarHandling.d.ts +48 -0
  82. package/dist/analyzer/typeEvaluator/typeVarHandling.js +756 -0
  83. package/dist/analyzer/typeEvaluator/typeVarHandling.js.map +1 -0
  84. package/dist/analyzer/typeEvaluator.d.ts +3 -31
  85. package/dist/analyzer/typeEvaluator.js +5033 -13761
  86. package/dist/analyzer/typeEvaluator.js.map +1 -1
  87. package/dist/analyzer/typeGuards.d.ts +2 -2
  88. package/dist/analyzer/typeGuards.js +212 -1567
  89. package/dist/analyzer/typeGuards.js.map +1 -1
  90. package/dist/analyzer/typeUtils.js +6 -2
  91. package/dist/analyzer/typeUtils.js.map +1 -1
  92. package/dist/analyzer/typedDicts.js +111 -0
  93. package/dist/analyzer/typedDicts.js.map +1 -1
  94. package/dist/browser/browserConnection.d.ts +12 -0
  95. package/dist/browser/browserConnection.js +23 -0
  96. package/dist/browser/browserConnection.js.map +1 -0
  97. package/dist/browser/browserFileSystem.d.ts +73 -0
  98. package/dist/browser/browserFileSystem.js +578 -0
  99. package/dist/browser/browserFileSystem.js.map +1 -0
  100. package/dist/browser/browserHost.d.ts +4 -0
  101. package/dist/browser/browserHost.js +10 -0
  102. package/dist/browser/browserHost.js.map +1 -0
  103. package/dist/browser/browserProcess.d.ts +1 -0
  104. package/dist/browser/browserProcess.js +17 -0
  105. package/dist/browser/browserProcess.js.map +1 -0
  106. package/dist/browser/browserServer.d.ts +8 -0
  107. package/dist/browser/browserServer.js +32 -0
  108. package/dist/browser/browserServer.js.map +1 -0
  109. package/dist/browser/cancellation/common.d.ts +10 -0
  110. package/dist/browser/cancellation/common.js +114 -0
  111. package/dist/browser/cancellation/common.js.map +1 -0
  112. package/dist/browser/cancellation/objectURLReceiverStrategy.d.ts +5 -0
  113. package/dist/browser/cancellation/objectURLReceiverStrategy.js +37 -0
  114. package/dist/browser/cancellation/objectURLReceiverStrategy.js.map +1 -0
  115. package/dist/browser/cancellation/objectURLSenderStrategy.d.ts +7 -0
  116. package/dist/browser/cancellation/objectURLSenderStrategy.js +32 -0
  117. package/dist/browser/cancellation/objectURLSenderStrategy.js.map +1 -0
  118. package/dist/browser/worker.d.ts +1 -0
  119. package/dist/browser/worker.js +33 -0
  120. package/dist/browser/worker.js.map +1 -0
  121. package/dist/pyrightServer.d.ts +34 -0
  122. package/dist/pyrightServer.js +239 -0
  123. package/dist/pyrightServer.js.map +1 -0
  124. package/dist/server.d.ts +3 -23
  125. package/dist/server.js +12 -232
  126. package/dist/server.js.map +1 -1
  127. package/dist/tests/benchmarks/typeInferenceComparison.d.ts +1 -0
  128. package/dist/tests/benchmarks/typeInferenceComparison.js +1235 -0
  129. package/dist/tests/benchmarks/typeInferenceComparison.js.map +1 -0
  130. package/dist/tests/benchmarks/typeInferencePyrightEntry.d.ts +1 -0
  131. package/dist/tests/benchmarks/typeInferencePyrightEntry.js +53 -0
  132. package/dist/tests/benchmarks/typeInferencePyrightEntry.js.map +1 -0
  133. package/dist/tests/browserCancellation.test.d.ts +1 -0
  134. package/dist/tests/browserCancellation.test.js +63 -0
  135. package/dist/tests/browserCancellation.test.js.map +1 -0
  136. package/dist/tests/browserServer.test.d.ts +1 -0
  137. package/dist/tests/browserServer.test.js +177 -0
  138. package/dist/tests/browserServer.test.js.map +1 -0
  139. package/dist/tests/constraintSolver.test.js +45 -0
  140. package/dist/tests/constraintSolver.test.js.map +1 -1
  141. package/dist/tests/mypyPrimerAnalysis.test.js +15 -1
  142. package/dist/tests/mypyPrimerAnalysis.test.js.map +1 -1
  143. package/dist/tests/typeCacheUtils.test.js +46 -0
  144. package/dist/tests/typeCacheUtils.test.js.map +1 -1
  145. package/dist/tests/typeEvaluator1.test.js +75 -0
  146. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  147. package/dist/tests/typeEvaluator3.test.js +4 -0
  148. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  149. package/dist/tests/typeEvaluator4.test.js +32 -0
  150. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  151. package/dist/tests/typeEvaluator7.test.js +394 -0
  152. package/dist/tests/typeEvaluator7.test.js.map +1 -1
  153. package/dist/tests/typeUtils.test.js +28 -0
  154. package/dist/tests/typeUtils.test.js.map +1 -1
  155. package/dist/typeServer/stubGenerator.js +136 -3
  156. package/dist/typeServer/stubGenerator.js.map +1 -1
  157. package/dist/typeServer/typeServerConversionUtils.js +13 -0
  158. package/dist/typeServer/typeServerConversionUtils.js.map +1 -1
  159. package/package.json +3 -1
@@ -0,0 +1,1683 @@
1
+ "use strict";
2
+ /*
3
+ * typeGuardNarrowing.ts
4
+ * Copyright (c) Microsoft Corporation.
5
+ * Licensed under the MIT license.
6
+ *
7
+ * Helper logic shared by type narrowing entry points.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.getNoneEllipsisNarrowingInfo = getNoneEllipsisNarrowingInfo;
11
+ exports.getTypeIsCallNarrowingInfo = getTypeIsCallNarrowingInfo;
12
+ exports.getIsLiteralOrClassNarrowingInfo = getIsLiteralOrClassNarrowingInfo;
13
+ exports.getIndexedLiteralNarrowingInfo = getIndexedLiteralNarrowingInfo;
14
+ exports.getIsInstanceCallNarrowingInfo = getIsInstanceCallNarrowingInfo;
15
+ exports.getBoolCallNarrowingInfo = getBoolCallNarrowingInfo;
16
+ exports.getNotExpressionNarrowingInfo = getNotExpressionNarrowingInfo;
17
+ exports.getEqualsNarrowingInfo = getEqualsNarrowingInfo;
18
+ exports.getMemberAccessNarrowingInfo = getMemberAccessNarrowingInfo;
19
+ exports.getLenComparisonNarrowingInfo = getLenComparisonNarrowingInfo;
20
+ exports.getInOperatorNarrowingInfo = getInOperatorNarrowingInfo;
21
+ exports.narrowTypeForTruthiness = narrowTypeForTruthiness;
22
+ exports.narrowTupleTypeForIsNone = narrowTupleTypeForIsNone;
23
+ exports.narrowTypeForIsNone = narrowTypeForIsNone;
24
+ exports.narrowTypeForIsEllipsis = narrowTypeForIsEllipsis;
25
+ exports.getIsInstanceClassTypes = getIsInstanceClassTypes;
26
+ exports.narrowTypeForInstanceOrSubclass = narrowTypeForInstanceOrSubclass;
27
+ exports.narrowTypeForTupleLength = narrowTypeForTupleLength;
28
+ exports.narrowTypeForContainerType = narrowTypeForContainerType;
29
+ exports.getElementTypeForContainerNarrowing = getElementTypeForContainerNarrowing;
30
+ exports.narrowTypeForContainerElementType = narrowTypeForContainerElementType;
31
+ exports.narrowTypeForTypedDictKey = narrowTypeForTypedDictKey;
32
+ exports.narrowTypeForDiscriminatedDictEntryComparison = narrowTypeForDiscriminatedDictEntryComparison;
33
+ exports.narrowTypeForDiscriminatedTupleComparison = narrowTypeForDiscriminatedTupleComparison;
34
+ exports.narrowTypeForDiscriminatedLiteralFieldComparison = narrowTypeForDiscriminatedLiteralFieldComparison;
35
+ exports.narrowTypeForDiscriminatedFieldNoneComparison = narrowTypeForDiscriminatedFieldNoneComparison;
36
+ exports.narrowTypeForTypeIs = narrowTypeForTypeIs;
37
+ exports.narrowTypeForClassComparison = narrowTypeForClassComparison;
38
+ exports.narrowTypeForLiteralComparison = narrowTypeForLiteralComparison;
39
+ exports.enumerateLiteralsForType = enumerateLiteralsForType;
40
+ exports.isNameSameScope = isNameSameScope;
41
+ exports.narrowTypeForUserDefinedTypeGuard = narrowTypeForUserDefinedTypeGuard;
42
+ const debug_1 = require("../../common/debug");
43
+ const analyzerNodeInfo_1 = require("../analyzerNodeInfo");
44
+ const constraintTracker_1 = require("../constraintTracker");
45
+ const enums_1 = require("../enums");
46
+ const operations_1 = require("../operations");
47
+ const scopeUtils_1 = require("../scopeUtils");
48
+ const typedDicts_1 = require("../typedDicts");
49
+ const types_1 = require("../types");
50
+ const typeUtils_1 = require("../typeUtils");
51
+ function getNoneEllipsisNarrowingInfo(ctx, reference, testExpression, isPositiveTest) {
52
+ if (testExpression.nodeType !== 7 /* ParseNodeType.BinaryOperation */) {
53
+ return undefined;
54
+ }
55
+ const isOrIsNotOperator = testExpression.d.operator === 39 /* OperatorType.Is */ || testExpression.d.operator === 40 /* OperatorType.IsNot */;
56
+ const equalsOrNotEqualsOperator = testExpression.d.operator === 12 /* OperatorType.Equals */ || testExpression.d.operator === 28 /* OperatorType.NotEquals */;
57
+ if (!isOrIsNotOperator && !equalsOrNotEqualsOperator) {
58
+ return undefined;
59
+ }
60
+ const adjIsPositiveTest = testExpression.d.operator === 39 /* OperatorType.Is */ || testExpression.d.operator === 12 /* OperatorType.Equals */
61
+ ? isPositiveTest
62
+ : !isPositiveTest;
63
+ if (testExpression.d.rightExpr.nodeType === 14 /* ParseNodeType.Constant */ &&
64
+ testExpression.d.rightExpr.d.constType === 27 /* KeywordType.None */) {
65
+ if (ctx.isMatchingExpressionOrWalrusRhs(reference, testExpression.d.leftExpr)) {
66
+ return { kind: 'none', adjIsPositiveTest };
67
+ }
68
+ const leftExpression = testExpression.d.leftExpr;
69
+ if (leftExpression.nodeType === 27 /* ParseNodeType.Index */ &&
70
+ ctx.isMatchingExpression(reference, leftExpression.d.leftExpr) &&
71
+ leftExpression.d.items.length === 1 &&
72
+ !leftExpression.d.trailingComma &&
73
+ leftExpression.d.items[0].d.argCategory === 0 /* ArgCategory.Simple */ &&
74
+ !leftExpression.d.items[0].d.name &&
75
+ leftExpression.d.items[0].d.valueExpr.nodeType === 40 /* ParseNodeType.Number */ &&
76
+ leftExpression.d.items[0].d.valueExpr.d.isInteger &&
77
+ !leftExpression.d.items[0].d.valueExpr.d.isImaginary) {
78
+ const indexValue = leftExpression.d.items[0].d.valueExpr.d.value;
79
+ if (typeof indexValue === 'number') {
80
+ return { kind: 'tuple-none', adjIsPositiveTest, tupleIndex: indexValue };
81
+ }
82
+ }
83
+ }
84
+ if (testExpression.d.rightExpr.nodeType === 21 /* ParseNodeType.Ellipsis */ &&
85
+ ctx.isMatchingExpressionOrWalrusRhs(reference, testExpression.d.leftExpr)) {
86
+ return { kind: 'ellipsis', adjIsPositiveTest };
87
+ }
88
+ return undefined;
89
+ }
90
+ function isTypeCallBase(callType) {
91
+ return (0, types_1.isInstantiableClass)(callType) && types_1.ClassType.isBuiltIn(callType, 'type');
92
+ }
93
+ function getTypeIsCallNarrowingInfo(ctx, reference, testExpression, isPositiveTest) {
94
+ if (testExpression.nodeType !== 7 /* ParseNodeType.BinaryOperation */) {
95
+ return undefined;
96
+ }
97
+ const isOrIsNotOperator = testExpression.d.operator === 39 /* OperatorType.Is */ || testExpression.d.operator === 40 /* OperatorType.IsNot */;
98
+ const equalsOrNotEqualsOperator = testExpression.d.operator === 12 /* OperatorType.Equals */ || testExpression.d.operator === 28 /* OperatorType.NotEquals */;
99
+ if (!isOrIsNotOperator && !equalsOrNotEqualsOperator) {
100
+ return undefined;
101
+ }
102
+ const adjIsPositiveTest = testExpression.d.operator === 39 /* OperatorType.Is */ || testExpression.d.operator === 12 /* OperatorType.Equals */
103
+ ? isPositiveTest
104
+ : !isPositiveTest;
105
+ let typeCallNode;
106
+ let otherExpr;
107
+ const isTypeCall = (expr, referenceExpr) => expr.nodeType === 9 /* ParseNodeType.Call */ &&
108
+ expr.d.args.length === 1 &&
109
+ expr.d.args[0].d.argCategory === 0 /* ArgCategory.Simple */ &&
110
+ (!referenceExpr || ctx.isMatchingExpressionOrWalrusRhs(referenceExpr, expr.d.args[0].d.valueExpr)) &&
111
+ isTypeCallBase(ctx.getTypeOfExpression(expr.d.leftExpr, 2 /* EvalFlags.CallBaseDefaults */).type);
112
+ if (isTypeCall(testExpression.d.leftExpr, reference)) {
113
+ typeCallNode = testExpression.d.leftExpr;
114
+ otherExpr = testExpression.d.rightExpr;
115
+ }
116
+ else if (isTypeCall(testExpression.d.rightExpr, reference)) {
117
+ typeCallNode = testExpression.d.rightExpr;
118
+ otherExpr = testExpression.d.leftExpr;
119
+ }
120
+ if (!typeCallNode || !otherExpr) {
121
+ return undefined;
122
+ }
123
+ const otherResult = ctx.getTypeOfExpression(otherExpr);
124
+ const classTypes = [];
125
+ let isClassType = true;
126
+ let classTypeVar;
127
+ if ((0, types_1.isTypeVar)(otherResult.type) && types_1.TypeBase.isInstantiable(otherResult.type)) {
128
+ classTypeVar = (0, typeUtils_1.convertToInstance)(otherResult.type);
129
+ }
130
+ else if ((0, types_1.isClassInstance)(otherResult.type) &&
131
+ types_1.ClassType.isBuiltIn(otherResult.type, 'type') &&
132
+ otherResult.type.priv.typeArgs?.length === 1 &&
133
+ (0, types_1.isTypeVar)(otherResult.type.priv.typeArgs[0])) {
134
+ classTypeVar = otherResult.type.priv.typeArgs[0];
135
+ }
136
+ ctx.mapSubtypesExpandTypeVars(otherResult.type, (expandedSubtype) => {
137
+ let instantiable;
138
+ if ((0, types_1.isClass)(expandedSubtype)) {
139
+ if ((0, types_1.isClassInstance)(expandedSubtype) &&
140
+ types_1.ClassType.isBuiltIn(expandedSubtype, 'type') &&
141
+ expandedSubtype.priv.typeArgs &&
142
+ expandedSubtype.priv.typeArgs.length > 0) {
143
+ const extracted = expandedSubtype.priv.typeArgs[0];
144
+ if ((0, types_1.isInstantiableClass)(extracted)) {
145
+ instantiable = extracted;
146
+ }
147
+ }
148
+ else if ((0, types_1.isInstantiableClass)(expandedSubtype)) {
149
+ instantiable = expandedSubtype;
150
+ }
151
+ }
152
+ if (instantiable) {
153
+ classTypes.push(instantiable);
154
+ }
155
+ else {
156
+ isClassType = false;
157
+ }
158
+ return undefined;
159
+ });
160
+ if (!isClassType || classTypes.length === 0) {
161
+ return undefined;
162
+ }
163
+ const allowLegacyEquality = !isOrIsNotOperator &&
164
+ typeCallNode === testExpression.d.leftExpr &&
165
+ (((0, types_1.isInstantiableClass)(otherResult.type) &&
166
+ !otherResult.type.priv.includeSubclasses &&
167
+ !otherResult.type.priv.isTypeArgExplicit) ||
168
+ isTypeCall(otherExpr));
169
+ return {
170
+ classTypes,
171
+ classTypeVar,
172
+ adjIsPositiveTest,
173
+ isOrIsNotOperator,
174
+ allowLegacyEquality,
175
+ isIncomplete: !!otherResult.isIncomplete,
176
+ };
177
+ }
178
+ function getIsLiteralOrClassNarrowingInfo(ctx, reference, testExpression, isPositiveTest) {
179
+ if (testExpression.nodeType !== 7 /* ParseNodeType.BinaryOperation */) {
180
+ return undefined;
181
+ }
182
+ if (testExpression.d.operator !== 39 /* OperatorType.Is */ && testExpression.d.operator !== 40 /* OperatorType.IsNot */) {
183
+ return undefined;
184
+ }
185
+ if (!ctx.isMatchingExpressionOrWalrusRhs(reference, testExpression.d.leftExpr)) {
186
+ return undefined;
187
+ }
188
+ const adjIsPositiveTest = testExpression.d.operator === 39 /* OperatorType.Is */ ? isPositiveTest : !isPositiveTest;
189
+ const rightTypeResult = ctx.getTypeOfExpression(testExpression.d.rightExpr);
190
+ const rightType = rightTypeResult.type;
191
+ if ((0, types_1.isClassInstance)(rightType) && rightType.priv.literalValue !== undefined) {
192
+ return {
193
+ kind: 'literal',
194
+ rightType,
195
+ adjIsPositiveTest,
196
+ isIncomplete: !!rightTypeResult.isIncomplete,
197
+ };
198
+ }
199
+ if ((0, types_1.isInstantiableClass)(rightType)) {
200
+ return {
201
+ kind: 'class',
202
+ rightType,
203
+ adjIsPositiveTest,
204
+ isIncomplete: !!rightTypeResult.isIncomplete,
205
+ };
206
+ }
207
+ return undefined;
208
+ }
209
+ function getIndexedLiteralNarrowingInfo(ctx, reference, testExpression, isPositiveTest) {
210
+ if (testExpression.nodeType !== 7 /* ParseNodeType.BinaryOperation */) {
211
+ return undefined;
212
+ }
213
+ if (testExpression.d.operator !== 39 /* OperatorType.Is */ && testExpression.d.operator !== 40 /* OperatorType.IsNot */) {
214
+ return undefined;
215
+ }
216
+ if (testExpression.d.leftExpr.nodeType !== 27 /* ParseNodeType.Index */ ||
217
+ testExpression.d.leftExpr.d.items.length !== 1 ||
218
+ testExpression.d.leftExpr.d.trailingComma ||
219
+ testExpression.d.leftExpr.d.items[0].d.argCategory !== 0 /* ArgCategory.Simple */ ||
220
+ !ctx.isMatchingExpression(reference, testExpression.d.leftExpr.d.leftExpr)) {
221
+ return undefined;
222
+ }
223
+ const indexTypeResult = ctx.getTypeOfExpression(testExpression.d.leftExpr.d.items[0].d.valueExpr);
224
+ const indexType = indexTypeResult.type;
225
+ if (!(0, types_1.isClassInstance)(indexType) || !(0, typeUtils_1.isLiteralType)(indexType)) {
226
+ return undefined;
227
+ }
228
+ const rightTypeResult = ctx.getTypeOfExpression(testExpression.d.rightExpr);
229
+ const rightType = rightTypeResult.type;
230
+ if (!(0, types_1.isClassInstance)(rightType) || rightType.priv.literalValue === undefined) {
231
+ return undefined;
232
+ }
233
+ const adjIsPositiveTest = testExpression.d.operator === 39 /* OperatorType.Is */ ? isPositiveTest : !isPositiveTest;
234
+ if (types_1.ClassType.isBuiltIn(indexType, 'str')) {
235
+ return {
236
+ kind: 'dict',
237
+ indexType,
238
+ rightType,
239
+ adjIsPositiveTest,
240
+ isIncomplete: !!indexTypeResult.isIncomplete,
241
+ };
242
+ }
243
+ if (types_1.ClassType.isBuiltIn(indexType, 'int')) {
244
+ let canNarrow = false;
245
+ if (types_1.ClassType.isBuiltIn(rightType, 'bool')) {
246
+ canNarrow = true;
247
+ }
248
+ else if (rightType.priv.literalValue instanceof types_1.EnumLiteral) {
249
+ canNarrow = true;
250
+ }
251
+ if (canNarrow) {
252
+ return {
253
+ kind: 'tuple',
254
+ indexType,
255
+ rightType,
256
+ adjIsPositiveTest,
257
+ isIncomplete: !!rightTypeResult.isIncomplete,
258
+ };
259
+ }
260
+ }
261
+ return undefined;
262
+ }
263
+ function getIsInstanceCallNarrowingInfo(ctx, reference, testExpression, isPositiveTest) {
264
+ if (testExpression.nodeType !== 9 /* ParseNodeType.Call */ || testExpression.d.args.length !== 2) {
265
+ return undefined;
266
+ }
267
+ const arg0Expr = testExpression.d.args[0].d.valueExpr;
268
+ const arg1Expr = testExpression.d.args[1].d.valueExpr;
269
+ if (!ctx.isMatchingExpressionOrWalrusRhs(reference, arg0Expr)) {
270
+ return undefined;
271
+ }
272
+ const callTypeResult = ctx.getTypeOfExpression(testExpression.d.leftExpr, 2 /* EvalFlags.CallBaseDefaults */);
273
+ const callType = callTypeResult.type;
274
+ if (!(0, types_1.isFunction)(callType) || !types_1.FunctionType.isBuiltIn(callType, ['isinstance', 'issubclass'])) {
275
+ return undefined;
276
+ }
277
+ const isInstanceCheck = types_1.FunctionType.isBuiltIn(callType, 'isinstance');
278
+ const arg1TypeResult = ctx.getTypeOfExpression(arg1Expr, 536871546 /* EvalFlags.IsInstanceArgDefaults */);
279
+ const classTypeInfo = ctx.getIsInstanceClassTypes(arg1TypeResult.type, arg1Expr);
280
+ const isIncomplete = !!callTypeResult.isIncomplete || !!arg1TypeResult.isIncomplete;
281
+ if (classTypeInfo) {
282
+ return {
283
+ kind: 'narrow',
284
+ classTypeList: isPositiveTest ? classTypeInfo.classTypes : classTypeInfo.negativeClassTypes,
285
+ isInstanceCheck,
286
+ isIncomplete,
287
+ };
288
+ }
289
+ if (isIncomplete) {
290
+ return { kind: 'incomplete', isIncomplete: true };
291
+ }
292
+ return undefined;
293
+ }
294
+ function getBoolCallNarrowingInfo(ctx, reference, testExpression) {
295
+ if (testExpression.nodeType !== 9 /* ParseNodeType.Call */ ||
296
+ testExpression.d.args.length !== 1 ||
297
+ testExpression.d.args[0].d.name) {
298
+ return undefined;
299
+ }
300
+ if (!ctx.isMatchingExpressionOrWalrusRhs(reference, testExpression.d.args[0].d.valueExpr)) {
301
+ return undefined;
302
+ }
303
+ const callTypeResult = ctx.getTypeOfExpression(testExpression.d.leftExpr, 2 /* EvalFlags.CallBaseDefaults */);
304
+ const callType = callTypeResult.type;
305
+ if ((0, types_1.isInstantiableClass)(callType) && types_1.ClassType.isBuiltIn(callType, 'bool')) {
306
+ return { isIncomplete: !!callTypeResult.isIncomplete };
307
+ }
308
+ return undefined;
309
+ }
310
+ function getNotExpressionNarrowingInfo(reference, testExpression, isPositiveTest) {
311
+ if (testExpression.nodeType === 55 /* ParseNodeType.UnaryOperation */ &&
312
+ testExpression.d.operator === 38 /* OperatorType.Not */ &&
313
+ reference !== testExpression) {
314
+ return {
315
+ innerExpression: testExpression.d.expr,
316
+ adjIsPositiveTest: !isPositiveTest,
317
+ };
318
+ }
319
+ return undefined;
320
+ }
321
+ function getEqualsNarrowingInfo(ctx, reference, testExpression, isPositiveTest) {
322
+ if (testExpression.nodeType !== 7 /* ParseNodeType.BinaryOperation */) {
323
+ return undefined;
324
+ }
325
+ const equalsOrNotEqualsOperator = testExpression.d.operator === 12 /* OperatorType.Equals */ || testExpression.d.operator === 28 /* OperatorType.NotEquals */;
326
+ if (!equalsOrNotEqualsOperator) {
327
+ return undefined;
328
+ }
329
+ const adjIsPositiveTest = testExpression.d.operator === 12 /* OperatorType.Equals */ ? isPositiveTest : !isPositiveTest;
330
+ if (ctx.isMatchingExpressionOrWalrusRhs(reference, testExpression.d.leftExpr)) {
331
+ const rightTypeResult = ctx.getTypeOfExpression(testExpression.d.rightExpr);
332
+ const rightType = rightTypeResult.type;
333
+ if ((0, types_1.isClassInstance)(rightType) && rightType.priv.literalValue !== undefined) {
334
+ return {
335
+ kind: 'literal',
336
+ rightType,
337
+ adjIsPositiveTest,
338
+ isIncomplete: !!rightTypeResult.isIncomplete,
339
+ };
340
+ }
341
+ if ((0, types_1.isInstantiableClass)(rightType)) {
342
+ return {
343
+ kind: 'class',
344
+ rightType,
345
+ adjIsPositiveTest,
346
+ isIncomplete: !!rightTypeResult.isIncomplete,
347
+ };
348
+ }
349
+ }
350
+ if (testExpression.d.leftExpr.nodeType === 27 /* ParseNodeType.Index */ &&
351
+ testExpression.d.leftExpr.d.items.length === 1 &&
352
+ !testExpression.d.leftExpr.d.trailingComma &&
353
+ testExpression.d.leftExpr.d.items[0].d.argCategory === 0 /* ArgCategory.Simple */ &&
354
+ ctx.isMatchingExpression(reference, testExpression.d.leftExpr.d.leftExpr)) {
355
+ const indexTypeResult = ctx.getTypeOfExpression(testExpression.d.leftExpr.d.items[0].d.valueExpr);
356
+ const indexType = indexTypeResult.type;
357
+ if ((0, types_1.isClassInstance)(indexType) && (0, typeUtils_1.isLiteralType)(indexType) && types_1.ClassType.isBuiltIn(indexType, ['str', 'int'])) {
358
+ const rightTypeResult = ctx.getTypeOfExpression(testExpression.d.rightExpr);
359
+ const rightType = rightTypeResult.type;
360
+ if ((0, typeUtils_1.isLiteralTypeOrUnion)(rightType)) {
361
+ return {
362
+ kind: 'index',
363
+ indexType,
364
+ rightType,
365
+ adjIsPositiveTest,
366
+ isIncomplete: !!indexTypeResult.isIncomplete || !!rightTypeResult.isIncomplete,
367
+ };
368
+ }
369
+ }
370
+ }
371
+ return undefined;
372
+ }
373
+ function getMemberAccessNarrowingInfo(ctx, reference, testExpression, isPositiveTest) {
374
+ if (testExpression.nodeType !== 7 /* ParseNodeType.BinaryOperation */) {
375
+ return undefined;
376
+ }
377
+ const isOrIsNotOperator = testExpression.d.operator === 39 /* OperatorType.Is */ || testExpression.d.operator === 40 /* OperatorType.IsNot */;
378
+ const equalsOrNotEqualsOperator = testExpression.d.operator === 12 /* OperatorType.Equals */ || testExpression.d.operator === 28 /* OperatorType.NotEquals */;
379
+ if (!isOrIsNotOperator && !equalsOrNotEqualsOperator) {
380
+ return undefined;
381
+ }
382
+ if (testExpression.d.leftExpr.nodeType !== 35 /* ParseNodeType.MemberAccess */ ||
383
+ !ctx.isMatchingExpression(reference, testExpression.d.leftExpr.d.leftExpr)) {
384
+ return undefined;
385
+ }
386
+ const adjIsPositiveTest = testExpression.d.operator === 39 /* OperatorType.Is */ || testExpression.d.operator === 12 /* OperatorType.Equals */
387
+ ? isPositiveTest
388
+ : !isPositiveTest;
389
+ if (isOrIsNotOperator &&
390
+ testExpression.d.rightExpr.nodeType === 14 /* ParseNodeType.Constant */ &&
391
+ testExpression.d.rightExpr.d.constType === 27 /* KeywordType.None */) {
392
+ return {
393
+ kind: 'none',
394
+ memberName: testExpression.d.leftExpr.d.member.d.value,
395
+ adjIsPositiveTest,
396
+ isIncomplete: false,
397
+ };
398
+ }
399
+ const rightTypeResult = ctx.getTypeOfExpression(testExpression.d.rightExpr);
400
+ const rightType = rightTypeResult.type;
401
+ if ((0, types_1.isClassInstance)(rightType)) {
402
+ const isLiteralEqualsCase = equalsOrNotEqualsOperator && (rightType.priv.literalValue !== undefined || (0, typeUtils_1.isNoneInstance)(rightType));
403
+ const isLiteralIdentityCase = isOrIsNotOperator &&
404
+ (types_1.ClassType.isEnumClass(rightType) || types_1.ClassType.isBuiltIn(rightType, 'bool')) &&
405
+ rightType.priv.literalValue !== undefined;
406
+ if (isLiteralEqualsCase || isLiteralIdentityCase) {
407
+ return {
408
+ kind: 'literal',
409
+ memberName: testExpression.d.leftExpr.d.member.d.value,
410
+ rightType,
411
+ adjIsPositiveTest,
412
+ isIncomplete: !!rightTypeResult.isIncomplete,
413
+ };
414
+ }
415
+ }
416
+ return undefined;
417
+ }
418
+ function getLenComparisonNarrowingInfo(ctx, reference, testExpression, isPositiveTest) {
419
+ if (testExpression.nodeType !== 7 /* ParseNodeType.BinaryOperation */) {
420
+ return undefined;
421
+ }
422
+ const comparisonOperator = testExpression.d.operator === 12 /* OperatorType.Equals */ ||
423
+ testExpression.d.operator === 28 /* OperatorType.NotEquals */ ||
424
+ testExpression.d.operator === 20 /* OperatorType.LessThan */ ||
425
+ testExpression.d.operator === 21 /* OperatorType.LessThanOrEqual */ ||
426
+ testExpression.d.operator === 15 /* OperatorType.GreaterThan */ ||
427
+ testExpression.d.operator === 16 /* OperatorType.GreaterThanOrEqual */;
428
+ if (!comparisonOperator ||
429
+ testExpression.d.leftExpr.nodeType !== 9 /* ParseNodeType.Call */ ||
430
+ testExpression.d.leftExpr.d.args.length !== 1) {
431
+ return undefined;
432
+ }
433
+ const arg0Expr = testExpression.d.leftExpr.d.args[0].d.valueExpr;
434
+ if (!ctx.isMatchingExpression(reference, arg0Expr)) {
435
+ return undefined;
436
+ }
437
+ const callTypeResult = ctx.getTypeOfExpression(testExpression.d.leftExpr.d.leftExpr, 2 /* EvalFlags.CallBaseDefaults */);
438
+ const callType = callTypeResult.type;
439
+ if (!(0, types_1.isFunction)(callType) || callType.shared.fullName !== 'builtins.len') {
440
+ return undefined;
441
+ }
442
+ const rightTypeResult = ctx.getTypeOfExpression(testExpression.d.rightExpr);
443
+ const rightType = rightTypeResult.type;
444
+ if (!(0, types_1.isClassInstance)(rightType) ||
445
+ typeof rightType.priv.literalValue !== 'number' ||
446
+ rightType.priv.literalValue < 0) {
447
+ return undefined;
448
+ }
449
+ let tupleLength = rightType.priv.literalValue;
450
+ const isLessOrEqual = testExpression.d.operator === 12 /* OperatorType.Equals */ ||
451
+ testExpression.d.operator === 20 /* OperatorType.LessThan */ ||
452
+ testExpression.d.operator === 21 /* OperatorType.LessThanOrEqual */;
453
+ const adjIsPositiveTest = isLessOrEqual ? isPositiveTest : !isPositiveTest;
454
+ if (testExpression.d.operator === 21 /* OperatorType.LessThanOrEqual */ ||
455
+ testExpression.d.operator === 15 /* OperatorType.GreaterThan */) {
456
+ tupleLength++;
457
+ }
458
+ const isEqualityCheck = testExpression.d.operator === 12 /* OperatorType.Equals */ || testExpression.d.operator === 28 /* OperatorType.NotEquals */;
459
+ return {
460
+ tupleLength,
461
+ adjIsPositiveTest,
462
+ isLessThanCheck: !isEqualityCheck,
463
+ isIncomplete: !!callTypeResult.isIncomplete || !!rightTypeResult.isIncomplete,
464
+ };
465
+ }
466
+ function getInOperatorNarrowingInfo(ctx, reference, testExpression, isPositiveTest) {
467
+ if (testExpression.nodeType !== 7 /* ParseNodeType.BinaryOperation */ ||
468
+ (testExpression.d.operator !== 41 /* OperatorType.In */ && testExpression.d.operator !== 42 /* OperatorType.NotIn */)) {
469
+ return undefined;
470
+ }
471
+ const adjIsPositiveTest = testExpression.d.operator === 41 /* OperatorType.In */ ? isPositiveTest : !isPositiveTest;
472
+ if (ctx.isMatchingExpressionOrWalrusRhs(reference, testExpression.d.leftExpr)) {
473
+ const rightTypeResult = ctx.getTypeOfExpression(testExpression.d.rightExpr);
474
+ return {
475
+ kind: 'container',
476
+ containerType: rightTypeResult.type,
477
+ adjIsPositiveTest,
478
+ isIncomplete: !!rightTypeResult.isIncomplete,
479
+ };
480
+ }
481
+ if (ctx.isMatchingExpression(reference, testExpression.d.rightExpr)) {
482
+ const leftTypeResult = ctx.getTypeOfExpression(testExpression.d.leftExpr);
483
+ const leftType = leftTypeResult.type;
484
+ if ((0, types_1.isClassInstance)(leftType) && types_1.ClassType.isBuiltIn(leftType, 'str') && (0, typeUtils_1.isLiteralType)(leftType)) {
485
+ return {
486
+ kind: 'typedDictKey',
487
+ typedDictKeyType: types_1.ClassType.cloneAsInstantiable(leftType),
488
+ adjIsPositiveTest,
489
+ isIncomplete: !!leftTypeResult.isIncomplete,
490
+ };
491
+ }
492
+ }
493
+ return undefined;
494
+ return undefined;
495
+ }
496
+ function narrowTypeForTruthiness(evaluator, type, isPositiveTest) {
497
+ return (0, typeUtils_1.mapSubtypes)(type, (subtype) => {
498
+ if (isPositiveTest) {
499
+ if (evaluator.canBeTruthy(subtype)) {
500
+ return evaluator.removeFalsinessFromType(subtype);
501
+ }
502
+ }
503
+ else {
504
+ if (evaluator.canBeFalsy(subtype)) {
505
+ return evaluator.removeTruthinessFromType(subtype);
506
+ }
507
+ }
508
+ return undefined;
509
+ });
510
+ }
511
+ function narrowTupleTypeForIsNone(evaluator, type, isPositiveTest, indexValue) {
512
+ return evaluator.mapSubtypesExpandTypeVars(type, /* options */ undefined, (subtype) => {
513
+ const tupleType = (0, typeUtils_1.getSpecializedTupleType)(subtype);
514
+ if (!tupleType || (0, typeUtils_1.isUnboundedTupleClass)(tupleType) || !tupleType.priv.tupleTypeArgs) {
515
+ return subtype;
516
+ }
517
+ const tupleLength = tupleType.priv.tupleTypeArgs.length;
518
+ if (indexValue < 0 || indexValue >= tupleLength) {
519
+ return subtype;
520
+ }
521
+ const typeOfEntry = evaluator.makeTopLevelTypeVarsConcrete(tupleType.priv.tupleTypeArgs[indexValue].type);
522
+ if (isPositiveTest) {
523
+ if (!evaluator.assignType(typeOfEntry, evaluator.getNoneType())) {
524
+ return undefined;
525
+ }
526
+ }
527
+ else {
528
+ if ((0, typeUtils_1.isNoneInstance)(typeOfEntry)) {
529
+ return undefined;
530
+ }
531
+ }
532
+ return subtype;
533
+ });
534
+ }
535
+ function narrowTypeForIsNone(evaluator, type, isPositiveTest) {
536
+ const expandedType = (0, typeUtils_1.mapSubtypes)(type, (subtype) => {
537
+ return (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(subtype);
538
+ });
539
+ let resultIncludesNoneSubtype = false;
540
+ const result = evaluator.mapSubtypesExpandTypeVars(expandedType,
541
+ /* options */ undefined, (subtype, unexpandedSubtype) => {
542
+ if ((0, types_1.isAnyOrUnknown)(subtype)) {
543
+ if (isPositiveTest) {
544
+ resultIncludesNoneSubtype = true;
545
+ return (0, typeUtils_1.addConditionToType)(evaluator.getNoneType(), subtype.props?.condition);
546
+ }
547
+ return subtype;
548
+ }
549
+ let useExpandedSubtype = false;
550
+ if ((0, types_1.isTypeVar)(unexpandedSubtype) && !types_1.TypeVarType.isSelf(unexpandedSubtype)) {
551
+ if (unexpandedSubtype.shared.constraints.some((constraint) => {
552
+ return evaluator.assignType(constraint, evaluator.getNoneType());
553
+ })) {
554
+ useExpandedSubtype = true;
555
+ }
556
+ if (unexpandedSubtype.shared.boundType &&
557
+ evaluator.assignType(unexpandedSubtype.shared.boundType, evaluator.getNoneType())) {
558
+ useExpandedSubtype = true;
559
+ }
560
+ }
561
+ const adjustedSubtype = useExpandedSubtype ? subtype : unexpandedSubtype;
562
+ const newTypeBaseInstance = getInnermostNewTypeBaseInstance(adjustedSubtype);
563
+ if (newTypeBaseInstance && (0, typeUtils_1.isNoneInstance)(newTypeBaseInstance)) {
564
+ resultIncludesNoneSubtype = true;
565
+ return isPositiveTest ? adjustedSubtype : undefined;
566
+ }
567
+ if ((0, typeUtils_1.isNoneInstance)(subtype)) {
568
+ resultIncludesNoneSubtype = true;
569
+ return isPositiveTest ? adjustedSubtype : undefined;
570
+ }
571
+ if (evaluator.assignType(subtype, evaluator.getNoneType())) {
572
+ resultIncludesNoneSubtype = true;
573
+ return isPositiveTest
574
+ ? (0, typeUtils_1.addConditionToType)(evaluator.getNoneType(), subtype.props?.condition)
575
+ : adjustedSubtype;
576
+ }
577
+ return isPositiveTest ? undefined : adjustedSubtype;
578
+ });
579
+ if (isPositiveTest && resultIncludesNoneSubtype) {
580
+ return (0, typeUtils_1.mapSubtypes)(result, (subtype) => {
581
+ const baseInstance = getInnermostNewTypeBaseInstance(subtype);
582
+ return (0, typeUtils_1.isNoneInstance)(subtype) || (baseInstance && (0, typeUtils_1.isNoneInstance)(baseInstance)) ? subtype : undefined;
583
+ });
584
+ }
585
+ return result;
586
+ }
587
+ function narrowTypeForIsEllipsis(evaluator, node, type, isPositiveTest) {
588
+ const expandedType = (0, typeUtils_1.mapSubtypes)(type, (subtype) => {
589
+ return (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(subtype);
590
+ });
591
+ let resultIncludesEllipsisSubtype = false;
592
+ const ellipsisType = evaluator.getBuiltInObject(node, 'EllipsisType') ??
593
+ evaluator.getBuiltInObject(node, 'ellipsis') ??
594
+ types_1.AnyType.create();
595
+ const isEllipsisInstance = (subtype) => {
596
+ return (0, types_1.isClassInstance)(subtype) && types_1.ClassType.isBuiltIn(subtype, ['EllipsisType', 'ellipsis']);
597
+ };
598
+ const result = evaluator.mapSubtypesExpandTypeVars(expandedType,
599
+ /* options */ undefined, (subtype, unexpandedSubtype) => {
600
+ if ((0, types_1.isAnyOrUnknown)(subtype)) {
601
+ return subtype;
602
+ }
603
+ const adjustedSubtype = (0, types_1.isTypeVar)(unexpandedSubtype) && !types_1.TypeVarType.hasConstraints(unexpandedSubtype)
604
+ ? unexpandedSubtype
605
+ : subtype;
606
+ const newTypeBaseInstance = getInnermostNewTypeBaseInstance(adjustedSubtype);
607
+ if (newTypeBaseInstance && isEllipsisInstance(newTypeBaseInstance)) {
608
+ resultIncludesEllipsisSubtype = true;
609
+ return isPositiveTest ? adjustedSubtype : undefined;
610
+ }
611
+ if (isEllipsisInstance(subtype)) {
612
+ resultIncludesEllipsisSubtype = true;
613
+ return isPositiveTest ? adjustedSubtype : undefined;
614
+ }
615
+ if (evaluator.assignType(subtype, ellipsisType)) {
616
+ resultIncludesEllipsisSubtype = true;
617
+ return isPositiveTest ? (0, typeUtils_1.addConditionToType)(ellipsisType, subtype.props?.condition) : adjustedSubtype;
618
+ }
619
+ return isPositiveTest ? undefined : adjustedSubtype;
620
+ });
621
+ if (isPositiveTest && resultIncludesEllipsisSubtype) {
622
+ return (0, typeUtils_1.mapSubtypes)(result, (subtype) => {
623
+ const baseInstance = getInnermostNewTypeBaseInstance(subtype);
624
+ return isEllipsisInstance(subtype) || (baseInstance && isEllipsisInstance(baseInstance))
625
+ ? subtype
626
+ : undefined;
627
+ });
628
+ }
629
+ return result;
630
+ }
631
+ function getIsInstanceClassTypes(evaluator, argType, argExpr) {
632
+ let foundNonClassType = false;
633
+ const classTypes = [];
634
+ const negativeClassTypes = [];
635
+ // Create a helper function that returns a list of class types or
636
+ // undefined if any of the types are not valid.
637
+ const addClassTypesToList = (types, isAmbiguous, isUnboundedEntry) => {
638
+ types.forEach((subtype) => {
639
+ if ((0, types_1.isClass)(subtype)) {
640
+ subtype = (0, typeUtils_1.specializeWithUnknownTypeArgs)(subtype, evaluator.getTupleClassType());
641
+ if ((0, types_1.isInstantiableClass)(subtype) && types_1.ClassType.isBuiltIn(subtype, 'Callable')) {
642
+ subtype = (0, typeUtils_1.convertToInstantiable)((0, typeUtils_1.getUnknownTypeForCallable)());
643
+ }
644
+ else if (types_1.TypeBase.isInstance(subtype) && types_1.ClassType.isBuiltIn(subtype, 'type')) {
645
+ if (subtype.priv.typeArgs && subtype.priv.typeArgs.length > 0) {
646
+ const typeArg = subtype.priv.typeArgs[0];
647
+ if ((0, types_1.isAnyOrUnknown)(typeArg)) {
648
+ foundNonClassType = true;
649
+ return;
650
+ }
651
+ if ((0, types_1.isInstantiableClass)(typeArg)) {
652
+ subtype = types_1.ClassType.cloneIncludeSubclasses(typeArg);
653
+ }
654
+ else if ((0, types_1.isClassInstance)(typeArg)) {
655
+ subtype = types_1.ClassType.cloneAsInstantiable(typeArg);
656
+ }
657
+ }
658
+ }
659
+ }
660
+ let classType;
661
+ if ((0, types_1.isInstantiableClass)(subtype)) {
662
+ // If this is a reference to a class that has type promotions (e.g.
663
+ // float or complex), remove the promotions for purposes of the
664
+ // isinstance check).
665
+ if (!subtype.priv.includeSubclasses && subtype.priv.includePromotions) {
666
+ subtype = types_1.ClassType.cloneRemoveTypePromotions(subtype);
667
+ }
668
+ classType = subtype;
669
+ }
670
+ else if ((0, types_1.isTypeVar)(subtype) && types_1.TypeBase.isInstantiable(subtype)) {
671
+ classType = subtype;
672
+ }
673
+ else if ((0, typeUtils_1.isNoneTypeClass)(subtype)) {
674
+ (0, debug_1.assert)((0, types_1.isInstantiableClass)(subtype));
675
+ classType = subtype;
676
+ }
677
+ else if ((0, types_1.isFunction)(subtype) &&
678
+ subtype.shared.parameters.length === 2 &&
679
+ subtype.shared.parameters[0].category === 1 /* ParamCategory.ArgsList */ &&
680
+ subtype.shared.parameters[1].category === 2 /* ParamCategory.KwargsDict */) {
681
+ classType = subtype;
682
+ }
683
+ else {
684
+ foundNonClassType = true;
685
+ return;
686
+ }
687
+ classTypes.push(classType);
688
+ // Unbounded entries may be absent, and alternative class objects
689
+ // are not all guaranteed to participate in the runtime check.
690
+ if (!isUnboundedEntry && !isAmbiguous) {
691
+ negativeClassTypes.push(classType);
692
+ }
693
+ });
694
+ };
695
+ const addClassTypesRecursive = (type, isAmbiguous, isUnboundedEntry, recursionCount, expression) => {
696
+ if (recursionCount > types_1.maxTypeRecursionCount) {
697
+ return;
698
+ }
699
+ // A runtime union checks both operands, but either operand can itself
700
+ // be an alternative class object. Keep their certainty separate.
701
+ if ((0, types_1.isUnion)(type) &&
702
+ expression?.nodeType === 7 /* ParseNodeType.BinaryOperation */ &&
703
+ expression.d.operator === 6 /* OperatorType.BitwiseOr */) {
704
+ const leftType = evaluator.getCachedType(expression.d.leftExpr);
705
+ const rightType = evaluator.getCachedType(expression.d.rightExpr);
706
+ if (leftType &&
707
+ rightType &&
708
+ !(0, operations_1.customMetaclassSupportsMethod)(leftType, '__or__') &&
709
+ !(0, operations_1.customMetaclassSupportsMethod)(rightType, '__ror__')) {
710
+ // Match the union evaluator's normalization of None operands to NoneType.
711
+ const adjustedLeftType = (0, typeUtils_1.isNoneInstance)(leftType)
712
+ ? (0, typeUtils_1.convertToInstantiable)(evaluator.getNoneType())
713
+ : leftType;
714
+ const adjustedRightType = (0, typeUtils_1.isNoneInstance)(rightType)
715
+ ? (0, typeUtils_1.convertToInstantiable)(evaluator.getNoneType())
716
+ : rightType;
717
+ addClassTypesRecursive(adjustedLeftType, isAmbiguous, isUnboundedEntry, recursionCount, expression.d.leftExpr);
718
+ addClassTypesRecursive(adjustedRightType, isAmbiguous, isUnboundedEntry, recursionCount, expression.d.rightExpr);
719
+ return;
720
+ }
721
+ }
722
+ const isRuntimeUnion = type.props?.specialForm && types_1.ClassType.isBuiltIn(type.props.specialForm, 'UnionType');
723
+ const isAmbiguousType = isAmbiguous || ((0, types_1.isUnion)(type) && !isRuntimeUnion);
724
+ (0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
725
+ if ((0, types_1.isClassInstance)(subtype) && (0, typeUtils_1.isTupleClass)(subtype)) {
726
+ if (subtype.priv.tupleTypeArgs) {
727
+ let entryExpressions;
728
+ if (expression?.nodeType === 52 /* ParseNodeType.Tuple */) {
729
+ const expressions = [];
730
+ expression.d.items.forEach((item) => {
731
+ if (item.nodeType !== 56 /* ParseNodeType.Unpack */) {
732
+ expressions.push(item);
733
+ return;
734
+ }
735
+ const unpackedType = evaluator.getCachedType(item.d.expr);
736
+ const entryCount = unpackedType && (0, types_1.isClassInstance)(unpackedType) && (0, typeUtils_1.isTupleClass)(unpackedType)
737
+ ? unpackedType.priv.tupleTypeArgs?.length ?? 1
738
+ : 1;
739
+ for (let index = 0; index < entryCount; index++) {
740
+ expressions.push(undefined);
741
+ }
742
+ });
743
+ if (expressions.length === subtype.priv.tupleTypeArgs.length) {
744
+ entryExpressions = expressions;
745
+ }
746
+ }
747
+ subtype.priv.tupleTypeArgs.forEach((tupleEntry, index) => {
748
+ addClassTypesRecursive(tupleEntry.type, isAmbiguousType, isUnboundedEntry || tupleEntry.isUnbounded, recursionCount + 1, entryExpressions?.[index]);
749
+ });
750
+ }
751
+ }
752
+ else {
753
+ addClassTypesToList([subtype], isAmbiguousType, isUnboundedEntry);
754
+ }
755
+ });
756
+ };
757
+ addClassTypesRecursive(argType, /* isAmbiguous */ false, /* isUnboundedEntry */ false, 0, argExpr);
758
+ return foundNonClassType ? undefined : { classTypes, negativeClassTypes };
759
+ }
760
+ function narrowTypeForInstanceOrSubclass(evaluator, type, filterTypes, isInstanceCheck, isTypeIsCheck, isPositiveTest, errorNode, nodeInfo, narrowTypeForInstanceOrSubclassInternalCallback) {
761
+ if (!isInstanceCheck && !isTypeIsCheck && !isPositiveTest) {
762
+ filterTypes = filterTypes.filter((filterType) => {
763
+ const concreteFilterType = evaluator.makeTopLevelTypeVarsConcrete(filterType);
764
+ return (!(0, types_1.isInstantiableClass)(concreteFilterType) ||
765
+ !types_1.ClassType.isFinal(concreteFilterType) ||
766
+ !(0, operations_1.customMetaclassSupportsMethod)(concreteFilterType, '__subclasscheck__'));
767
+ });
768
+ }
769
+ if (!isPositiveTest && filterTypes.length === 0) {
770
+ return type;
771
+ }
772
+ const narrowedType = narrowTypeForInstanceOrSubclassInternalCallback(evaluator, type, filterTypes, isInstanceCheck, isTypeIsCheck, isPositiveTest,
773
+ /* allowIntersections */ false, errorNode, nodeInfo);
774
+ if (!(0, types_1.isNever)(narrowedType)) {
775
+ return narrowedType;
776
+ }
777
+ return narrowTypeForInstanceOrSubclassInternalCallback(evaluator, type, filterTypes, isInstanceCheck, isTypeIsCheck, isPositiveTest,
778
+ /* allowIntersections */ true, errorNode, nodeInfo);
779
+ }
780
+ function narrowTypeForTupleLength(evaluator, referenceType, lengthValue, isPositiveTest, isLessThanCheck) {
781
+ return (0, typeUtils_1.mapSubtypes)(referenceType, (subtype) => {
782
+ const concreteSubtype = evaluator.makeTopLevelTypeVarsConcrete(subtype);
783
+ // If it's not a tuple, we can't narrow it.
784
+ if (!(0, types_1.isClassInstance)(concreteSubtype) ||
785
+ !(0, typeUtils_1.isTupleClass)(concreteSubtype) ||
786
+ !concreteSubtype.priv.tupleTypeArgs) {
787
+ return subtype;
788
+ }
789
+ // If the tuple contains a TypeVarTuple, we can't narrow it.
790
+ if (concreteSubtype.priv.tupleTypeArgs.some((typeArg) => (0, types_1.isUnpackedTypeVarTuple)(typeArg.type))) {
791
+ return subtype;
792
+ }
793
+ // If the tuple contains no unbounded elements, then we know its length exactly.
794
+ if (!concreteSubtype.priv.tupleTypeArgs.some((typeArg) => typeArg.isUnbounded)) {
795
+ const tupleLengthMatches = isLessThanCheck
796
+ ? concreteSubtype.priv.tupleTypeArgs.length < lengthValue
797
+ : concreteSubtype.priv.tupleTypeArgs.length === lengthValue;
798
+ return tupleLengthMatches === isPositiveTest ? subtype : undefined;
799
+ }
800
+ // The tuple contains a "...". We'll expand this into as many elements as
801
+ // necessary to match the lengthValue.
802
+ const elementsToAdd = lengthValue - concreteSubtype.priv.tupleTypeArgs.length + 1;
803
+ if (!isLessThanCheck) {
804
+ // If the specified length is smaller than the minimum length of this tuple,
805
+ // we can rule it out for a positive test and rule it in for a negative test.
806
+ if (elementsToAdd < 0) {
807
+ return isPositiveTest ? undefined : subtype;
808
+ }
809
+ if (!isPositiveTest) {
810
+ // If this is an equality check for the minimum length (e.g.
811
+ // "len(x) == 0"), we can expand the minimum length by one).
812
+ const minLen = concreteSubtype.priv.tupleTypeArgs.length - 1;
813
+ if (lengthValue === minLen) {
814
+ return expandUnboundedTupleElement(concreteSubtype, 1, /* keepUnbounded */ true);
815
+ }
816
+ return subtype;
817
+ }
818
+ return expandUnboundedTupleElement(concreteSubtype, elementsToAdd, /* keepUnbounded */ false);
819
+ }
820
+ // If this is a tuple related to an "*args: P.args" parameter, don't expand it.
821
+ if ((0, types_1.isParamSpec)(subtype) && subtype.priv.paramSpecAccess) {
822
+ return subtype;
823
+ }
824
+ // Place an upper limit on the number of union subtypes we
825
+ // will expand the tuple to.
826
+ const maxTupleUnionExpansion = 32;
827
+ if (elementsToAdd > maxTupleUnionExpansion) {
828
+ return subtype;
829
+ }
830
+ if (isPositiveTest) {
831
+ if (elementsToAdd < 1) {
832
+ return undefined;
833
+ }
834
+ const typesToCombine = [];
835
+ for (let i = 0; i < elementsToAdd; i++) {
836
+ typesToCombine.push(expandUnboundedTupleElement(concreteSubtype, i, /* keepUnbounded */ false));
837
+ }
838
+ return (0, types_1.combineTypes)(typesToCombine);
839
+ }
840
+ return expandUnboundedTupleElement(concreteSubtype, elementsToAdd, /* keepUnbounded */ true);
841
+ });
842
+ }
843
+ function expandUnboundedTupleElement(tupleType, elementsToAdd, keepUnbounded) {
844
+ const tupleTypeArgs = [];
845
+ tupleType.priv.tupleTypeArgs.forEach((typeArg) => {
846
+ if (!typeArg.isUnbounded) {
847
+ tupleTypeArgs.push(typeArg);
848
+ }
849
+ else {
850
+ for (let i = 0; i < elementsToAdd; i++) {
851
+ tupleTypeArgs.push({ isUnbounded: false, type: typeArg.type });
852
+ }
853
+ if (keepUnbounded) {
854
+ tupleTypeArgs.push(typeArg);
855
+ }
856
+ }
857
+ });
858
+ return (0, typeUtils_1.specializeTupleClass)(tupleType, tupleTypeArgs);
859
+ }
860
+ function narrowTypeForContainerType(evaluator, referenceType, containerType, isPositiveTest) {
861
+ if (isPositiveTest) {
862
+ const elementType = getElementTypeForContainerNarrowing(containerType);
863
+ if (!elementType) {
864
+ return referenceType;
865
+ }
866
+ return narrowTypeForContainerElementType(evaluator, referenceType, evaluator.makeTopLevelTypeVarsConcrete(elementType));
867
+ }
868
+ // Narrowing in the negative case is possible only with tuples
869
+ // with a known length.
870
+ if (!(0, types_1.isClassInstance)(containerType) ||
871
+ !types_1.ClassType.isBuiltIn(containerType, 'tuple') ||
872
+ !containerType.priv.tupleTypeArgs) {
873
+ return referenceType;
874
+ }
875
+ // Determine which tuple types can be eliminated. Only "None",
876
+ // literal types, and final instantiable classes can be handled here.
877
+ // Non-final instantiable classes (type[A]) cannot be eliminated in negative
878
+ // tests because a subclass SubA(A) reaches the negative branch at runtime
879
+ // (since SubA != A). Generic classes are also excluded because a
880
+ // specialized class object like Box[int] is not the same runtime object
881
+ // as Box. Classes that define or inherit __class_getitem__ are excluded
882
+ // for the same reason.
883
+ const typesToEliminate = [];
884
+ containerType.priv.tupleTypeArgs.forEach((tupleEntry) => {
885
+ if (!tupleEntry.isUnbounded) {
886
+ if ((0, typeUtils_1.isNoneInstance)(tupleEntry.type)) {
887
+ typesToEliminate.push(tupleEntry.type);
888
+ }
889
+ else if ((0, types_1.isClassInstance)(tupleEntry.type) && (0, typeUtils_1.isLiteralType)(tupleEntry.type)) {
890
+ typesToEliminate.push(tupleEntry.type);
891
+ }
892
+ else if ((0, types_1.isInstantiableClass)(tupleEntry.type) &&
893
+ types_1.ClassType.isFinal(tupleEntry.type) &&
894
+ tupleEntry.type.shared.typeParams.length === 0 &&
895
+ !(0, typeUtils_1.lookUpClassMember)(tupleEntry.type, '__class_getitem__')) {
896
+ typesToEliminate.push(tupleEntry.type);
897
+ }
898
+ }
899
+ });
900
+ if (typesToEliminate.length === 0) {
901
+ return referenceType;
902
+ }
903
+ const canNarrowLiterals = typesToEliminate.some(types_1.isClassInstance);
904
+ return (0, typeUtils_1.mapSubtypes)(referenceType, (unexpandedSubtype) => {
905
+ const referenceSubtype = evaluator.makeTopLevelTypeVarsConcrete(unexpandedSubtype);
906
+ if (canNarrowLiterals &&
907
+ (0, types_1.isClassInstance)(referenceSubtype) &&
908
+ referenceSubtype.priv.literalValue === undefined) {
909
+ // If we're able to enumerate all possible literal values
910
+ // (for bool or enum), we can eliminate all others in a negative test.
911
+ const allLiteralTypes = enumerateLiteralsForType(evaluator, referenceSubtype);
912
+ if (allLiteralTypes && allLiteralTypes.length > 0) {
913
+ return (0, types_1.combineTypes)(allLiteralTypes.filter((type) => !typesToEliminate.some((t) => (0, types_1.isTypeSame)(t, type))));
914
+ }
915
+ }
916
+ if (typesToEliminate.some((t) => (0, types_1.isTypeSame)(t, referenceSubtype))) {
917
+ return undefined;
918
+ }
919
+ return unexpandedSubtype;
920
+ });
921
+ }
922
+ function getElementTypeForContainerNarrowing(containerType) {
923
+ // We support contains narrowing only for certain built-in types that have been specialized.
924
+ const supportedContainers = ['list', 'set', 'frozenset', 'deque', 'tuple', 'dict', 'defaultdict', 'OrderedDict'];
925
+ if (!(0, types_1.isClassInstance)(containerType) || !types_1.ClassType.isBuiltIn(containerType, supportedContainers)) {
926
+ return undefined;
927
+ }
928
+ if (!containerType.priv.typeArgs || containerType.priv.typeArgs.length < 1) {
929
+ return undefined;
930
+ }
931
+ let elementType = containerType.priv.typeArgs[0];
932
+ if ((0, typeUtils_1.isTupleClass)(containerType) && containerType.priv.tupleTypeArgs) {
933
+ elementType = (0, types_1.combineTypes)(containerType.priv.tupleTypeArgs.map((t) => t.type));
934
+ }
935
+ return elementType;
936
+ }
937
+ function narrowTypeForContainerElementType(evaluator, referenceType, elementType) {
938
+ return evaluator.mapSubtypesExpandTypeVars(referenceType, /* options */ undefined, (referenceSubtype) => {
939
+ return (0, typeUtils_1.mapSubtypes)(elementType, (elementSubtype) => {
940
+ if ((0, types_1.isAnyOrUnknown)(elementSubtype)) {
941
+ return referenceSubtype;
942
+ }
943
+ // If the two types are disjoint (i.e. are not comparable), eliminate this subtype.
944
+ if (!evaluator.isTypeComparable(elementSubtype, referenceSubtype)) {
945
+ return undefined;
946
+ }
947
+ // If one of the two types is a literal, we can narrow to that type.
948
+ if ((0, types_1.isClassInstance)(elementSubtype) &&
949
+ ((0, typeUtils_1.isLiteralLikeType)(elementSubtype) || (0, typeUtils_1.isNoneInstance)(elementSubtype)) &&
950
+ evaluator.assignType(referenceSubtype, elementSubtype)) {
951
+ return (0, typeUtils_1.stripTypeForm)((0, typeUtils_1.addConditionToType)(elementSubtype, referenceSubtype.props?.condition));
952
+ }
953
+ if ((0, types_1.isClassInstance)(referenceSubtype) &&
954
+ ((0, typeUtils_1.isLiteralLikeType)(referenceSubtype) || (0, typeUtils_1.isNoneInstance)(referenceSubtype)) &&
955
+ evaluator.assignType(elementSubtype, referenceSubtype)) {
956
+ return (0, typeUtils_1.stripTypeForm)((0, typeUtils_1.addConditionToType)(referenceSubtype, elementSubtype.props?.condition));
957
+ }
958
+ // If the element type is a known class object that is assignable to
959
+ // the reference type, we can narrow to that class object.
960
+ if ((0, types_1.isInstantiableClass)(elementSubtype) &&
961
+ !elementSubtype.priv.includeSubclasses &&
962
+ evaluator.assignType(referenceSubtype, elementSubtype)) {
963
+ return (0, typeUtils_1.stripTypeForm)((0, typeUtils_1.addConditionToType)(elementSubtype, referenceSubtype.props?.condition));
964
+ }
965
+ // It's not safe to narrow.
966
+ return referenceSubtype;
967
+ });
968
+ });
969
+ }
970
+ function narrowTypeForTypedDictKey(evaluator, referenceType, literalKey, isPositiveTest) {
971
+ const narrowedType = evaluator.mapSubtypesExpandTypeVars(referenceType,
972
+ /* options */ undefined, (subtype, unexpandedSubtype) => {
973
+ if ((0, types_1.isParamSpec)(unexpandedSubtype)) {
974
+ return unexpandedSubtype;
975
+ }
976
+ if ((0, types_1.isClassInstance)(subtype) && types_1.ClassType.isTypedDictClass(subtype)) {
977
+ const entries = (0, typedDicts_1.getTypedDictMembersForClass)(evaluator, subtype, /* allowNarrowed */ true);
978
+ const knownEntry = entries.knownItems.get(literalKey.priv.literalValue);
979
+ const tdEntry = knownEntry ?? entries.extraItems;
980
+ if (isPositiveTest) {
981
+ // The code that is commented out below implements the behavior that is technically
982
+ // correct, but until we PEP 728 is ratified and we have a way to express "extra items"
983
+ // and closed TypedDicts, we'll preserve the older (less correct) behavior to enable
984
+ // narrowing of TypedDicts based on checks for specific keys.
985
+ // TODO - remove this behavior once PEP 728 is accepted and the feature is no
986
+ // longer experimental.
987
+ if (!tdEntry) {
988
+ return undefined;
989
+ }
990
+ // if (!tdEntry) {
991
+ // // If there is no TD entry for this key and no "extra items" defined,
992
+ // // we have to assume that the TypedDict may contain extra items, so
993
+ // // narrowing it isn't possible in this case.
994
+ // return subtype;
995
+ // }
996
+ if ((0, types_1.isNever)(tdEntry.valueType)) {
997
+ // If the entry is typed as Never or the "extra items" is typed as Never,
998
+ // then this key cannot be present in the TypedDict, and we can eliminate it.
999
+ // A closed TypedDict has an "extra items" of Never, so this is what allows
1000
+ // a key check to discriminate between closed TypedDicts.
1001
+ return undefined;
1002
+ }
1003
+ // If the entry is currently not required and not marked provided, we can mark
1004
+ // it as provided after this guard expression confirms it is.
1005
+ if (tdEntry.isRequired || tdEntry.isProvided) {
1006
+ return subtype;
1007
+ }
1008
+ const newNarrowedEntriesMap = new Map(subtype.priv.typedDictNarrowedEntries ?? []);
1009
+ // Add the new entry.
1010
+ newNarrowedEntriesMap.set(literalKey.priv.literalValue, {
1011
+ valueType: tdEntry.valueType,
1012
+ isReadOnly: tdEntry.isReadOnly,
1013
+ isRequired: false,
1014
+ isProvided: true,
1015
+ });
1016
+ // Clone the TypedDict object with the new entries.
1017
+ return types_1.ClassType.cloneAsInstance(types_1.ClassType.cloneForNarrowedTypedDictEntries(types_1.ClassType.cloneAsInstantiable(subtype), newNarrowedEntriesMap));
1018
+ }
1019
+ else {
1020
+ if (!knownEntry) {
1021
+ // The key is not one of the known items, so it can be supplied
1022
+ // only through an "extra items" entry, which says nothing about
1023
+ // whether this particular key is present. Its absence is therefore
1024
+ // consistent with the type, and the subtype cannot be eliminated.
1025
+ return subtype;
1026
+ }
1027
+ return knownEntry.isRequired || knownEntry.isProvided ? undefined : subtype;
1028
+ }
1029
+ }
1030
+ return subtype;
1031
+ });
1032
+ return narrowedType;
1033
+ }
1034
+ function narrowTypeForDiscriminatedDictEntryComparison(evaluator, referenceType, indexLiteralType, literalType, isPositiveTest) {
1035
+ let canNarrow = true;
1036
+ const narrowedType = (0, typeUtils_1.mapSubtypes)(referenceType, (subtype) => {
1037
+ if ((0, types_1.isClassInstance)(subtype) && types_1.ClassType.isTypedDictClass(subtype)) {
1038
+ const symbolMap = (0, typedDicts_1.getTypedDictMembersForClass)(evaluator, subtype);
1039
+ const tdEntry = symbolMap.knownItems.get(indexLiteralType.priv.literalValue);
1040
+ if (tdEntry && (0, typeUtils_1.isLiteralTypeOrUnion)(tdEntry.valueType)) {
1041
+ if (isPositiveTest) {
1042
+ let foundMatch = false;
1043
+ (0, typeUtils_1.doForEachSubtype)(literalType, (literalSubtype) => {
1044
+ if (evaluator.assignType(tdEntry.valueType, literalSubtype)) {
1045
+ foundMatch = true;
1046
+ }
1047
+ });
1048
+ return foundMatch ? subtype : undefined;
1049
+ }
1050
+ else {
1051
+ let foundNonMatch = false;
1052
+ (0, typeUtils_1.doForEachSubtype)(literalType, (literalSubtype) => {
1053
+ if (!evaluator.assignType(literalSubtype, tdEntry.valueType)) {
1054
+ foundNonMatch = true;
1055
+ }
1056
+ });
1057
+ return foundNonMatch ? subtype : undefined;
1058
+ }
1059
+ }
1060
+ }
1061
+ canNarrow = false;
1062
+ return subtype;
1063
+ });
1064
+ return canNarrow ? narrowedType : referenceType;
1065
+ }
1066
+ function narrowTypeForDiscriminatedTupleComparison(evaluator, referenceType, indexLiteralType, literalType, isPositiveTest) {
1067
+ let canNarrow = true;
1068
+ const narrowedType = (0, typeUtils_1.mapSubtypes)(referenceType, (subtype) => {
1069
+ if ((0, types_1.isClassInstance)(subtype) &&
1070
+ types_1.ClassType.isTupleClass(subtype) &&
1071
+ !(0, typeUtils_1.isUnboundedTupleClass)(subtype) &&
1072
+ typeof indexLiteralType.priv.literalValue === 'number' &&
1073
+ (0, types_1.isClassInstance)(literalType)) {
1074
+ const indexValue = indexLiteralType.priv.literalValue;
1075
+ if (subtype.priv.tupleTypeArgs && indexValue >= 0 && indexValue < subtype.priv.tupleTypeArgs.length) {
1076
+ const tupleEntryType = subtype.priv.tupleTypeArgs[indexValue]?.type;
1077
+ if (tupleEntryType && (0, typeUtils_1.isLiteralTypeOrUnion)(tupleEntryType)) {
1078
+ if (isPositiveTest) {
1079
+ return evaluator.assignType(tupleEntryType, literalType) ? subtype : undefined;
1080
+ }
1081
+ else {
1082
+ return evaluator.assignType(literalType, tupleEntryType) ? undefined : subtype;
1083
+ }
1084
+ }
1085
+ }
1086
+ }
1087
+ canNarrow = false;
1088
+ return subtype;
1089
+ });
1090
+ return canNarrow ? narrowedType : referenceType;
1091
+ }
1092
+ function narrowTypeForDiscriminatedLiteralFieldComparison(evaluator, referenceType, memberName, literalType, isPositiveTest) {
1093
+ const narrowedType = (0, typeUtils_1.mapSubtypes)(referenceType, (subtype) => {
1094
+ let memberInfo;
1095
+ if ((0, types_1.isClassInstance)(subtype)) {
1096
+ memberInfo = (0, typeUtils_1.lookUpObjectMember)(subtype, memberName);
1097
+ }
1098
+ else if ((0, types_1.isInstantiableClass)(subtype)) {
1099
+ memberInfo = (0, typeUtils_1.lookUpClassMember)(subtype, memberName);
1100
+ }
1101
+ if (memberInfo && memberInfo.isTypeDeclared) {
1102
+ let memberType = evaluator.getTypeOfMember(memberInfo);
1103
+ // Handle the case where the field is a property
1104
+ // that has a declared literal return type for its getter.
1105
+ if ((0, types_1.isClassInstance)(subtype) && (0, types_1.isClassInstance)(memberType) && (0, typeUtils_1.isProperty)(memberType)) {
1106
+ const getterType = memberType.priv.fgetInfo?.methodType;
1107
+ if (getterType && (0, types_1.isFunction)(getterType) && getterType.shared.declaredReturnType) {
1108
+ const getterReturnType = types_1.FunctionType.getEffectiveReturnType(getterType);
1109
+ if (getterReturnType) {
1110
+ memberType = getterReturnType;
1111
+ }
1112
+ }
1113
+ }
1114
+ if ((0, typeUtils_1.isLiteralTypeOrUnion)(memberType, /* allowNone */ true)) {
1115
+ if (isPositiveTest) {
1116
+ return evaluator.assignType(memberType, literalType) ? subtype : undefined;
1117
+ }
1118
+ else {
1119
+ return evaluator.assignType(literalType, memberType) ? undefined : subtype;
1120
+ }
1121
+ }
1122
+ }
1123
+ return subtype;
1124
+ });
1125
+ return narrowedType;
1126
+ }
1127
+ function narrowTypeForDiscriminatedFieldNoneComparison(evaluator, referenceType, memberName, isPositiveTest) {
1128
+ return (0, typeUtils_1.mapSubtypes)(referenceType, (subtype) => {
1129
+ let memberInfo;
1130
+ if ((0, types_1.isClassInstance)(subtype)) {
1131
+ memberInfo = (0, typeUtils_1.lookUpObjectMember)(subtype, memberName);
1132
+ }
1133
+ else if ((0, types_1.isInstantiableClass)(subtype)) {
1134
+ memberInfo = (0, typeUtils_1.lookUpClassMember)(subtype, memberName);
1135
+ }
1136
+ if (memberInfo && memberInfo.isTypeDeclared) {
1137
+ // Check the declared type before narrowing, since the member type
1138
+ // below will be concretized and lose descriptor identity.
1139
+ const declaredType = evaluator.getDeclaredTypeOfSymbol(memberInfo.symbol)?.type;
1140
+ if (!declaredType) {
1141
+ // isTypeDeclared is true but the type couldn't be resolved (e.g. an
1142
+ // unresolvable stub). Conservatively skip narrowing rather than risk
1143
+ // incorrectly eliminating a descriptor-typed member.
1144
+ return subtype;
1145
+ }
1146
+ // Check if any subtype of the declared type is a descriptor or property.
1147
+ // isMaybeDescriptorInstance handles declared types in instance form (ClassInstance),
1148
+ // while isMaybeDescriptorClass handles declared types in instantiable form
1149
+ // (InstantiableClass), which occurs when the annotation refers to the class object itself.
1150
+ // This check applies to both positive and negative test paths: descriptor __get__
1151
+ // return values don't reflect stored values regardless of test polarity.
1152
+ const isDescriptorOrProperty = (0, typeUtils_1.someSubtypes)(declaredType, (declaredSubtype) => (0, typeUtils_1.isProperty)(declaredSubtype) ||
1153
+ (0, typeUtils_1.isMaybeDescriptorInstance)(declaredSubtype) ||
1154
+ (0, typeUtils_1.isMaybeDescriptorClass)(declaredSubtype));
1155
+ if (isDescriptorOrProperty) {
1156
+ return subtype;
1157
+ }
1158
+ const memberType = evaluator.makeTopLevelTypeVarsConcrete(evaluator.getTypeOfMember(memberInfo));
1159
+ let canNarrow = true;
1160
+ if (isPositiveTest) {
1161
+ (0, typeUtils_1.doForEachSubtype)(memberType, (memberSubtype) => {
1162
+ memberSubtype = evaluator.makeTopLevelTypeVarsConcrete(memberSubtype);
1163
+ if ((0, types_1.isAnyOrUnknown)(memberSubtype) || (0, typeUtils_1.isNoneInstance)(memberSubtype) || (0, types_1.isNever)(memberSubtype)) {
1164
+ canNarrow = false;
1165
+ }
1166
+ });
1167
+ }
1168
+ else {
1169
+ canNarrow = (0, typeUtils_1.isNoneInstance)(memberType);
1170
+ }
1171
+ if (canNarrow) {
1172
+ return undefined;
1173
+ }
1174
+ }
1175
+ return subtype;
1176
+ });
1177
+ }
1178
+ function narrowTypeForTypeIs(evaluator, type, classTypes, isPositiveTest, isIsOperator, classTypeVar, allowLegacyEquality) {
1179
+ const metaclassEqualityResults = isIsOperator ? undefined : new Map();
1180
+ const hasEqualitySemantics = allowLegacyEquality
1181
+ ? hasDeclaredIdentityEqualitySemantics
1182
+ : hasIdentityEqualitySemantics;
1183
+ if (metaclassEqualityResults &&
1184
+ classTypes.some((classType) => !hasEqualitySemantics(classType, metaclassEqualityResults))) {
1185
+ return type;
1186
+ }
1187
+ // We currently don't support narrowing in the negative direction
1188
+ // when there are more than one class types.
1189
+ if (!isPositiveTest && classTypes.length > 1) {
1190
+ return type;
1191
+ }
1192
+ // Retain the TypeVar rather than its expanded constraints so assignments and loop joins preserve correlation.
1193
+ if (isIsOperator && isPositiveTest && classTypeVar && (0, types_1.isAnyOrUnknown)(type)) {
1194
+ return classTypeVar;
1195
+ }
1196
+ let gradualArgResults;
1197
+ const typesToCombine = classTypes.map((classType) => {
1198
+ return evaluator.mapSubtypesExpandTypeVars(type,
1199
+ /* options */ undefined, (subtype, unexpandedSubtype) => {
1200
+ if ((0, types_1.isClassInstance)(subtype)) {
1201
+ const isLiteral = subtype.priv.literalValue !== undefined;
1202
+ const instantiableSubtype = isLiteral
1203
+ ? types_1.ClassType.cloneIncludeSubclasses(types_1.ClassType.cloneAsInstantiable(types_1.ClassType.cloneWithLiteral(subtype, undefined)),
1204
+ /* includeSubclasses */ false)
1205
+ : types_1.ClassType.cloneAsInstantiable(subtype);
1206
+ if (metaclassEqualityResults &&
1207
+ !hasEqualitySemantics(instantiableSubtype, metaclassEqualityResults)) {
1208
+ return unexpandedSubtype;
1209
+ }
1210
+ const matches = types_1.ClassType.isDerivedFrom(classType, instantiableSubtype);
1211
+ // A literal has an exact runtime class, not an arbitrary subclass.
1212
+ if (matches && isLiteral && !types_1.ClassType.isSameGenericClass(instantiableSubtype, classType)) {
1213
+ return isPositiveTest ? undefined : subtype;
1214
+ }
1215
+ if (isPositiveTest) {
1216
+ if (matches) {
1217
+ if (types_1.ClassType.isSameGenericClass(instantiableSubtype, classType)) {
1218
+ return (0, typeUtils_1.addConditionToType)(subtype, (0, typeUtils_1.getTypeCondition)(classType));
1219
+ }
1220
+ let narrowedClass = classType;
1221
+ if (subtype.priv.typeArgs || subtype.priv.tupleTypeArgs) {
1222
+ if (classType.shared.typeParams.length > 0) {
1223
+ if ((0, typeUtils_1.containsAnyRecursive)(classType) ||
1224
+ !evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(classType))) {
1225
+ const genericClass = (0, typeUtils_1.selfSpecializeClass)(types_1.ClassType.specialize(classType, undefined));
1226
+ const constraints = new constraintTracker_1.ConstraintTracker();
1227
+ if (!evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(genericClass), undefined, constraints, 2 /* AssignTypeFlags.Contravariant */ |
1228
+ 2048 /* AssignTypeFlags.PopulateExpectedType */ |
1229
+ 4096 /* AssignTypeFlags.SkipPopulateUnknownExpectedType */)) {
1230
+ return (0, typeUtils_1.addConditionToType)(subtype, (0, typeUtils_1.getTypeCondition)(classType));
1231
+ }
1232
+ const specializedClass = evaluator.solveAndApplyConstraints(genericClass, constraints, {
1233
+ replaceUnsolved: {
1234
+ scopeIds: (0, typeUtils_1.getTypeVarScopeIds)(classType),
1235
+ useUnknown: true,
1236
+ tupleClassType: evaluator.getTupleClassType(),
1237
+ },
1238
+ });
1239
+ if (!(0, types_1.isInstantiableClass)(specializedClass)) {
1240
+ return (0, typeUtils_1.addConditionToType)(subtype, (0, typeUtils_1.getTypeCondition)(classType));
1241
+ }
1242
+ const results = (gradualArgResults ?? (gradualArgResults = new Map()));
1243
+ narrowedClass = types_1.ClassType.specialize(specializedClass, specializedClass.priv.typeArgs?.map((arg, index) => fillTypeGuardGradualArgs(arg, classType.priv.typeArgs?.[index], results)));
1244
+ }
1245
+ }
1246
+ else if (!evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(classType))) {
1247
+ return classType.priv.includeSubclasses && !types_1.ClassType.isFinal(classType)
1248
+ ? (0, typeUtils_1.addConditionToType)(subtype, (0, typeUtils_1.getTypeCondition)(classType))
1249
+ : undefined;
1250
+ }
1251
+ }
1252
+ return (0, typeUtils_1.addConditionToType)(types_1.ClassType.cloneAsInstance(narrowedClass), subtype.props?.condition);
1253
+ }
1254
+ if (!classType.priv.includeSubclasses) {
1255
+ if (evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(classType))) {
1256
+ return (0, typeUtils_1.addConditionToType)(types_1.ClassType.cloneAsInstance(classType), (0, typeUtils_1.getTypeCondition)(subtype));
1257
+ }
1258
+ return undefined;
1259
+ }
1260
+ // A subclass of both the subtype and the class could satisfy the
1261
+ // comparison, so eliminate the subtype only if no such class can exist.
1262
+ if ((types_1.ClassType.isFinal(classType) ||
1263
+ isLiteral ||
1264
+ types_1.ClassType.isFinal(instantiableSubtype) ||
1265
+ areDisjointBasesIncompatible(instantiableSubtype, classType)) &&
1266
+ !evaluator.assignType(types_1.ClassType.cloneAsInstance(classType), subtype) &&
1267
+ !evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(classType))) {
1268
+ return undefined;
1269
+ }
1270
+ if (!(0, types_1.isTypeVar)(unexpandedSubtype) || !types_1.TypeVarType.isSelf(unexpandedSubtype)) {
1271
+ return (0, typeUtils_1.addConditionToType)(subtype, classType.props?.condition);
1272
+ }
1273
+ }
1274
+ // A final class has no subclasses, so it is treated as an exact class.
1275
+ if (!classType.priv.includeSubclasses || types_1.ClassType.isFinal(classType)) {
1276
+ // If the runtime class is exact and it matches, then
1277
+ // we can eliminate it in the negative case.
1278
+ if (matches && (isLiteral || types_1.ClassType.isFinal(instantiableSubtype))) {
1279
+ return undefined;
1280
+ }
1281
+ // We can't eliminate the subtype in the negative
1282
+ // case because it could be a subclass of the type,
1283
+ // in which case `type(x) is y` would fail.
1284
+ return subtype;
1285
+ }
1286
+ }
1287
+ if ((0, types_1.isAnyOrUnknown)(subtype)) {
1288
+ if (metaclassEqualityResults && !allowLegacyEquality) {
1289
+ return subtype;
1290
+ }
1291
+ return isPositiveTest
1292
+ ? types_1.ClassType.cloneAsInstance((0, typeUtils_1.addConditionToType)(classType, (0, typeUtils_1.getTypeCondition)(subtype)))
1293
+ : subtype;
1294
+ }
1295
+ return unexpandedSubtype;
1296
+ });
1297
+ });
1298
+ return (0, types_1.combineTypes)(typesToCombine);
1299
+ }
1300
+ function hasUnresolvedMetaclassInMro(classType) {
1301
+ return classType.shared.mro.some((baseClass) => !(0, types_1.isInstantiableClass)(baseClass) || !!(baseClass.shared.flags & 134217728 /* ClassTypeFlags.HasUnresolvedMetaclass */));
1302
+ }
1303
+ function hasIdentityEqualitySemantics(classType, metaclassEqualityResults) {
1304
+ if (classType.priv.includeSubclasses && !types_1.ClassType.isFinal(classType)) {
1305
+ return false;
1306
+ }
1307
+ if (classType.shared.typeParams.length > 0) {
1308
+ return false;
1309
+ }
1310
+ return hasDeclaredIdentityEqualitySemantics(classType, metaclassEqualityResults);
1311
+ }
1312
+ function hasDeclaredIdentityEqualitySemantics(classType, metaclassEqualityResults) {
1313
+ const metaclass = classType.shared.effectiveMetaclass;
1314
+ if (!metaclass ||
1315
+ !(0, types_1.isInstantiableClass)(metaclass) ||
1316
+ hasUnresolvedMetaclassInMro(classType) ||
1317
+ hasUnresolvedMetaclassInMro(metaclass)) {
1318
+ return false;
1319
+ }
1320
+ if (types_1.ClassType.isBuiltIn(metaclass, 'type')) {
1321
+ return true;
1322
+ }
1323
+ // Cloned metaclasses share method definitions, but the class-specific checks above cannot be shared.
1324
+ const cachedResult = metaclassEqualityResults.get(metaclass.shared);
1325
+ if (cachedResult !== undefined) {
1326
+ return cachedResult;
1327
+ }
1328
+ const result = !(0, operations_1.customMetaclassSupportsMethod)(classType, '__eq__') && !(0, operations_1.customMetaclassSupportsMethod)(classType, '__ne__');
1329
+ metaclassEqualityResults.set(metaclass.shared, result);
1330
+ return result;
1331
+ }
1332
+ function narrowTypeForClassComparison(evaluator, referenceType, classType, isPositiveTest, isIsOperator = true) {
1333
+ // Limit reuse to this invocation so results cannot outlive the evaluation that established them.
1334
+ const metaclassEqualityResults = isIsOperator ? undefined : new Map();
1335
+ if (metaclassEqualityResults && !hasIdentityEqualitySemantics(classType, metaclassEqualityResults)) {
1336
+ return referenceType;
1337
+ }
1338
+ return (0, typeUtils_1.mapSubtypes)(referenceType, (subtype) => {
1339
+ // Multiple class constraints expand to a union with distinct conditions, which equality cannot narrow.
1340
+ if (metaclassEqualityResults &&
1341
+ (0, types_1.isTypeVar)(subtype) &&
1342
+ !subtype.shared.recursiveAlias &&
1343
+ subtype.shared.constraints.length > 1 &&
1344
+ subtype.shared.constraints.every(types_1.isClassInstance)) {
1345
+ return subtype;
1346
+ }
1347
+ let concreteSubtype = evaluator.makeTopLevelTypeVarsConcrete(subtype);
1348
+ if (metaclassEqualityResults &&
1349
+ (!(0, types_1.isInstantiableClass)(concreteSubtype) ||
1350
+ !hasIdentityEqualitySemantics(concreteSubtype, metaclassEqualityResults))) {
1351
+ return subtype;
1352
+ }
1353
+ if (isPositiveTest) {
1354
+ if ((0, types_1.isClassInstance)(concreteSubtype) &&
1355
+ types_1.TypeBase.isInstance(subtype) &&
1356
+ types_1.ClassType.isBuiltIn(concreteSubtype, 'type')) {
1357
+ concreteSubtype =
1358
+ concreteSubtype.priv.typeArgs && concreteSubtype.priv.typeArgs.length > 0
1359
+ ? (0, typeUtils_1.convertToInstantiable)(concreteSubtype.priv.typeArgs[0])
1360
+ : types_1.UnknownType.create();
1361
+ }
1362
+ if ((0, types_1.isAnyOrUnknown)(concreteSubtype)) {
1363
+ return (0, typeUtils_1.addConditionToType)(classType, (0, typeUtils_1.getTypeCondition)(concreteSubtype));
1364
+ }
1365
+ if ((0, types_1.isClass)(concreteSubtype)) {
1366
+ if (types_1.TypeBase.isInstance(concreteSubtype)) {
1367
+ if (!isIsOperator) {
1368
+ return subtype;
1369
+ }
1370
+ return types_1.ClassType.isBuiltIn(concreteSubtype, 'object') ? classType : undefined;
1371
+ }
1372
+ const isSuperType = isFilterSuperclass(subtype, concreteSubtype, classType, classType);
1373
+ if (!classType.priv.includeSubclasses) {
1374
+ // Handle the case where the LHS and RHS operands are specific
1375
+ // classes, as opposed to types that represent classes and their
1376
+ // subclasses.
1377
+ if (!concreteSubtype.priv.includeSubclasses) {
1378
+ return types_1.ClassType.isSameGenericClass(concreteSubtype, classType) ? classType : undefined;
1379
+ }
1380
+ if (isSuperType) {
1381
+ return (0, typeUtils_1.addConditionToType)(classType, (0, typeUtils_1.getTypeCondition)(concreteSubtype));
1382
+ }
1383
+ const isSubType = types_1.ClassType.isDerivedFrom(classType, concreteSubtype);
1384
+ if (isSubType) {
1385
+ return (0, typeUtils_1.addConditionToType)(classType, (0, typeUtils_1.getTypeCondition)(concreteSubtype));
1386
+ }
1387
+ return undefined;
1388
+ }
1389
+ if (types_1.ClassType.isFinal(concreteSubtype) && !isSuperType) {
1390
+ return undefined;
1391
+ }
1392
+ }
1393
+ }
1394
+ else {
1395
+ if ((0, types_1.isInstantiableClass)(concreteSubtype) &&
1396
+ types_1.ClassType.isSameGenericClass(classType, concreteSubtype) &&
1397
+ types_1.ClassType.isFinal(classType)) {
1398
+ return undefined;
1399
+ }
1400
+ }
1401
+ return subtype;
1402
+ });
1403
+ }
1404
+ function isFilterSuperclass(varType, concreteVarType, filterType, concreteFilterType) {
1405
+ if ((0, types_1.isTypeVar)(filterType) || concreteFilterType.priv.literalValue !== undefined) {
1406
+ return (0, types_1.isTypeSame)((0, typeUtils_1.convertToInstance)(filterType), varType);
1407
+ }
1408
+ // If the filter type represents all possible subclasses
1409
+ // of a type, we can't make any statements about its superclass
1410
+ // relationship with concreteVarType.
1411
+ if (concreteFilterType.priv.includeSubclasses) {
1412
+ return false;
1413
+ }
1414
+ if (types_1.ClassType.isDerivedFrom(concreteVarType, concreteFilterType)) {
1415
+ return true;
1416
+ }
1417
+ // Handle the special case where the variable type is a TypedDict and
1418
+ // we're filtering against 'dict'. TypedDict isn't derived from dict,
1419
+ // but at runtime, isinstance returns True.
1420
+ if (types_1.ClassType.isBuiltIn(concreteFilterType, 'dict') && types_1.ClassType.isTypedDictClass(concreteVarType)) {
1421
+ return true;
1422
+ }
1423
+ return false;
1424
+ }
1425
+ function isPrimitiveBackedEnumClass(classType) {
1426
+ if (!types_1.ClassType.isEnumClass(classType)) {
1427
+ return false;
1428
+ }
1429
+ return (0, typeUtils_1.derivesFromStdlibClass)(classType, 'int') || (0, typeUtils_1.derivesFromStdlibClass)(classType, 'str');
1430
+ }
1431
+ function isPrimitiveBackedEnumAndPrimitive(enumType, primitiveType) {
1432
+ if (types_1.ClassType.isEnumClass(primitiveType) || !isPrimitiveBackedEnumClass(enumType)) {
1433
+ return false;
1434
+ }
1435
+ // Exclude bool, which derives from int but whose literal values are distinct
1436
+ // from the corresponding int literals.
1437
+ if (types_1.ClassType.isBuiltIn(primitiveType, 'int')) {
1438
+ return (0, typeUtils_1.derivesFromStdlibClass)(enumType, 'int');
1439
+ }
1440
+ if (types_1.ClassType.isBuiltIn(primitiveType, 'str')) {
1441
+ return (0, typeUtils_1.derivesFromStdlibClass)(enumType, 'str');
1442
+ }
1443
+ return false;
1444
+ }
1445
+ function unwrapPrimitiveBackedEnumLiteral(classType) {
1446
+ const literalValue = classType.priv.literalValue;
1447
+ if (!(literalValue instanceof types_1.EnumLiteral) || !isPrimitiveBackedEnumClass(classType)) {
1448
+ return classType;
1449
+ }
1450
+ const itemType = literalValue.itemType;
1451
+ if ((0, types_1.isClassInstance)(itemType) && itemType.priv.literalValue !== undefined) {
1452
+ return itemType;
1453
+ }
1454
+ return classType;
1455
+ }
1456
+ function isLiteralValueEqualAtRuntime(type1, type2) {
1457
+ return types_1.ClassType.isLiteralValueSame(unwrapPrimitiveBackedEnumLiteral(type1), unwrapPrimitiveBackedEnumLiteral(type2));
1458
+ }
1459
+ function getInnermostNewTypeBaseInstance(subtype) {
1460
+ if (!(0, types_1.isClassInstance)(subtype) || !types_1.ClassType.isNewTypeClass(subtype)) {
1461
+ return undefined;
1462
+ }
1463
+ let currentType = subtype;
1464
+ while ((0, types_1.isClassInstance)(currentType) && types_1.ClassType.isNewTypeClass(currentType)) {
1465
+ if (currentType.shared.baseClasses.length === 0) {
1466
+ return undefined;
1467
+ }
1468
+ const baseClass = currentType.shared.baseClasses[0];
1469
+ if (!(0, types_1.isClass)(baseClass)) {
1470
+ return undefined;
1471
+ }
1472
+ currentType = types_1.ClassType.cloneAsInstance(baseClass);
1473
+ }
1474
+ return currentType;
1475
+ }
1476
+ function narrowTypeForLiteralComparison(evaluator, referenceType, literalType, isPositiveTest, isIsOperator) {
1477
+ return evaluator.mapSubtypesExpandTypeVars(referenceType, /* options */ undefined, (subtype) => {
1478
+ subtype = evaluator.makeTopLevelTypeVarsConcrete(subtype);
1479
+ if ((0, types_1.isAnyOrUnknown)(subtype)) {
1480
+ if (isPositiveTest) {
1481
+ return literalType;
1482
+ }
1483
+ return subtype;
1484
+ }
1485
+ // Determine whether this is a comparison between a primitive-backed enum
1486
+ // (e.g. IntEnum or StrEnum) and its underlying primitive type. Such a
1487
+ // comparison can be used for narrowing because the enum member compares
1488
+ // equal to its underlying primitive value at runtime.
1489
+ const isPrimitiveBackedEnumComparison = !isIsOperator &&
1490
+ (0, types_1.isClassInstance)(subtype) &&
1491
+ (isPrimitiveBackedEnumAndPrimitive(subtype, literalType) ||
1492
+ isPrimitiveBackedEnumAndPrimitive(literalType, subtype));
1493
+ if ((0, types_1.isClassInstance)(subtype) &&
1494
+ (types_1.ClassType.isSameGenericClass(literalType, subtype) || isPrimitiveBackedEnumComparison)) {
1495
+ if (subtype.priv.literalValue !== undefined) {
1496
+ const literalValueMatches = isPrimitiveBackedEnumComparison
1497
+ ? isLiteralValueEqualAtRuntime(subtype, literalType)
1498
+ : types_1.ClassType.isLiteralValueSame(subtype, literalType);
1499
+ if (isPositiveTest) {
1500
+ return literalValueMatches ? subtype : undefined;
1501
+ }
1502
+ const isSingleton = types_1.ClassType.isEnumClass(literalType) ||
1503
+ (0, typeUtils_1.isSentinelLiteral)(subtype) ||
1504
+ types_1.ClassType.isBuiltIn(literalType, 'bool');
1505
+ // For negative tests, we can eliminate the literal value if it doesn't match,
1506
+ // but only for equality tests or for 'is' tests that involve enums, bools, or sentinels.
1507
+ return literalValueMatches && (isSingleton || !isIsOperator) ? undefined : subtype;
1508
+ }
1509
+ if (isPositiveTest) {
1510
+ if (isPrimitiveBackedEnumComparison) {
1511
+ // If the reference type is the enum, attempt to find the member
1512
+ // whose value matches the primitive literal. If no member can be
1513
+ // identified (e.g. for an IntFlag class, whose members cannot be
1514
+ // enumerated), retain the reference type rather than narrowing it
1515
+ // to the primitive literal type.
1516
+ if (types_1.ClassType.isEnumClass(subtype)) {
1517
+ const allLiteralTypes = enumerateLiteralsForType(evaluator, subtype);
1518
+ const match = allLiteralTypes?.find((type) => isLiteralValueEqualAtRuntime(type, literalType));
1519
+ return match ?? subtype;
1520
+ }
1521
+ // The reference type is the primitive type, so narrowing it to the
1522
+ // enum literal would lose its (potentially derived) class. Retain
1523
+ // the reference type instead.
1524
+ return subtype;
1525
+ }
1526
+ return literalType;
1527
+ }
1528
+ // If we're able to enumerate all possible literal values
1529
+ // (for bool or enum), we can eliminate all others in a negative test.
1530
+ const allLiteralTypes = enumerateLiteralsForType(evaluator, subtype);
1531
+ if (allLiteralTypes && allLiteralTypes.length > 0) {
1532
+ return (0, types_1.combineTypes)(allLiteralTypes.filter((type) => isPrimitiveBackedEnumComparison
1533
+ ? !isLiteralValueEqualAtRuntime(type, literalType)
1534
+ : !types_1.ClassType.isLiteralValueSame(type, literalType)));
1535
+ }
1536
+ return subtype;
1537
+ }
1538
+ if (isPositiveTest) {
1539
+ if ((0, types_1.isClassInstance)(subtype) && types_1.ClassType.isBuiltIn(subtype, 'LiteralString')) {
1540
+ return literalType;
1541
+ }
1542
+ if (isIsOperator || (0, typeUtils_1.isNoneInstance)(subtype)) {
1543
+ const compareType = getInnermostNewTypeBaseInstance(subtype) ?? subtype;
1544
+ const isSubtype = evaluator.assignType(compareType, literalType);
1545
+ if (isSubtype) {
1546
+ return (0, types_1.isClassInstance)(subtype) && types_1.ClassType.isNewTypeClass(subtype) ? subtype : literalType;
1547
+ }
1548
+ return undefined;
1549
+ }
1550
+ }
1551
+ return subtype;
1552
+ });
1553
+ }
1554
+ function enumerateLiteralsForType(evaluator, type) {
1555
+ if (types_1.ClassType.isBuiltIn(type, 'bool')) {
1556
+ // Booleans have only two types: True and False.
1557
+ return [
1558
+ types_1.ClassType.cloneWithLiteral(type, /* value */ true),
1559
+ types_1.ClassType.cloneWithLiteral(type, /* value */ false),
1560
+ ];
1561
+ }
1562
+ if (types_1.ClassType.isEnumClass(type)) {
1563
+ // Enum expansion doesn't apply if the member set cannot be statically
1564
+ // enumerated or if the class derives from enum.Flag.
1565
+ if (types_1.ClassType.isEnumMemberSetMayBeDynamicallyModified(type) ||
1566
+ type.shared.mro.some((mroClass) => (0, types_1.isClass)(mroClass) && types_1.ClassType.isBuiltIn(mroClass, 'Flag'))) {
1567
+ return undefined;
1568
+ }
1569
+ // Enumerate all of the values in this enumeration.
1570
+ const enumList = [];
1571
+ const fields = types_1.ClassType.getSymbolTable(type);
1572
+ fields.forEach((symbol, name) => {
1573
+ if (!symbol.isIgnoredForProtocolMatch()) {
1574
+ let symbolType = evaluator.getEffectiveTypeOfSymbol(symbol);
1575
+ symbolType = (0, enums_1.transformTypeForEnumMember)(evaluator, type, name, (0, analyzerNodeInfo_1.getInfoReader)(evaluator)) ?? symbolType;
1576
+ if ((0, types_1.isClassInstance)(symbolType) &&
1577
+ types_1.ClassType.isSameGenericClass(type, symbolType) &&
1578
+ symbolType.priv.literalValue !== undefined) {
1579
+ enumList.push(symbolType);
1580
+ }
1581
+ }
1582
+ });
1583
+ return enumList;
1584
+ }
1585
+ return undefined;
1586
+ }
1587
+ function isNameSameScope(evaluator, reference, expression) {
1588
+ const refSymbol = evaluator.lookUpSymbolRecursive(reference, reference.d.value, /* honorCodeFlow */ false);
1589
+ const exprSymbol = evaluator.lookUpSymbolRecursive(expression, expression.d.value, /* honorCodeFlow */ false);
1590
+ if (!refSymbol || !exprSymbol) {
1591
+ // This shouldn't happen, but just to be safe...
1592
+ return true;
1593
+ }
1594
+ const refScope = refSymbol.scope;
1595
+ const exprScope = exprSymbol.scope;
1596
+ if (refScope === exprScope) {
1597
+ return true;
1598
+ }
1599
+ return (0, scopeUtils_1.isScopeContainedWithin)(refScope, exprScope);
1600
+ }
1601
+ function areDisjointBasesIncompatible(classType1, classType2) {
1602
+ const base1 = types_1.ClassType.getDisjointBase(classType1);
1603
+ const base2 = types_1.ClassType.getDisjointBase(classType2);
1604
+ return !!base1 && !!base2 && !types_1.ClassType.getMostDerivedDisjointBase([base1, base2]);
1605
+ }
1606
+ function fillTypeGuardGradualArgs(input, hint, results, recursionCount = 0) {
1607
+ if (!hint || input === hint || recursionCount > types_1.maxTypeRecursionCount) {
1608
+ return input;
1609
+ }
1610
+ if ((0, types_1.isAnyOrUnknown)(input)) {
1611
+ return (0, types_1.isAnyOrUnknown)(hint) ? ((0, types_1.isAny)(hint) ? hint : input) : hint;
1612
+ }
1613
+ if (!(0, types_1.isClass)(input) || !(0, types_1.isClass)(hint) || !types_1.ClassType.isSameGenericClass(input, hint)) {
1614
+ return input;
1615
+ }
1616
+ let inputResults = results.get(input);
1617
+ const cachedResult = inputResults?.get(hint);
1618
+ if (cachedResult !== undefined) {
1619
+ return cachedResult;
1620
+ }
1621
+ if (!inputResults) {
1622
+ inputResults = new Map();
1623
+ results.set(input, inputResults);
1624
+ }
1625
+ // Bound recursive aliases and reuse shared argument graphs within this narrowing operation.
1626
+ inputResults.set(hint, input);
1627
+ const inputTuple = input.priv.tupleTypeArgs;
1628
+ const hintTuple = hint.priv.tupleTypeArgs;
1629
+ if (inputTuple || hintTuple) {
1630
+ if (!inputTuple ||
1631
+ !hintTuple ||
1632
+ inputTuple.length !== hintTuple.length ||
1633
+ inputTuple.some((arg, index) => arg.isUnbounded !== hintTuple[index].isUnbounded ||
1634
+ !!arg.isOptional !== !!hintTuple[index].isOptional)) {
1635
+ return input;
1636
+ }
1637
+ const tupleArgs = inputTuple.map((arg, index) => ({
1638
+ ...arg,
1639
+ type: fillTypeGuardGradualArgs(arg.type, hintTuple[index].type, results, recursionCount + 1),
1640
+ }));
1641
+ const result = tupleArgs.every((arg, index) => arg.type === inputTuple[index].type)
1642
+ ? input
1643
+ : (0, typeUtils_1.specializeTupleClass)(input, tupleArgs, input.priv.isTypeArgExplicit, input.priv.isUnpacked);
1644
+ inputResults.set(hint, result);
1645
+ return result;
1646
+ }
1647
+ const inputArgs = input.priv.typeArgs;
1648
+ const hintArgs = hint.priv.typeArgs;
1649
+ if (!inputArgs || !hintArgs || inputArgs.length !== hintArgs.length) {
1650
+ return input;
1651
+ }
1652
+ const typeArgs = inputArgs.map((arg, index) => fillTypeGuardGradualArgs(arg, hintArgs[index], results, recursionCount + 1));
1653
+ const result = typeArgs.every((arg, index) => arg === inputArgs[index])
1654
+ ? input
1655
+ : types_1.ClassType.specialize(input, typeArgs, input.priv.isTypeArgExplicit);
1656
+ inputResults.set(hint, result);
1657
+ return result;
1658
+ }
1659
+ function narrowTypeForUserDefinedTypeGuard(evaluator, type, typeGuardType, isPositiveTest, isStrictTypeGuard, errorNode, nodeInfo, narrowTypeForInstanceOrSubclassCallback) {
1660
+ // For non-strict type guards, always narrow to the typeGuardType
1661
+ // in the positive case and don't narrow in the negative case.
1662
+ if (!isStrictTypeGuard) {
1663
+ let result = type;
1664
+ if (isPositiveTest) {
1665
+ result = typeGuardType;
1666
+ // If the type guard is a non-constrained TypeVar, add a
1667
+ // condition to the resulting type.
1668
+ if ((0, types_1.isTypeVar)(type) && !(0, types_1.isParamSpec)(type) && !types_1.TypeVarType.hasConstraints(type)) {
1669
+ result = (0, typeUtils_1.addConditionToType)(result, [{ typeVar: type, constraintIndex: 0 }]);
1670
+ }
1671
+ return result;
1672
+ }
1673
+ return result;
1674
+ }
1675
+ const filterTypes = [];
1676
+ (0, typeUtils_1.doForEachSubtype)(typeGuardType, (typeGuardSubtype) => {
1677
+ filterTypes.push((0, typeUtils_1.convertToInstantiable)(typeGuardSubtype));
1678
+ });
1679
+ return narrowTypeForInstanceOrSubclassCallback(evaluator, type, filterTypes,
1680
+ /* isInstanceCheck */ true,
1681
+ /* isTypeIsCheck */ true, isPositiveTest, errorNode, nodeInfo);
1682
+ }
1683
+ //# sourceMappingURL=typeGuardNarrowing.js.map