@zzzen/pyright-internal 1.2.0-dev.20261011 → 1.2.0-dev.20261101
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.
- package/dist/analyzer/binder.js +28 -9
- package/dist/analyzer/binder.js.map +1 -1
- package/dist/analyzer/checker.js +8 -3
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/codeFlowEngine.js +76 -30
- package/dist/analyzer/codeFlowEngine.js.map +1 -1
- package/dist/analyzer/dataClasses.js +14 -5
- package/dist/analyzer/dataClasses.js.map +1 -1
- package/dist/analyzer/decorators.d.ts +1 -1
- package/dist/analyzer/decorators.js +22 -2
- package/dist/analyzer/decorators.js.map +1 -1
- package/dist/analyzer/namedTuples.d.ts +2 -1
- package/dist/analyzer/namedTuples.js +63 -35
- package/dist/analyzer/namedTuples.js.map +1 -1
- package/dist/analyzer/operations.js +45 -1
- package/dist/analyzer/operations.js.map +1 -1
- package/dist/analyzer/overloadResultAdmission.js +115 -3
- package/dist/analyzer/overloadResultAdmission.js.map +1 -1
- package/dist/analyzer/overloadResultController.js +36 -10
- package/dist/analyzer/overloadResultController.js.map +1 -1
- package/dist/analyzer/overloadResultSelector.js +32 -12
- package/dist/analyzer/overloadResultSelector.js.map +1 -1
- package/dist/analyzer/parseTreeUtils.d.ts +3 -0
- package/dist/analyzer/parseTreeUtils.js +56 -0
- package/dist/analyzer/parseTreeUtils.js.map +1 -1
- package/dist/analyzer/patternMatching.js +67 -27
- package/dist/analyzer/patternMatching.js.map +1 -1
- package/dist/analyzer/program.d.ts +3 -0
- package/dist/analyzer/program.js +34 -9
- package/dist/analyzer/program.js.map +1 -1
- package/dist/analyzer/sentinel.js +7 -1
- package/dist/analyzer/sentinel.js.map +1 -1
- package/dist/analyzer/service.js +6 -2
- package/dist/analyzer/service.js.map +1 -1
- package/dist/analyzer/sourceEnumerator.d.ts +3 -1
- package/dist/analyzer/sourceEnumerator.js +30 -11
- package/dist/analyzer/sourceEnumerator.js.map +1 -1
- package/dist/analyzer/sourceFile.js +13 -6
- package/dist/analyzer/sourceFile.js.map +1 -1
- package/dist/analyzer/sourceMapper.d.ts +1 -0
- package/dist/analyzer/sourceMapper.js +10 -4
- package/dist/analyzer/sourceMapper.js.map +1 -1
- package/dist/analyzer/tupleComparison.d.ts +6 -0
- package/dist/analyzer/tupleComparison.js +731 -0
- package/dist/analyzer/tupleComparison.js.map +1 -0
- package/dist/analyzer/tuples.js +52 -10
- package/dist/analyzer/tuples.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +508 -63
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +1 -1
- package/dist/analyzer/typeEvaluatorTypes.js +2 -3
- package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
- package/dist/analyzer/typeGuards.d.ts +6 -1
- package/dist/analyzer/typeGuards.js +373 -72
- package/dist/analyzer/typeGuards.js.map +1 -1
- package/dist/analyzer/typeStubRenderer.d.ts +6 -1
- package/dist/analyzer/typeStubRenderer.js +19 -12
- package/dist/analyzer/typeStubRenderer.js.map +1 -1
- package/dist/analyzer/typeUtils.js +3 -0
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/analyzer/typedDicts.d.ts +2 -1
- package/dist/analyzer/typedDicts.js +49 -10
- package/dist/analyzer/typedDicts.js.map +1 -1
- package/dist/analyzer/types.d.ts +14 -0
- package/dist/analyzer/types.js +215 -10
- package/dist/analyzer/types.js.map +1 -1
- package/dist/common/configOptions.d.ts +1 -0
- package/dist/common/configOptions.js +9 -0
- package/dist/common/configOptions.js.map +1 -1
- package/dist/common/processUtils.d.ts +6 -0
- package/dist/common/processUtils.js +56 -1
- package/dist/common/processUtils.js.map +1 -1
- package/dist/common/textEditTracker.js +1 -1
- package/dist/common/textEditTracker.js.map +1 -1
- package/dist/common/windowsProcessTree.d.ts +2 -0
- package/dist/common/windowsProcessTree.js +23 -0
- package/dist/common/windowsProcessTree.js.map +1 -1
- package/dist/common/windowsProcessTree.json +273 -34
- package/dist/languageServerBase.d.ts +3 -0
- package/dist/languageServerBase.js +44 -12
- package/dist/languageServerBase.js.map +1 -1
- package/dist/languageService/callHierarchyProvider.js +6 -6
- package/dist/languageService/callHierarchyProvider.js.map +1 -1
- package/dist/languageService/referencesProvider.js +3 -3
- package/dist/languageService/referencesProvider.js.map +1 -1
- package/dist/languageService/renameProvider.js +1 -1
- package/dist/languageService/renameProvider.js.map +1 -1
- package/dist/languageService/symbolIndexer.js +2 -2
- package/dist/languageService/symbolIndexer.js.map +1 -1
- package/dist/localization/localize.d.ts +2 -0
- package/dist/localization/localize.js +2 -0
- package/dist/localization/localize.js.map +1 -1
- package/dist/localization/package.nls.en-us.json +8 -0
- package/dist/parser/parseTreeTokenReuse.d.ts +34 -0
- package/dist/parser/parseTreeTokenReuse.js +897 -0
- package/dist/parser/parseTreeTokenReuse.js.map +1 -0
- package/dist/parser/tokenizer.d.ts +10 -1
- package/dist/parser/tokenizer.js +184 -130
- package/dist/parser/tokenizer.js.map +1 -1
- package/dist/tests/checker.test.js +58 -0
- package/dist/tests/checker.test.js.map +1 -1
- package/dist/tests/config.test.js +126 -0
- package/dist/tests/config.test.js.map +1 -1
- package/dist/tests/fourSlashParser.test.js +35 -0
- package/dist/tests/fourSlashParser.test.js.map +1 -1
- package/dist/tests/fourslash/hover.typedDict.get.fourslash.js +11 -0
- package/dist/tests/fourslash/hover.typedDict.get.fourslash.js.map +1 -1
- package/dist/tests/harness/fourslash/fourSlashParser.js +14 -4
- package/dist/tests/harness/fourslash/fourSlashParser.js.map +1 -1
- package/dist/tests/languageServer.test.js +15 -0
- package/dist/tests/languageServer.test.js.map +1 -1
- package/dist/tests/lsp/languageServer.js +6 -6
- package/dist/tests/lsp/languageServer.js.map +1 -1
- package/dist/tests/mypyPrimerAnalysis.test.js +133 -0
- package/dist/tests/mypyPrimerAnalysis.test.js.map +1 -1
- package/dist/tests/overloadResultController.test.js +379 -1
- package/dist/tests/overloadResultController.test.js.map +1 -1
- package/dist/tests/signatureHelp.test.js +34 -0
- package/dist/tests/signatureHelp.test.js.map +1 -1
- package/dist/tests/sourceEnumeratorSymlink.test.js +98 -13
- package/dist/tests/sourceEnumeratorSymlink.test.js.map +1 -1
- package/dist/tests/sourceMapperUtils.test.js +143 -0
- package/dist/tests/sourceMapperUtils.test.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +22 -3
- package/dist/tests/typeEvaluator1.test.js.map +1 -1
- package/dist/tests/typeEvaluator2.test.js +54 -1
- package/dist/tests/typeEvaluator2.test.js.map +1 -1
- package/dist/tests/typeEvaluator4.test.js +10 -3
- package/dist/tests/typeEvaluator4.test.js.map +1 -1
- package/dist/tests/typeEvaluator5.test.js +1 -1
- package/dist/tests/typeEvaluator6.test.js +55 -0
- package/dist/tests/typeEvaluator6.test.js.map +1 -1
- package/dist/tests/typeEvaluator7.test.js +30 -0
- package/dist/tests/typeEvaluator7.test.js.map +1 -1
- package/dist/tests/typeEvaluator8.test.js +1293 -2
- package/dist/tests/typeEvaluator8.test.js.map +1 -1
- package/dist/tests/types.test.js +55 -0
- package/dist/tests/types.test.js.map +1 -1
- package/dist/typeServer/programWrapper.js +8 -2
- package/dist/typeServer/programWrapper.js.map +1 -1
- package/dist/typeServer/server.d.ts +12 -2
- package/dist/typeServer/server.js +97 -0
- package/dist/typeServer/server.js.map +1 -1
- package/package.json +3 -3
|
@@ -43,6 +43,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
43
43
|
};
|
|
44
44
|
})();
|
|
45
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.applyTypeNarrowingCallback = applyTypeNarrowingCallback;
|
|
46
47
|
exports.getTypeNarrowingCallback = getTypeNarrowingCallback;
|
|
47
48
|
exports.getIsInstanceClassTypes = getIsInstanceClassTypes;
|
|
48
49
|
exports.narrowTypeForInstanceOrSubclass = narrowTypeForInstanceOrSubclass;
|
|
@@ -66,6 +67,23 @@ const symbol_1 = require("./symbol");
|
|
|
66
67
|
const typedDicts_1 = require("./typedDicts");
|
|
67
68
|
const types_1 = require("./types");
|
|
68
69
|
const typeUtils_1 = require("./typeUtils");
|
|
70
|
+
function applyTypeNarrowingCallback(callback, type) {
|
|
71
|
+
const result = callback(type);
|
|
72
|
+
const baseType = (0, types_1.getInferredTupleLiteralBase)(type);
|
|
73
|
+
if (baseType === type) {
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
// Narrow both views at the flow boundary, not recursively within a guard.
|
|
77
|
+
// Independently established literals must survive mutable inference too.
|
|
78
|
+
const baseResult = callback(baseType);
|
|
79
|
+
if (!result && !baseResult) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
type: (0, types_1.retainInferredTupleLiterals)(result?.type ?? type, (0, types_1.getInferredTupleLiteralBase)(baseResult?.type ?? baseType)),
|
|
84
|
+
isIncomplete: !!result?.isIncomplete || !!baseResult?.isIncomplete,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
69
87
|
// Given a reference expression and a test expression, returns a callback that
|
|
70
88
|
// can be used to narrow the type described by the reference expression.
|
|
71
89
|
// If the specified flow node is not associated with the test expression,
|
|
@@ -135,37 +153,77 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
|
135
153
|
};
|
|
136
154
|
}
|
|
137
155
|
}
|
|
138
|
-
// Look for "type(X) is Y", "type(X) is not Y", "type(X) == Y" or "type(X) != Y"
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
156
|
+
// Look for "type(X) is Y", "type(X) is not Y", "type(X) == Y" or "type(X) != Y",
|
|
157
|
+
// as well as reverse forms "Y is type(X)", "Y is not type(X)", "Y == type(X)", "Y != type(X)".
|
|
158
|
+
let typeCallNode;
|
|
159
|
+
let otherExpr;
|
|
160
|
+
const isTypeCall = (expr, referenceExpr) => expr.nodeType === 9 /* ParseNodeType.Call */ &&
|
|
161
|
+
expr.d.args.length === 1 &&
|
|
162
|
+
expr.d.args[0].d.argCategory === 0 /* ArgCategory.Simple */ &&
|
|
163
|
+
(!referenceExpr ||
|
|
164
|
+
isMatchingExpressionOrWalrusRhs(evaluator, referenceExpr, expr.d.args[0].d.valueExpr)) &&
|
|
165
|
+
isTypeCallBase(evaluator.getTypeOfExpression(expr.d.leftExpr, 2 /* EvalFlags.CallBaseDefaults */).type);
|
|
166
|
+
// Either operand may be the call; pick the one whose argument matches the reference.
|
|
167
|
+
if (isTypeCall(testExpression.d.leftExpr, reference)) {
|
|
168
|
+
typeCallNode = testExpression.d.leftExpr;
|
|
169
|
+
otherExpr = testExpression.d.rightExpr;
|
|
170
|
+
}
|
|
171
|
+
else if (isTypeCall(testExpression.d.rightExpr, reference)) {
|
|
172
|
+
typeCallNode = testExpression.d.rightExpr;
|
|
173
|
+
otherExpr = testExpression.d.leftExpr;
|
|
174
|
+
}
|
|
175
|
+
if (typeCallNode && otherExpr) {
|
|
176
|
+
const otherResult = evaluator.getTypeOfExpression(otherExpr);
|
|
177
|
+
const classTypes = [];
|
|
178
|
+
let isClassType = true;
|
|
179
|
+
let classTypeVar;
|
|
180
|
+
if ((0, types_1.isTypeVar)(otherResult.type) && types_1.TypeBase.isInstantiable(otherResult.type)) {
|
|
181
|
+
classTypeVar = (0, typeUtils_1.convertToInstance)(otherResult.type);
|
|
182
|
+
}
|
|
183
|
+
else if ((0, types_1.isClassInstance)(otherResult.type) &&
|
|
184
|
+
types_1.ClassType.isBuiltIn(otherResult.type, 'type') &&
|
|
185
|
+
otherResult.type.priv.typeArgs?.length === 1 &&
|
|
186
|
+
(0, types_1.isTypeVar)(otherResult.type.priv.typeArgs[0])) {
|
|
187
|
+
classTypeVar = otherResult.type.priv.typeArgs[0];
|
|
188
|
+
}
|
|
189
|
+
evaluator.mapSubtypesExpandTypeVars(otherResult.type, /* options */ undefined, (expandedSubtype) => {
|
|
190
|
+
let instantiable;
|
|
191
|
+
if ((0, types_1.isClass)(expandedSubtype)) {
|
|
192
|
+
if ((0, types_1.isClassInstance)(expandedSubtype) &&
|
|
193
|
+
types_1.ClassType.isBuiltIn(expandedSubtype, 'type') &&
|
|
194
|
+
expandedSubtype.priv.typeArgs &&
|
|
195
|
+
expandedSubtype.priv.typeArgs.length > 0) {
|
|
196
|
+
const extracted = (0, typeUtils_1.convertToInstantiable)(expandedSubtype.priv.typeArgs[0],
|
|
197
|
+
/* includeSubclasses */ true);
|
|
198
|
+
if ((0, types_1.isInstantiableClass)(extracted)) {
|
|
199
|
+
instantiable = extracted;
|
|
166
200
|
}
|
|
167
201
|
}
|
|
202
|
+
else if ((0, types_1.isInstantiableClass)(expandedSubtype)) {
|
|
203
|
+
instantiable = expandedSubtype;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (instantiable) {
|
|
207
|
+
classTypes.push(instantiable);
|
|
168
208
|
}
|
|
209
|
+
else {
|
|
210
|
+
isClassType = false;
|
|
211
|
+
}
|
|
212
|
+
return undefined;
|
|
213
|
+
});
|
|
214
|
+
if (isClassType && classTypes.length > 0) {
|
|
215
|
+
const allowLegacyEquality = !isOrIsNotOperator &&
|
|
216
|
+
typeCallNode === testExpression.d.leftExpr &&
|
|
217
|
+
(((0, types_1.isInstantiableClass)(otherResult.type) &&
|
|
218
|
+
!otherResult.type.priv.includeSubclasses &&
|
|
219
|
+
!otherResult.type.priv.isTypeArgExplicit) ||
|
|
220
|
+
isTypeCall(otherExpr));
|
|
221
|
+
return (type) => {
|
|
222
|
+
return {
|
|
223
|
+
type: narrowTypeForTypeIs(evaluator, type, classTypes, adjIsPositiveTest, isOrIsNotOperator, classTypeVar, allowLegacyEquality),
|
|
224
|
+
isIncomplete: !!otherResult.isIncomplete,
|
|
225
|
+
};
|
|
226
|
+
};
|
|
169
227
|
}
|
|
170
228
|
}
|
|
171
229
|
if (isOrIsNotOperator) {
|
|
@@ -428,9 +486,12 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
|
428
486
|
const isInstanceCheck = types_1.FunctionType.isBuiltIn(callType, 'isinstance');
|
|
429
487
|
const arg1TypeResult = evaluator.getTypeOfExpression(arg1Expr, 536871546 /* EvalFlags.IsInstanceArgDefaults */);
|
|
430
488
|
const arg1Type = arg1TypeResult.type;
|
|
431
|
-
const
|
|
489
|
+
const classTypeInfo = getIsInstanceClassTypes(evaluator, arg1Type, arg1Expr);
|
|
432
490
|
const isIncomplete = !!callTypeResult.isIncomplete || !!arg1TypeResult.isIncomplete;
|
|
433
|
-
if (
|
|
491
|
+
if (classTypeInfo) {
|
|
492
|
+
const classTypeList = isPositiveTest
|
|
493
|
+
? classTypeInfo.classTypes
|
|
494
|
+
: classTypeInfo.negativeClassTypes;
|
|
434
495
|
return (type) => {
|
|
435
496
|
return {
|
|
436
497
|
type: narrowTypeForInstanceOrSubclass(evaluator, type, classTypeList, isInstanceCheck,
|
|
@@ -956,23 +1017,40 @@ function narrowTypeForIsEllipsis(evaluator, node, type, isPositiveTest) {
|
|
|
956
1017
|
}
|
|
957
1018
|
return result;
|
|
958
1019
|
}
|
|
959
|
-
// The "isinstance" and "issubclass" calls
|
|
960
|
-
//
|
|
961
|
-
//
|
|
962
|
-
//
|
|
963
|
-
function getIsInstanceClassTypes(evaluator, argType) {
|
|
1020
|
+
// The "isinstance" and "issubclass" calls accept classes, runtime unions,
|
|
1021
|
+
// and arbitrarily-nested tuples of these. This method extracts possible
|
|
1022
|
+
// classes and guaranteed negative filters,
|
|
1023
|
+
// or undefined if the filter contains a non-class type.
|
|
1024
|
+
function getIsInstanceClassTypes(evaluator, argType, argExpr) {
|
|
964
1025
|
let foundNonClassType = false;
|
|
965
|
-
const
|
|
1026
|
+
const classTypes = [];
|
|
1027
|
+
const negativeClassTypes = [];
|
|
966
1028
|
// Create a helper function that returns a list of class types or
|
|
967
1029
|
// undefined if any of the types are not valid.
|
|
968
|
-
const addClassTypesToList = (types) => {
|
|
1030
|
+
const addClassTypesToList = (types, isAmbiguous, isUnboundedEntry) => {
|
|
969
1031
|
types.forEach((subtype) => {
|
|
970
1032
|
if ((0, types_1.isClass)(subtype)) {
|
|
971
1033
|
subtype = (0, typeUtils_1.specializeWithUnknownTypeArgs)(subtype, evaluator.getTupleClassType());
|
|
972
1034
|
if ((0, types_1.isInstantiableClass)(subtype) && types_1.ClassType.isBuiltIn(subtype, 'Callable')) {
|
|
973
1035
|
subtype = (0, typeUtils_1.convertToInstantiable)((0, typeUtils_1.getUnknownTypeForCallable)());
|
|
974
1036
|
}
|
|
1037
|
+
else if (types_1.TypeBase.isInstance(subtype) && types_1.ClassType.isBuiltIn(subtype, 'type')) {
|
|
1038
|
+
if (subtype.priv.typeArgs && subtype.priv.typeArgs.length > 0) {
|
|
1039
|
+
const typeArg = subtype.priv.typeArgs[0];
|
|
1040
|
+
if ((0, types_1.isAnyOrUnknown)(typeArg)) {
|
|
1041
|
+
foundNonClassType = true;
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
if ((0, types_1.isInstantiableClass)(typeArg)) {
|
|
1045
|
+
subtype = types_1.ClassType.cloneIncludeSubclasses(typeArg);
|
|
1046
|
+
}
|
|
1047
|
+
else if ((0, types_1.isClassInstance)(typeArg)) {
|
|
1048
|
+
subtype = types_1.ClassType.cloneAsInstantiable(typeArg);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
975
1052
|
}
|
|
1053
|
+
let classType;
|
|
976
1054
|
if ((0, types_1.isInstantiableClass)(subtype)) {
|
|
977
1055
|
// If this is a reference to a class that has type promotions (e.g.
|
|
978
1056
|
// float or complex), remove the promotions for purposes of the
|
|
@@ -980,49 +1058,112 @@ function getIsInstanceClassTypes(evaluator, argType) {
|
|
|
980
1058
|
if (!subtype.priv.includeSubclasses && subtype.priv.includePromotions) {
|
|
981
1059
|
subtype = types_1.ClassType.cloneRemoveTypePromotions(subtype);
|
|
982
1060
|
}
|
|
983
|
-
|
|
1061
|
+
classType = subtype;
|
|
984
1062
|
}
|
|
985
1063
|
else if ((0, types_1.isTypeVar)(subtype) && types_1.TypeBase.isInstantiable(subtype)) {
|
|
986
|
-
|
|
1064
|
+
classType = subtype;
|
|
987
1065
|
}
|
|
988
1066
|
else if ((0, typeUtils_1.isNoneTypeClass)(subtype)) {
|
|
989
1067
|
(0, debug_1.assert)((0, types_1.isInstantiableClass)(subtype));
|
|
990
|
-
|
|
1068
|
+
classType = subtype;
|
|
991
1069
|
}
|
|
992
1070
|
else if ((0, types_1.isFunction)(subtype) &&
|
|
993
1071
|
subtype.shared.parameters.length === 2 &&
|
|
994
1072
|
subtype.shared.parameters[0].category === 1 /* ParamCategory.ArgsList */ &&
|
|
995
1073
|
subtype.shared.parameters[1].category === 2 /* ParamCategory.KwargsDict */) {
|
|
996
|
-
|
|
1074
|
+
classType = subtype;
|
|
997
1075
|
}
|
|
998
1076
|
else {
|
|
999
1077
|
foundNonClassType = true;
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
classTypes.push(classType);
|
|
1081
|
+
// Unbounded entries may be absent, and alternative class objects
|
|
1082
|
+
// are not all guaranteed to participate in the runtime check.
|
|
1083
|
+
if (!isUnboundedEntry && !isAmbiguous) {
|
|
1084
|
+
negativeClassTypes.push(classType);
|
|
1000
1085
|
}
|
|
1001
1086
|
});
|
|
1002
1087
|
};
|
|
1003
|
-
const addClassTypesRecursive = (type, recursionCount
|
|
1088
|
+
const addClassTypesRecursive = (type, isAmbiguous, isUnboundedEntry, recursionCount, expression) => {
|
|
1004
1089
|
if (recursionCount > types_1.maxTypeRecursionCount) {
|
|
1005
1090
|
return;
|
|
1006
1091
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1092
|
+
// A runtime union checks both operands, but either operand can itself
|
|
1093
|
+
// be an alternative class object. Keep their certainty separate.
|
|
1094
|
+
if ((0, types_1.isUnion)(type) &&
|
|
1095
|
+
expression?.nodeType === 7 /* ParseNodeType.BinaryOperation */ &&
|
|
1096
|
+
expression.d.operator === 6 /* OperatorType.BitwiseOr */) {
|
|
1097
|
+
const leftType = evaluator.getCachedType(expression.d.leftExpr);
|
|
1098
|
+
const rightType = evaluator.getCachedType(expression.d.rightExpr);
|
|
1099
|
+
if (leftType &&
|
|
1100
|
+
rightType &&
|
|
1101
|
+
!(0, operations_1.customMetaclassSupportsMethod)(leftType, '__or__') &&
|
|
1102
|
+
!(0, operations_1.customMetaclassSupportsMethod)(rightType, '__ror__')) {
|
|
1103
|
+
// Match the union evaluator's normalization of None operands to NoneType.
|
|
1104
|
+
const adjustedLeftType = (0, typeUtils_1.isNoneInstance)(leftType)
|
|
1105
|
+
? (0, typeUtils_1.convertToInstantiable)(evaluator.getNoneType())
|
|
1106
|
+
: leftType;
|
|
1107
|
+
const adjustedRightType = (0, typeUtils_1.isNoneInstance)(rightType)
|
|
1108
|
+
? (0, typeUtils_1.convertToInstantiable)(evaluator.getNoneType())
|
|
1109
|
+
: rightType;
|
|
1110
|
+
addClassTypesRecursive(adjustedLeftType, isAmbiguous, isUnboundedEntry, recursionCount, expression.d.leftExpr);
|
|
1111
|
+
addClassTypesRecursive(adjustedRightType, isAmbiguous, isUnboundedEntry, recursionCount, expression.d.rightExpr);
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
const isRuntimeUnion = type.props?.specialForm && types_1.ClassType.isBuiltIn(type.props.specialForm, 'UnionType');
|
|
1116
|
+
const isAmbiguousType = isAmbiguous || ((0, types_1.isUnion)(type) && !isRuntimeUnion);
|
|
1117
|
+
(0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
|
|
1118
|
+
if ((0, types_1.isClassInstance)(subtype) && (0, typeUtils_1.isTupleClass)(subtype)) {
|
|
1119
|
+
if (subtype.priv.tupleTypeArgs) {
|
|
1120
|
+
let entryExpressions;
|
|
1121
|
+
if (expression?.nodeType === 52 /* ParseNodeType.Tuple */) {
|
|
1122
|
+
const expressions = [];
|
|
1123
|
+
expression.d.items.forEach((item) => {
|
|
1124
|
+
if (item.nodeType !== 56 /* ParseNodeType.Unpack */) {
|
|
1125
|
+
expressions.push(item);
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
const unpackedType = evaluator.getCachedType(item.d.expr);
|
|
1129
|
+
const entryCount = unpackedType && (0, types_1.isClassInstance)(unpackedType) && (0, typeUtils_1.isTupleClass)(unpackedType)
|
|
1130
|
+
? unpackedType.priv.tupleTypeArgs?.length ?? 1
|
|
1131
|
+
: 1;
|
|
1132
|
+
for (let index = 0; index < entryCount; index++) {
|
|
1133
|
+
expressions.push(undefined);
|
|
1134
|
+
}
|
|
1135
|
+
});
|
|
1136
|
+
if (expressions.length === subtype.priv.tupleTypeArgs.length) {
|
|
1137
|
+
entryExpressions = expressions;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
subtype.priv.tupleTypeArgs.forEach((tupleEntry, index) => {
|
|
1141
|
+
addClassTypesRecursive(tupleEntry.type, isAmbiguousType, isUnboundedEntry || tupleEntry.isUnbounded, recursionCount + 1, entryExpressions?.[index]);
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1012
1144
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
});
|
|
1018
|
-
}
|
|
1145
|
+
else {
|
|
1146
|
+
addClassTypesToList([subtype], isAmbiguousType, isUnboundedEntry);
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1019
1149
|
};
|
|
1020
|
-
(
|
|
1021
|
-
|
|
1022
|
-
});
|
|
1023
|
-
return foundNonClassType ? undefined : classTypeList;
|
|
1150
|
+
addClassTypesRecursive(argType, /* isAmbiguous */ false, /* isUnboundedEntry */ false, 0, argExpr);
|
|
1151
|
+
return foundNonClassType ? undefined : { classTypes, negativeClassTypes };
|
|
1024
1152
|
}
|
|
1025
1153
|
function narrowTypeForInstanceOrSubclass(evaluator, type, filterTypes, isInstanceCheck, isTypeIsCheck, isPositiveTest, errorNode, nodeInfo) {
|
|
1154
|
+
if (!isInstanceCheck && !isTypeIsCheck && !isPositiveTest) {
|
|
1155
|
+
// A custom subclass check can reject even the exact same final class.
|
|
1156
|
+
// Preserve the existing narrowing policy for non-final classes, including ABCs.
|
|
1157
|
+
filterTypes = filterTypes.filter((filterType) => {
|
|
1158
|
+
const concreteFilterType = evaluator.makeTopLevelTypeVarsConcrete(filterType);
|
|
1159
|
+
return (!(0, types_1.isInstantiableClass)(concreteFilterType) ||
|
|
1160
|
+
!types_1.ClassType.isFinal(concreteFilterType) ||
|
|
1161
|
+
!(0, operations_1.customMetaclassSupportsMethod)(concreteFilterType, '__subclasscheck__'));
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
if (!isPositiveTest && filterTypes.length === 0) {
|
|
1165
|
+
return type;
|
|
1166
|
+
}
|
|
1026
1167
|
// First try with intersection types disallowed.
|
|
1027
1168
|
const narrowedType = narrowTypeForInstanceOrSubclassInternal(evaluator, type, filterTypes, isInstanceCheck, isTypeIsCheck, isPositiveTest,
|
|
1028
1169
|
/* allowIntersections */ false, errorNode, nodeInfo);
|
|
@@ -1162,8 +1303,10 @@ function narrowTypeForInstance(evaluator, type, filterTypes, isTypeIsCheck, isPo
|
|
|
1162
1303
|
// note this case specially so we don't do any narrowing, which
|
|
1163
1304
|
// will generate false positives.
|
|
1164
1305
|
if (filterIsSuperclass) {
|
|
1165
|
-
if (!isTypeIsCheck &&
|
|
1166
|
-
|
|
1306
|
+
if (!isTypeIsCheck &&
|
|
1307
|
+
concreteFilterType.priv.includeSubclasses &&
|
|
1308
|
+
!types_1.ClassType.isFinal(concreteFilterType)) {
|
|
1309
|
+
// If the filter type includes subclasses and is not final, we can't eliminate
|
|
1167
1310
|
// this type in the negative direction. We'll relax this for
|
|
1168
1311
|
// TypeIs checks.
|
|
1169
1312
|
isClassRelationshipIndeterminate = true;
|
|
@@ -1607,8 +1750,14 @@ function narrowTypeForContainerType(evaluator, referenceType, containerType, isP
|
|
|
1607
1750
|
!containerType.priv.tupleTypeArgs) {
|
|
1608
1751
|
return referenceType;
|
|
1609
1752
|
}
|
|
1610
|
-
// Determine which tuple types can be eliminated. Only "None"
|
|
1611
|
-
// literal types can be handled here.
|
|
1753
|
+
// Determine which tuple types can be eliminated. Only "None",
|
|
1754
|
+
// literal types, and final instantiable classes can be handled here.
|
|
1755
|
+
// Non-final instantiable classes (type[A]) cannot be eliminated in negative
|
|
1756
|
+
// tests because a subclass SubA(A) reaches the negative branch at runtime
|
|
1757
|
+
// (since SubA != A). Generic classes are also excluded because a
|
|
1758
|
+
// specialized class object like Box[int] is not the same runtime object
|
|
1759
|
+
// as Box. Classes that define or inherit __class_getitem__ are excluded
|
|
1760
|
+
// for the same reason.
|
|
1612
1761
|
const typesToEliminate = [];
|
|
1613
1762
|
containerType.priv.tupleTypeArgs.forEach((tupleEntry) => {
|
|
1614
1763
|
if (!tupleEntry.isUnbounded) {
|
|
@@ -1618,14 +1767,23 @@ function narrowTypeForContainerType(evaluator, referenceType, containerType, isP
|
|
|
1618
1767
|
else if ((0, types_1.isClassInstance)(tupleEntry.type) && (0, typeUtils_1.isLiteralType)(tupleEntry.type)) {
|
|
1619
1768
|
typesToEliminate.push(tupleEntry.type);
|
|
1620
1769
|
}
|
|
1770
|
+
else if ((0, types_1.isInstantiableClass)(tupleEntry.type) &&
|
|
1771
|
+
types_1.ClassType.isFinal(tupleEntry.type) &&
|
|
1772
|
+
tupleEntry.type.shared.typeParams.length === 0 &&
|
|
1773
|
+
!(0, typeUtils_1.lookUpClassMember)(tupleEntry.type, '__class_getitem__')) {
|
|
1774
|
+
typesToEliminate.push(tupleEntry.type);
|
|
1775
|
+
}
|
|
1621
1776
|
}
|
|
1622
1777
|
});
|
|
1623
1778
|
if (typesToEliminate.length === 0) {
|
|
1624
1779
|
return referenceType;
|
|
1625
1780
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1781
|
+
const canNarrowLiterals = typesToEliminate.some(types_1.isClassInstance);
|
|
1782
|
+
return (0, typeUtils_1.mapSubtypes)(referenceType, (unexpandedSubtype) => {
|
|
1783
|
+
const referenceSubtype = evaluator.makeTopLevelTypeVarsConcrete(unexpandedSubtype);
|
|
1784
|
+
if (canNarrowLiterals &&
|
|
1785
|
+
(0, types_1.isClassInstance)(referenceSubtype) &&
|
|
1786
|
+
referenceSubtype.priv.literalValue === undefined) {
|
|
1629
1787
|
// If we're able to enumerate all possible literal values
|
|
1630
1788
|
// (for bool or enum), we can eliminate all others in a negative test.
|
|
1631
1789
|
const allLiteralTypes = enumerateLiteralsForType(evaluator, referenceSubtype);
|
|
@@ -1636,7 +1794,7 @@ function narrowTypeForContainerType(evaluator, referenceType, containerType, isP
|
|
|
1636
1794
|
if (typesToEliminate.some((t) => (0, types_1.isTypeSame)(t, referenceSubtype))) {
|
|
1637
1795
|
return undefined;
|
|
1638
1796
|
}
|
|
1639
|
-
return
|
|
1797
|
+
return unexpandedSubtype;
|
|
1640
1798
|
});
|
|
1641
1799
|
}
|
|
1642
1800
|
function getElementTypeForContainerNarrowing(containerType) {
|
|
@@ -1906,36 +2064,172 @@ function narrowTypeForDiscriminatedFieldNoneComparison(evaluator, referenceType,
|
|
|
1906
2064
|
return subtype;
|
|
1907
2065
|
});
|
|
1908
2066
|
}
|
|
2067
|
+
function isTypeCallBase(callType) {
|
|
2068
|
+
return (0, types_1.isInstantiableClass)(callType) && types_1.ClassType.isBuiltIn(callType, 'type');
|
|
2069
|
+
}
|
|
2070
|
+
// Determines whether two classes have incompatible disjoint bases (PEP 800),
|
|
2071
|
+
// in which case no class can derive from both of them.
|
|
2072
|
+
function areDisjointBasesIncompatible(classType1, classType2) {
|
|
2073
|
+
const base1 = types_1.ClassType.getDisjointBase(classType1);
|
|
2074
|
+
const base2 = types_1.ClassType.getDisjointBase(classType2);
|
|
2075
|
+
return !!base1 && !!base2 && !types_1.ClassType.getMostDerivedDisjointBase([base1, base2]);
|
|
2076
|
+
}
|
|
2077
|
+
// Fill gradual holes without replacing facts inferred from the guarded value.
|
|
2078
|
+
function fillTypeGuardGradualArgs(input, hint, results, recursionCount = 0) {
|
|
2079
|
+
if (!hint || input === hint || recursionCount > types_1.maxTypeRecursionCount) {
|
|
2080
|
+
return input;
|
|
2081
|
+
}
|
|
2082
|
+
if ((0, types_1.isAnyOrUnknown)(input)) {
|
|
2083
|
+
return (0, types_1.isAnyOrUnknown)(hint) ? ((0, types_1.isAny)(hint) ? hint : input) : hint;
|
|
2084
|
+
}
|
|
2085
|
+
if (!(0, types_1.isClass)(input) || !(0, types_1.isClass)(hint) || !types_1.ClassType.isSameGenericClass(input, hint)) {
|
|
2086
|
+
return input;
|
|
2087
|
+
}
|
|
2088
|
+
let inputResults = results.get(input);
|
|
2089
|
+
const cachedResult = inputResults?.get(hint);
|
|
2090
|
+
if (cachedResult !== undefined) {
|
|
2091
|
+
return cachedResult;
|
|
2092
|
+
}
|
|
2093
|
+
if (!inputResults) {
|
|
2094
|
+
inputResults = new Map();
|
|
2095
|
+
results.set(input, inputResults);
|
|
2096
|
+
}
|
|
2097
|
+
// Bound recursive aliases and reuse shared argument graphs within this narrowing operation.
|
|
2098
|
+
inputResults.set(hint, input);
|
|
2099
|
+
const inputTuple = input.priv.tupleTypeArgs;
|
|
2100
|
+
const hintTuple = hint.priv.tupleTypeArgs;
|
|
2101
|
+
if (inputTuple || hintTuple) {
|
|
2102
|
+
if (!inputTuple ||
|
|
2103
|
+
!hintTuple ||
|
|
2104
|
+
inputTuple.length !== hintTuple.length ||
|
|
2105
|
+
inputTuple.some((arg, index) => arg.isUnbounded !== hintTuple[index].isUnbounded ||
|
|
2106
|
+
!!arg.isOptional !== !!hintTuple[index].isOptional)) {
|
|
2107
|
+
return input;
|
|
2108
|
+
}
|
|
2109
|
+
const tupleArgs = inputTuple.map((arg, index) => ({
|
|
2110
|
+
...arg,
|
|
2111
|
+
type: fillTypeGuardGradualArgs(arg.type, hintTuple[index].type, results, recursionCount + 1),
|
|
2112
|
+
}));
|
|
2113
|
+
const result = tupleArgs.every((arg, index) => arg.type === inputTuple[index].type)
|
|
2114
|
+
? input
|
|
2115
|
+
: (0, typeUtils_1.specializeTupleClass)(input, tupleArgs, input.priv.isTypeArgExplicit, input.priv.isUnpacked);
|
|
2116
|
+
inputResults.set(hint, result);
|
|
2117
|
+
return result;
|
|
2118
|
+
}
|
|
2119
|
+
const inputArgs = input.priv.typeArgs;
|
|
2120
|
+
const hintArgs = hint.priv.typeArgs;
|
|
2121
|
+
if (!inputArgs || !hintArgs || inputArgs.length !== hintArgs.length) {
|
|
2122
|
+
return input;
|
|
2123
|
+
}
|
|
2124
|
+
const typeArgs = inputArgs.map((arg, index) => fillTypeGuardGradualArgs(arg, hintArgs[index], results, recursionCount + 1));
|
|
2125
|
+
const result = typeArgs.every((arg, index) => arg === inputArgs[index])
|
|
2126
|
+
? input
|
|
2127
|
+
: types_1.ClassType.specialize(input, typeArgs, input.priv.isTypeArgExplicit);
|
|
2128
|
+
inputResults.set(hint, result);
|
|
2129
|
+
return result;
|
|
2130
|
+
}
|
|
1909
2131
|
// Attempts to narrow a type based on a "type(x) is y" or "type(x) is not y" check.
|
|
1910
|
-
function narrowTypeForTypeIs(evaluator, type, classTypes, isPositiveTest) {
|
|
2132
|
+
function narrowTypeForTypeIs(evaluator, type, classTypes, isPositiveTest, isIsOperator, classTypeVar, allowLegacyEquality) {
|
|
2133
|
+
const metaclassEqualityResults = isIsOperator ? undefined : new Map();
|
|
2134
|
+
const hasEqualitySemantics = allowLegacyEquality
|
|
2135
|
+
? hasDeclaredIdentityEqualitySemantics
|
|
2136
|
+
: hasIdentityEqualitySemantics;
|
|
2137
|
+
if (metaclassEqualityResults &&
|
|
2138
|
+
classTypes.some((classType) => !hasEqualitySemantics(classType, metaclassEqualityResults))) {
|
|
2139
|
+
return type;
|
|
2140
|
+
}
|
|
1911
2141
|
// We currently don't support narrowing in the negative direction
|
|
1912
2142
|
// when there are more than one class types.
|
|
1913
2143
|
if (!isPositiveTest && classTypes.length > 1) {
|
|
1914
2144
|
return type;
|
|
1915
2145
|
}
|
|
2146
|
+
// Retain the TypeVar rather than its expanded constraints so assignments and loop joins preserve correlation.
|
|
2147
|
+
if (isIsOperator && isPositiveTest && classTypeVar && (0, types_1.isAnyOrUnknown)(type)) {
|
|
2148
|
+
return classTypeVar;
|
|
2149
|
+
}
|
|
2150
|
+
let gradualArgResults;
|
|
1916
2151
|
const typesToCombine = classTypes.map((classType) => {
|
|
1917
2152
|
return evaluator.mapSubtypesExpandTypeVars(type,
|
|
1918
2153
|
/* options */ undefined, (subtype, unexpandedSubtype) => {
|
|
1919
2154
|
if ((0, types_1.isClassInstance)(subtype)) {
|
|
1920
|
-
const
|
|
2155
|
+
const isLiteral = subtype.priv.literalValue !== undefined;
|
|
2156
|
+
const instantiableSubtype = isLiteral
|
|
2157
|
+
? types_1.ClassType.cloneIncludeSubclasses(types_1.ClassType.cloneAsInstantiable(types_1.ClassType.cloneWithLiteral(subtype, undefined)),
|
|
2158
|
+
/* includeSubclasses */ false)
|
|
2159
|
+
: types_1.ClassType.cloneAsInstantiable(subtype);
|
|
2160
|
+
if (metaclassEqualityResults &&
|
|
2161
|
+
!hasEqualitySemantics(instantiableSubtype, metaclassEqualityResults)) {
|
|
2162
|
+
return unexpandedSubtype;
|
|
2163
|
+
}
|
|
2164
|
+
const matches = types_1.ClassType.isDerivedFrom(classType, instantiableSubtype);
|
|
2165
|
+
// A literal has an exact runtime class, not an arbitrary subclass.
|
|
2166
|
+
if (matches && isLiteral && !types_1.ClassType.isSameGenericClass(instantiableSubtype, classType)) {
|
|
2167
|
+
return isPositiveTest ? undefined : subtype;
|
|
2168
|
+
}
|
|
1921
2169
|
if (isPositiveTest) {
|
|
1922
2170
|
if (matches) {
|
|
1923
|
-
if (types_1.ClassType.isSameGenericClass(
|
|
2171
|
+
if (types_1.ClassType.isSameGenericClass(instantiableSubtype, classType)) {
|
|
1924
2172
|
return (0, typeUtils_1.addConditionToType)(subtype, (0, typeUtils_1.getTypeCondition)(classType));
|
|
1925
2173
|
}
|
|
1926
|
-
|
|
2174
|
+
let narrowedClass = classType;
|
|
2175
|
+
if (subtype.priv.typeArgs || subtype.priv.tupleTypeArgs) {
|
|
2176
|
+
if (classType.shared.typeParams.length > 0) {
|
|
2177
|
+
if ((0, typeUtils_1.containsAnyRecursive)(classType) ||
|
|
2178
|
+
!evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(classType))) {
|
|
2179
|
+
const genericClass = (0, typeUtils_1.selfSpecializeClass)(types_1.ClassType.specialize(classType, undefined));
|
|
2180
|
+
const constraints = new constraintTracker_1.ConstraintTracker();
|
|
2181
|
+
if (!evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(genericClass), undefined, constraints, 2 /* AssignTypeFlags.Contravariant */ |
|
|
2182
|
+
2048 /* AssignTypeFlags.PopulateExpectedType */ |
|
|
2183
|
+
4096 /* AssignTypeFlags.SkipPopulateUnknownExpectedType */)) {
|
|
2184
|
+
return (0, typeUtils_1.addConditionToType)(subtype, (0, typeUtils_1.getTypeCondition)(classType));
|
|
2185
|
+
}
|
|
2186
|
+
const specializedClass = evaluator.solveAndApplyConstraints(genericClass, constraints, {
|
|
2187
|
+
replaceUnsolved: {
|
|
2188
|
+
scopeIds: (0, typeUtils_1.getTypeVarScopeIds)(classType),
|
|
2189
|
+
useUnknown: true,
|
|
2190
|
+
tupleClassType: evaluator.getTupleClassType(),
|
|
2191
|
+
},
|
|
2192
|
+
});
|
|
2193
|
+
if (!(0, types_1.isInstantiableClass)(specializedClass)) {
|
|
2194
|
+
return (0, typeUtils_1.addConditionToType)(subtype, (0, typeUtils_1.getTypeCondition)(classType));
|
|
2195
|
+
}
|
|
2196
|
+
const results = (gradualArgResults ?? (gradualArgResults = new Map()));
|
|
2197
|
+
narrowedClass = types_1.ClassType.specialize(specializedClass, specializedClass.priv.typeArgs?.map((arg, index) => fillTypeGuardGradualArgs(arg, classType.priv.typeArgs?.[index], results)));
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
else if (!evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(classType))) {
|
|
2201
|
+
return classType.priv.includeSubclasses && !types_1.ClassType.isFinal(classType)
|
|
2202
|
+
? (0, typeUtils_1.addConditionToType)(subtype, (0, typeUtils_1.getTypeCondition)(classType))
|
|
2203
|
+
: undefined;
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
return (0, typeUtils_1.addConditionToType)(types_1.ClassType.cloneAsInstance(narrowedClass), subtype.props?.condition);
|
|
1927
2207
|
}
|
|
1928
2208
|
if (!classType.priv.includeSubclasses) {
|
|
2209
|
+
if (evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(classType))) {
|
|
2210
|
+
return (0, typeUtils_1.addConditionToType)(types_1.ClassType.cloneAsInstance(classType), (0, typeUtils_1.getTypeCondition)(subtype));
|
|
2211
|
+
}
|
|
2212
|
+
return undefined;
|
|
2213
|
+
}
|
|
2214
|
+
// A subclass of both the subtype and the class could satisfy the
|
|
2215
|
+
// comparison, so eliminate the subtype only if no such class can exist.
|
|
2216
|
+
if ((types_1.ClassType.isFinal(classType) ||
|
|
2217
|
+
isLiteral ||
|
|
2218
|
+
types_1.ClassType.isFinal(instantiableSubtype) ||
|
|
2219
|
+
areDisjointBasesIncompatible(instantiableSubtype, classType)) &&
|
|
2220
|
+
!evaluator.assignType(types_1.ClassType.cloneAsInstance(classType), subtype) &&
|
|
2221
|
+
!evaluator.assignType(subtype, types_1.ClassType.cloneAsInstance(classType))) {
|
|
1929
2222
|
return undefined;
|
|
1930
2223
|
}
|
|
1931
2224
|
if (!(0, types_1.isTypeVar)(unexpandedSubtype) || !types_1.TypeVarType.isSelf(unexpandedSubtype)) {
|
|
1932
2225
|
return (0, typeUtils_1.addConditionToType)(subtype, classType.props?.condition);
|
|
1933
2226
|
}
|
|
1934
2227
|
}
|
|
1935
|
-
|
|
1936
|
-
|
|
2228
|
+
// A final class has no subclasses, so it is treated as an exact class.
|
|
2229
|
+
if (!classType.priv.includeSubclasses || types_1.ClassType.isFinal(classType)) {
|
|
2230
|
+
// If the runtime class is exact and it matches, then
|
|
1937
2231
|
// we can eliminate it in the negative case.
|
|
1938
|
-
if (matches && types_1.ClassType.isFinal(
|
|
2232
|
+
if (matches && (isLiteral || types_1.ClassType.isFinal(instantiableSubtype))) {
|
|
1939
2233
|
return undefined;
|
|
1940
2234
|
}
|
|
1941
2235
|
// We can't eliminate the subtype in the negative
|
|
@@ -1945,6 +2239,9 @@ function narrowTypeForTypeIs(evaluator, type, classTypes, isPositiveTest) {
|
|
|
1945
2239
|
}
|
|
1946
2240
|
}
|
|
1947
2241
|
if ((0, types_1.isAnyOrUnknown)(subtype)) {
|
|
2242
|
+
if (metaclassEqualityResults && !allowLegacyEquality) {
|
|
2243
|
+
return subtype;
|
|
2244
|
+
}
|
|
1948
2245
|
return isPositiveTest
|
|
1949
2246
|
? types_1.ClassType.cloneAsInstance((0, typeUtils_1.addConditionToType)(classType, (0, typeUtils_1.getTypeCondition)(subtype)))
|
|
1950
2247
|
: subtype;
|
|
@@ -1969,6 +2266,10 @@ function hasIdentityEqualitySemantics(classType, metaclassEqualityResults) {
|
|
|
1969
2266
|
if (classType.shared.typeParams.length > 0) {
|
|
1970
2267
|
return false;
|
|
1971
2268
|
}
|
|
2269
|
+
return hasDeclaredIdentityEqualitySemantics(classType, metaclassEqualityResults);
|
|
2270
|
+
}
|
|
2271
|
+
// Legacy forward type(x) equality guards check declared metaclasses without closing subclass hierarchies.
|
|
2272
|
+
function hasDeclaredIdentityEqualitySemantics(classType, metaclassEqualityResults) {
|
|
1972
2273
|
const metaclass = classType.shared.effectiveMetaclass;
|
|
1973
2274
|
if (!metaclass ||
|
|
1974
2275
|
!(0, types_1.isInstantiableClass)(metaclass) ||
|