@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.
- package/dist/analyzer/binder.js +9 -3
- package/dist/analyzer/binder.js.map +1 -1
- package/dist/analyzer/constructorTransform.js +12 -0
- package/dist/analyzer/constructorTransform.js.map +1 -1
- package/dist/analyzer/constructors.d.ts +1 -1
- package/dist/analyzer/constructors.js +1 -1
- package/dist/analyzer/constructors.js.map +1 -1
- package/dist/analyzer/decorators.d.ts +1 -1
- package/dist/analyzer/decorators.js.map +1 -1
- package/dist/analyzer/functionTransform.d.ts +5 -0
- package/dist/analyzer/functionTransform.js +6 -3
- package/dist/analyzer/functionTransform.js.map +1 -1
- package/dist/analyzer/missingBindingMetadata.d.ts +6 -0
- package/dist/analyzer/missingBindingMetadata.js +22 -0
- package/dist/analyzer/missingBindingMetadata.js.map +1 -0
- package/dist/analyzer/namedTuples.d.ts +4 -1
- package/dist/analyzer/namedTuples.js +1 -0
- package/dist/analyzer/namedTuples.js.map +1 -1
- package/dist/analyzer/patternMatching.d.ts +5 -1
- package/dist/analyzer/patternMatching.js +3 -0
- package/dist/analyzer/patternMatching.js.map +1 -1
- package/dist/analyzer/program.d.ts +3 -0
- package/dist/analyzer/program.js +71 -1
- package/dist/analyzer/program.js.map +1 -1
- package/dist/analyzer/tuples.d.ts +1 -1
- package/dist/analyzer/tuples.js.map +1 -1
- package/dist/analyzer/typeCacheUtils.d.ts +1 -0
- package/dist/analyzer/typeCacheUtils.js +10 -0
- package/dist/analyzer/typeCacheUtils.js.map +1 -1
- package/dist/analyzer/typeEvaluator/boundMethodSpecialization.d.ts +15 -0
- package/dist/analyzer/typeEvaluator/boundMethodSpecialization.js +98 -0
- package/dist/analyzer/typeEvaluator/boundMethodSpecialization.js.map +1 -0
- package/dist/analyzer/typeEvaluator/classConstruction.d.ts +25 -0
- package/dist/analyzer/typeEvaluator/classConstruction.js +251 -0
- package/dist/analyzer/typeEvaluator/classConstruction.js.map +1 -0
- package/dist/analyzer/typeEvaluator/collectionInference.d.ts +41 -0
- package/dist/analyzer/typeEvaluator/collectionInference.js +695 -0
- package/dist/analyzer/typeEvaluator/collectionInference.js.map +1 -0
- package/dist/analyzer/typeEvaluator/diagnostics.d.ts +33 -0
- package/dist/analyzer/typeEvaluator/diagnostics.js +198 -0
- package/dist/analyzer/typeEvaluator/diagnostics.js.map +1 -0
- package/dist/analyzer/typeEvaluator/evaluatorCore.d.ts +80 -0
- package/dist/analyzer/typeEvaluator/evaluatorCore.js +1126 -0
- package/dist/analyzer/typeEvaluator/evaluatorCore.js.map +1 -0
- package/dist/analyzer/typeEvaluator/evaluatorNarrowing.d.ts +17 -0
- package/dist/analyzer/typeEvaluator/evaluatorNarrowing.js +370 -0
- package/dist/analyzer/typeEvaluator/evaluatorNarrowing.js.map +1 -0
- package/dist/analyzer/typeEvaluator/expressionEvaluation.d.ts +81 -0
- package/dist/analyzer/typeEvaluator/expressionEvaluation.js +1802 -0
- package/dist/analyzer/typeEvaluator/expressionEvaluation.js.map +1 -0
- package/dist/analyzer/typeEvaluator/flowAnalysis.d.ts +33 -0
- package/dist/analyzer/typeEvaluator/flowAnalysis.js +217 -0
- package/dist/analyzer/typeEvaluator/flowAnalysis.js.map +1 -0
- package/dist/analyzer/typeEvaluator/internals.d.ts +137 -0
- package/dist/analyzer/typeEvaluator/internals.js +10 -0
- package/dist/analyzer/typeEvaluator/internals.js.map +1 -0
- package/dist/analyzer/typeEvaluator/literalTypes.d.ts +3 -0
- package/dist/analyzer/typeEvaluator/literalTypes.js +52 -0
- package/dist/analyzer/typeEvaluator/literalTypes.js.map +1 -0
- package/dist/analyzer/typeEvaluator/memberResolution.d.ts +79 -0
- package/dist/analyzer/typeEvaluator/memberResolution.js +1007 -0
- package/dist/analyzer/typeEvaluator/memberResolution.js.map +1 -0
- package/dist/analyzer/typeEvaluator/overrideValidation.d.ts +15 -0
- package/dist/analyzer/typeEvaluator/overrideValidation.js +422 -0
- package/dist/analyzer/typeEvaluator/overrideValidation.js.map +1 -0
- package/dist/analyzer/typeEvaluator/returnTypeInference.d.ts +33 -0
- package/dist/analyzer/typeEvaluator/returnTypeInference.js +226 -0
- package/dist/analyzer/typeEvaluator/returnTypeInference.js.map +1 -0
- package/dist/analyzer/typeEvaluator/specialFormCreation.d.ts +39 -0
- package/dist/analyzer/typeEvaluator/specialFormCreation.js +1728 -0
- package/dist/analyzer/typeEvaluator/specialFormCreation.js.map +1 -0
- package/dist/analyzer/typeEvaluator/tupleUnpacking.d.ts +2 -0
- package/dist/analyzer/typeEvaluator/tupleUnpacking.js +36 -0
- package/dist/analyzer/typeEvaluator/tupleUnpacking.js.map +1 -0
- package/dist/analyzer/typeEvaluator/typeCompatibility.d.ts +36 -0
- package/dist/analyzer/typeEvaluator/typeCompatibility.js +1320 -0
- package/dist/analyzer/typeEvaluator/typeCompatibility.js.map +1 -0
- package/dist/analyzer/typeEvaluator/typeGuardNarrowing.d.ts +186 -0
- package/dist/analyzer/typeEvaluator/typeGuardNarrowing.js +1683 -0
- package/dist/analyzer/typeEvaluator/typeGuardNarrowing.js.map +1 -0
- package/dist/analyzer/typeEvaluator/typeVarHandling.d.ts +48 -0
- package/dist/analyzer/typeEvaluator/typeVarHandling.js +756 -0
- package/dist/analyzer/typeEvaluator/typeVarHandling.js.map +1 -0
- package/dist/analyzer/typeEvaluator.d.ts +3 -31
- package/dist/analyzer/typeEvaluator.js +5033 -13761
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeGuards.d.ts +2 -2
- package/dist/analyzer/typeGuards.js +212 -1567
- package/dist/analyzer/typeGuards.js.map +1 -1
- package/dist/analyzer/typeUtils.js +6 -2
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/analyzer/typedDicts.js +111 -0
- package/dist/analyzer/typedDicts.js.map +1 -1
- package/dist/browser/browserConnection.d.ts +12 -0
- package/dist/browser/browserConnection.js +23 -0
- package/dist/browser/browserConnection.js.map +1 -0
- package/dist/browser/browserFileSystem.d.ts +73 -0
- package/dist/browser/browserFileSystem.js +578 -0
- package/dist/browser/browserFileSystem.js.map +1 -0
- package/dist/browser/browserHost.d.ts +4 -0
- package/dist/browser/browserHost.js +10 -0
- package/dist/browser/browserHost.js.map +1 -0
- package/dist/browser/browserProcess.d.ts +1 -0
- package/dist/browser/browserProcess.js +17 -0
- package/dist/browser/browserProcess.js.map +1 -0
- package/dist/browser/browserServer.d.ts +8 -0
- package/dist/browser/browserServer.js +32 -0
- package/dist/browser/browserServer.js.map +1 -0
- package/dist/browser/cancellation/common.d.ts +10 -0
- package/dist/browser/cancellation/common.js +114 -0
- package/dist/browser/cancellation/common.js.map +1 -0
- package/dist/browser/cancellation/objectURLReceiverStrategy.d.ts +5 -0
- package/dist/browser/cancellation/objectURLReceiverStrategy.js +37 -0
- package/dist/browser/cancellation/objectURLReceiverStrategy.js.map +1 -0
- package/dist/browser/cancellation/objectURLSenderStrategy.d.ts +7 -0
- package/dist/browser/cancellation/objectURLSenderStrategy.js +32 -0
- package/dist/browser/cancellation/objectURLSenderStrategy.js.map +1 -0
- package/dist/browser/worker.d.ts +1 -0
- package/dist/browser/worker.js +33 -0
- package/dist/browser/worker.js.map +1 -0
- package/dist/pyrightServer.d.ts +34 -0
- package/dist/pyrightServer.js +239 -0
- package/dist/pyrightServer.js.map +1 -0
- package/dist/server.d.ts +3 -23
- package/dist/server.js +12 -232
- package/dist/server.js.map +1 -1
- package/dist/tests/benchmarks/typeInferenceComparison.d.ts +1 -0
- package/dist/tests/benchmarks/typeInferenceComparison.js +1235 -0
- package/dist/tests/benchmarks/typeInferenceComparison.js.map +1 -0
- package/dist/tests/benchmarks/typeInferencePyrightEntry.d.ts +1 -0
- package/dist/tests/benchmarks/typeInferencePyrightEntry.js +53 -0
- package/dist/tests/benchmarks/typeInferencePyrightEntry.js.map +1 -0
- package/dist/tests/browserCancellation.test.d.ts +1 -0
- package/dist/tests/browserCancellation.test.js +63 -0
- package/dist/tests/browserCancellation.test.js.map +1 -0
- package/dist/tests/browserServer.test.d.ts +1 -0
- package/dist/tests/browserServer.test.js +177 -0
- package/dist/tests/browserServer.test.js.map +1 -0
- package/dist/tests/constraintSolver.test.js +45 -0
- package/dist/tests/constraintSolver.test.js.map +1 -1
- package/dist/tests/mypyPrimerAnalysis.test.js +15 -1
- package/dist/tests/mypyPrimerAnalysis.test.js.map +1 -1
- package/dist/tests/typeCacheUtils.test.js +46 -0
- package/dist/tests/typeCacheUtils.test.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +75 -0
- package/dist/tests/typeEvaluator1.test.js.map +1 -1
- package/dist/tests/typeEvaluator3.test.js +4 -0
- package/dist/tests/typeEvaluator3.test.js.map +1 -1
- package/dist/tests/typeEvaluator4.test.js +32 -0
- package/dist/tests/typeEvaluator4.test.js.map +1 -1
- package/dist/tests/typeEvaluator7.test.js +394 -0
- package/dist/tests/typeEvaluator7.test.js.map +1 -1
- package/dist/tests/typeUtils.test.js +28 -0
- package/dist/tests/typeUtils.test.js.map +1 -1
- package/dist/typeServer/stubGenerator.js +136 -3
- package/dist/typeServer/stubGenerator.js.map +1 -1
- package/dist/typeServer/typeServerConversionUtils.js +13 -0
- package/dist/typeServer/typeServerConversionUtils.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* collectionInference.ts
|
|
4
|
+
* Copyright (c) Microsoft Corporation.
|
|
5
|
+
* Licensed under the MIT license.
|
|
6
|
+
*
|
|
7
|
+
* collectionInference implementation, using evaluator-owned dependencies and state.
|
|
8
|
+
*/
|
|
9
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
+
}
|
|
15
|
+
Object.defineProperty(o, k2, desc);
|
|
16
|
+
}) : (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
o[k2] = m[k];
|
|
19
|
+
}));
|
|
20
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
+
}) : function(o, v) {
|
|
23
|
+
o["default"] = v;
|
|
24
|
+
});
|
|
25
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
26
|
+
var ownKeys = function(o) {
|
|
27
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
28
|
+
var ar = [];
|
|
29
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
30
|
+
return ar;
|
|
31
|
+
};
|
|
32
|
+
return ownKeys(o);
|
|
33
|
+
};
|
|
34
|
+
return function (mod) {
|
|
35
|
+
if (mod && mod.__esModule) return mod;
|
|
36
|
+
var result = {};
|
|
37
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
38
|
+
__setModuleDefault(result, mod);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
})();
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.createCollectionInference = createCollectionInference;
|
|
44
|
+
const debug_1 = require("../../common/debug");
|
|
45
|
+
const diagnostic_1 = require("../../common/diagnostic");
|
|
46
|
+
const diagnosticRules_1 = require("../../common/diagnosticRules");
|
|
47
|
+
const localize_1 = require("../../localization/localize");
|
|
48
|
+
const parseNodes_1 = require("../../parser/parseNodes");
|
|
49
|
+
const constraintSolver_1 = require("../constraintSolver");
|
|
50
|
+
const constraintTracker_1 = require("../constraintTracker");
|
|
51
|
+
const ParseTreeUtils = __importStar(require("../parseTreeUtils"));
|
|
52
|
+
const tuples_1 = require("../tuples");
|
|
53
|
+
const typedDicts_1 = require("../typedDicts");
|
|
54
|
+
const typeEvaluatorTypes_1 = require("../typeEvaluatorTypes");
|
|
55
|
+
const types_1 = require("../types");
|
|
56
|
+
const typeUtils_1 = require("../typeUtils");
|
|
57
|
+
// Infers collection entries and comprehension clauses, including assignment and diagnostic effects.
|
|
58
|
+
function createCollectionInference(context) {
|
|
59
|
+
const { addDiagnostic, assignType, assignTypeToExpression, convertSpecialFormToRuntimeValue, evaluatorInterface, getBuiltInObject, getBuiltInType, getNoneType, getObjectType, getTupleClassType, getTypeOfExpression, getTypeOfIterator, getTypeVarScopesForNode, getTypingType, inferVarianceForClass, isTypeHashable, makeTopLevelTypeVarsConcrete, maxEntriesToUseForInference, nodeInfo, printType, solveAndApplyConstraints, stripLiteralValue, } = context;
|
|
60
|
+
function getTypeOfDictionaryWithContext(node, flags, inferenceContext, expectedDiagAddendum) {
|
|
61
|
+
inferenceContext.expectedType = (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(inferenceContext.expectedType);
|
|
62
|
+
let concreteExpectedType = makeTopLevelTypeVarsConcrete(inferenceContext.expectedType);
|
|
63
|
+
if (!(0, types_1.isClassInstance)(concreteExpectedType)) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
// Handle TypedDict's as a special case.
|
|
67
|
+
if (types_1.ClassType.isTypedDictClass(concreteExpectedType)) {
|
|
68
|
+
// Remove any conditions associated with the type so the resulting type isn't
|
|
69
|
+
// considered compatible with a bound TypeVar.
|
|
70
|
+
concreteExpectedType = types_1.TypeBase.cloneForCondition(concreteExpectedType, undefined);
|
|
71
|
+
const expectedTypedDictEntries = (0, typedDicts_1.getTypedDictMembersForClass)(evaluatorInterface, concreteExpectedType);
|
|
72
|
+
const { keyTypes, valueTypes, isIncomplete } = inferDictionaryEntries(node, flags, {
|
|
73
|
+
forceStrictInference: true,
|
|
74
|
+
isValueTypeInvariant: true,
|
|
75
|
+
expectedTypedDictEntries,
|
|
76
|
+
expectedDiagAddendum,
|
|
77
|
+
});
|
|
78
|
+
const resultTypedDict = (0, typedDicts_1.assignToTypedDict)(evaluatorInterface, concreteExpectedType, keyTypes, valueTypes,
|
|
79
|
+
// Don't overwrite existing expectedDiagAddendum messages if they were
|
|
80
|
+
// already provided by inferDictionaryEntries.
|
|
81
|
+
expectedDiagAddendum?.isEmpty() ? expectedDiagAddendum : undefined);
|
|
82
|
+
if (resultTypedDict) {
|
|
83
|
+
return {
|
|
84
|
+
type: resultTypedDict,
|
|
85
|
+
isIncomplete,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
let expectedKeyType;
|
|
91
|
+
let expectedValueType;
|
|
92
|
+
if ((0, types_1.isAnyOrUnknown)(inferenceContext.expectedType)) {
|
|
93
|
+
expectedKeyType = inferenceContext.expectedType;
|
|
94
|
+
expectedValueType = inferenceContext.expectedType;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const builtInDict = getBuiltInObject(node, 'dict');
|
|
98
|
+
if (!(0, types_1.isClassInstance)(builtInDict)) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
const dictConstraints = new constraintTracker_1.ConstraintTracker();
|
|
102
|
+
if (!(0, constraintSolver_1.addConstraintsForExpectedType)(evaluatorInterface, builtInDict, inferenceContext.expectedType, dictConstraints, getTypeVarScopesForNode(node), node.start)) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const specializedDict = solveAndApplyConstraints(types_1.ClassType.cloneAsInstantiable(builtInDict), dictConstraints);
|
|
106
|
+
if (!specializedDict.priv.typeArgs || specializedDict.priv.typeArgs.length !== 2) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
expectedKeyType = specializedDict.priv.typeArgs[0];
|
|
110
|
+
expectedValueType = specializedDict.priv.typeArgs[1];
|
|
111
|
+
}
|
|
112
|
+
// Dict and MutableMapping types have invariant value types, so they
|
|
113
|
+
// cannot be narrowed further. Other super-types like Mapping, Collection,
|
|
114
|
+
// and Iterable use covariant value types, so they can be narrowed.
|
|
115
|
+
let isValueTypeInvariant = false;
|
|
116
|
+
if ((0, types_1.isClassInstance)(inferenceContext.expectedType)) {
|
|
117
|
+
if (inferenceContext.expectedType.shared.typeParams.length >= 2) {
|
|
118
|
+
const valueTypeParam = inferenceContext.expectedType.shared.typeParams[1];
|
|
119
|
+
if (types_1.TypeVarType.getVariance(valueTypeParam) === 2 /* Variance.Invariant */) {
|
|
120
|
+
isValueTypeInvariant = true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const { keyTypes, valueTypes, isIncomplete, typeErrors } = inferDictionaryEntries(node, flags, {
|
|
125
|
+
forceStrictInference: true,
|
|
126
|
+
isValueTypeInvariant,
|
|
127
|
+
expectedKeyType,
|
|
128
|
+
expectedValueType,
|
|
129
|
+
expectedDiagAddendum,
|
|
130
|
+
});
|
|
131
|
+
const specializedKeyType = inferTypeArgFromExpectedEntryType((0, typeUtils_1.makeInferenceContext)(expectedKeyType), keyTypes.map((result) => result.type),
|
|
132
|
+
/* isNarrowable */ false);
|
|
133
|
+
const specializedValueType = inferTypeArgFromExpectedEntryType((0, typeUtils_1.makeInferenceContext)(expectedValueType), valueTypes.map((result) => result.type), !isValueTypeInvariant);
|
|
134
|
+
if (!specializedKeyType || !specializedValueType) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
const type = getBuiltInObject(node, 'dict', [specializedKeyType, specializedValueType]);
|
|
138
|
+
return { type, isIncomplete, typeErrors };
|
|
139
|
+
}
|
|
140
|
+
function getTypeOfDictionaryInferred(node, flags, hasExpectedType) {
|
|
141
|
+
const fallbackType = hasExpectedType ? types_1.AnyType.create() : types_1.UnknownType.create();
|
|
142
|
+
let keyType = fallbackType;
|
|
143
|
+
let valueType = fallbackType;
|
|
144
|
+
let isEmptyContainer = false;
|
|
145
|
+
const { keyTypes: keyTypeResults, valueTypes: valueTypeResults, isIncomplete, typeErrors, } = inferDictionaryEntries(node, flags, {
|
|
146
|
+
forceStrictInference: hasExpectedType,
|
|
147
|
+
isValueTypeInvariant: false,
|
|
148
|
+
});
|
|
149
|
+
// Strip any literal values and TypeForm types.
|
|
150
|
+
const keyTypes = keyTypeResults.map((t) => (0, typeUtils_1.stripTypeForm)(convertSpecialFormToRuntimeValue(stripLiteralValue(t.type), flags, !hasExpectedType)));
|
|
151
|
+
const valueTypes = valueTypeResults.map((t) => (0, typeUtils_1.stripTypeForm)(convertSpecialFormToRuntimeValue(stripLiteralValue(t.type), flags, !hasExpectedType)));
|
|
152
|
+
if (keyTypes.length > 0) {
|
|
153
|
+
if (nodeInfo.getFileInfo(node).diagnosticRuleSet.strictDictionaryInference || hasExpectedType) {
|
|
154
|
+
keyType = (0, types_1.combineTypes)(keyTypes);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
keyType = (0, typeUtils_1.areTypesSame)(keyTypes, { ignorePseudoGeneric: true }) ? keyTypes[0] : fallbackType;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
keyType = fallbackType;
|
|
162
|
+
}
|
|
163
|
+
// If the value type differs and we're not using "strict inference mode",
|
|
164
|
+
// we need to back off because we can't properly represent the mappings
|
|
165
|
+
// between different keys and associated value types. If all the values
|
|
166
|
+
// are the same type, we'll assume that all values in this dictionary should
|
|
167
|
+
// be the same.
|
|
168
|
+
if (valueTypes.length > 0) {
|
|
169
|
+
if (nodeInfo.getFileInfo(node).diagnosticRuleSet.strictDictionaryInference || hasExpectedType) {
|
|
170
|
+
valueType = (0, types_1.combineTypes)(valueTypes);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
valueType = (0, typeUtils_1.areTypesSame)(valueTypes, { ignorePseudoGeneric: true }) ? valueTypes[0] : fallbackType;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
valueType = fallbackType;
|
|
178
|
+
isEmptyContainer = true;
|
|
179
|
+
}
|
|
180
|
+
const dictClass = getBuiltInType(node, 'dict');
|
|
181
|
+
const type = (0, types_1.isInstantiableClass)(dictClass)
|
|
182
|
+
? types_1.ClassType.cloneAsInstance(types_1.ClassType.specialize(dictClass, [keyType, valueType],
|
|
183
|
+
/* isTypeArgExplicit */ true,
|
|
184
|
+
/* includeSubclasses */ undefined,
|
|
185
|
+
/* tupleTypeArgs */ undefined, isEmptyContainer))
|
|
186
|
+
: types_1.UnknownType.create();
|
|
187
|
+
if (isIncomplete) {
|
|
188
|
+
if ((0, typeUtils_1.getContainerDepth)(type) > typeEvaluatorTypes_1.maxInferredContainerDepth) {
|
|
189
|
+
return { type: types_1.UnknownType.create() };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return { type, isIncomplete, typeErrors };
|
|
193
|
+
}
|
|
194
|
+
function inferDictionaryEntries(node, flags, options) {
|
|
195
|
+
const results = {
|
|
196
|
+
keyTypes: [],
|
|
197
|
+
valueTypes: [],
|
|
198
|
+
isIncomplete: false,
|
|
199
|
+
typeErrors: false,
|
|
200
|
+
};
|
|
201
|
+
// The sampling limit restricts retained types, not evaluation or diagnostics.
|
|
202
|
+
node.d.items.forEach((entryNode, index) => {
|
|
203
|
+
const retainEntryTypes = options.forceStrictInference || index < maxEntriesToUseForInference;
|
|
204
|
+
let addUnknown = true;
|
|
205
|
+
if (entryNode.nodeType === 20 /* ParseNodeType.DictionaryKeyEntry */) {
|
|
206
|
+
inferDictionaryKeyEntry(node, entryNode, flags, options, results, retainEntryTypes);
|
|
207
|
+
addUnknown = false;
|
|
208
|
+
}
|
|
209
|
+
else if (entryNode.nodeType === 19 /* ParseNodeType.DictionaryExpandEntry */) {
|
|
210
|
+
addUnknown = !tryInferDictionaryExpansion(entryNode, flags, options, results, retainEntryTypes);
|
|
211
|
+
}
|
|
212
|
+
else if (entryNode.nodeType === 11 /* ParseNodeType.Comprehension */) {
|
|
213
|
+
const dictEntryTypeResult = getElementTypeFromComprehension(entryNode, flags | 268435456 /* EvalFlags.StripTupleLiterals */, options.expectedValueType, options.expectedKeyType);
|
|
214
|
+
const dictEntryType = dictEntryTypeResult.type;
|
|
215
|
+
if (dictEntryTypeResult.isIncomplete) {
|
|
216
|
+
results.isIncomplete = true;
|
|
217
|
+
}
|
|
218
|
+
if (dictEntryTypeResult.typeErrors) {
|
|
219
|
+
results.typeErrors = true;
|
|
220
|
+
}
|
|
221
|
+
// The result should be a tuple.
|
|
222
|
+
if ((0, types_1.isClassInstance)(dictEntryType) && (0, typeUtils_1.isTupleClass)(dictEntryType)) {
|
|
223
|
+
const typeArgs = dictEntryType.priv.tupleTypeArgs?.map((t) => t.type);
|
|
224
|
+
if (typeArgs && typeArgs.length === 2) {
|
|
225
|
+
if (retainEntryTypes) {
|
|
226
|
+
results.keyTypes.push({ node: entryNode, type: typeArgs[0] });
|
|
227
|
+
results.valueTypes.push({ node: entryNode, type: typeArgs[1] });
|
|
228
|
+
}
|
|
229
|
+
addUnknown = false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (addUnknown && retainEntryTypes) {
|
|
234
|
+
results.keyTypes.push({ node: entryNode, type: types_1.UnknownType.create() });
|
|
235
|
+
results.valueTypes.push({ node: entryNode, type: types_1.UnknownType.create() });
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
return results;
|
|
239
|
+
}
|
|
240
|
+
function inferDictionaryKeyEntry(node, entryNode, flags, options, results, retainEntryTypes) {
|
|
241
|
+
const { expectedKeyType, expectedValueType, expectedTypedDictEntries, expectedDiagAddendum } = options;
|
|
242
|
+
// Keys aren't type expressions, even within an inlined TypedDict annotation.
|
|
243
|
+
const keyFlags = flags & ~(256 /* EvalFlags.TypeExpression */ | 8 /* EvalFlags.StrLiteralAsType */ | 128 /* EvalFlags.InstantiableType */);
|
|
244
|
+
const keyTypeResult = getTypeOfExpression(entryNode.d.keyExpr, keyFlags | 268435456 /* EvalFlags.StripTupleLiterals */, (0, typeUtils_1.makeInferenceContext)(expectedKeyType ?? (options.forceStrictInference ? types_1.NeverType.createNever() : undefined)));
|
|
245
|
+
if (keyTypeResult.isIncomplete) {
|
|
246
|
+
results.isIncomplete = true;
|
|
247
|
+
}
|
|
248
|
+
if (keyTypeResult.typeErrors) {
|
|
249
|
+
results.typeErrors = true;
|
|
250
|
+
}
|
|
251
|
+
const keyType = keyTypeResult.type;
|
|
252
|
+
if (!keyTypeResult.isIncomplete && !keyTypeResult.typeErrors) {
|
|
253
|
+
verifySetEntryOrDictKeyIsHashable(entryNode.d.keyExpr, keyType, /* isDictKey */ true);
|
|
254
|
+
}
|
|
255
|
+
if (expectedDiagAddendum && keyTypeResult.expectedTypeDiagAddendum) {
|
|
256
|
+
expectedDiagAddendum.addAddendum(keyTypeResult.expectedTypeDiagAddendum);
|
|
257
|
+
}
|
|
258
|
+
let effectiveValueType;
|
|
259
|
+
if (expectedTypedDictEntries &&
|
|
260
|
+
(0, types_1.isClassInstance)(keyType) &&
|
|
261
|
+
types_1.ClassType.isBuiltIn(keyType, 'str') &&
|
|
262
|
+
(0, typeUtils_1.isLiteralType)(keyType) &&
|
|
263
|
+
(expectedTypedDictEntries.knownItems.has(keyType.priv.literalValue) ||
|
|
264
|
+
expectedTypedDictEntries.extraItems)) {
|
|
265
|
+
effectiveValueType =
|
|
266
|
+
expectedTypedDictEntries.knownItems.get(keyType.priv.literalValue)?.valueType ??
|
|
267
|
+
expectedTypedDictEntries.extraItems?.valueType;
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
effectiveValueType =
|
|
271
|
+
expectedValueType ?? (options.forceStrictInference ? types_1.NeverType.createNever() : undefined);
|
|
272
|
+
}
|
|
273
|
+
if (effectiveValueType) {
|
|
274
|
+
const liveTypeVarScopes = getTypeVarScopesForNode(node);
|
|
275
|
+
effectiveValueType = (0, typeUtils_1.transformExpectedType)(effectiveValueType, liveTypeVarScopes, node.start);
|
|
276
|
+
}
|
|
277
|
+
const entryInferenceContext = (0, typeUtils_1.makeInferenceContext)(effectiveValueType);
|
|
278
|
+
let valueTypeResult = getTypeOfExpression(entryNode.d.valueExpr, flags | 268435456 /* EvalFlags.StripTupleLiterals */, entryInferenceContext);
|
|
279
|
+
if (entryInferenceContext && !valueTypeResult.typeErrors) {
|
|
280
|
+
const fromExpectedType = inferTypeArgFromExpectedEntryType(entryInferenceContext, [valueTypeResult.type], !options.isValueTypeInvariant);
|
|
281
|
+
if (fromExpectedType) {
|
|
282
|
+
valueTypeResult = { ...valueTypeResult, type: fromExpectedType };
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (expectedDiagAddendum && valueTypeResult.expectedTypeDiagAddendum) {
|
|
286
|
+
expectedDiagAddendum.addAddendum(valueTypeResult.expectedTypeDiagAddendum);
|
|
287
|
+
}
|
|
288
|
+
if (valueTypeResult.isIncomplete) {
|
|
289
|
+
results.isIncomplete = true;
|
|
290
|
+
}
|
|
291
|
+
if (valueTypeResult.typeErrors) {
|
|
292
|
+
results.typeErrors = true;
|
|
293
|
+
}
|
|
294
|
+
if (retainEntryTypes) {
|
|
295
|
+
// A later literal key replaces its earlier key/value pair.
|
|
296
|
+
if ((0, types_1.isClass)(keyType) && (0, typeUtils_1.isLiteralType)(keyType)) {
|
|
297
|
+
const existingIndex = results.keyTypes.findIndex((kt) => (0, types_1.isTypeSame)(keyType, kt.type));
|
|
298
|
+
if (existingIndex >= 0) {
|
|
299
|
+
results.keyTypes.splice(existingIndex, 1);
|
|
300
|
+
results.valueTypes.splice(existingIndex, 1);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
results.keyTypes.push({ node: entryNode.d.keyExpr, type: keyType });
|
|
304
|
+
results.valueTypes.push({ node: entryNode.d.valueExpr, type: valueTypeResult.type });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Returns whether the expansion has a usable key/value shape, even beyond the sampling limit.
|
|
308
|
+
function tryInferDictionaryExpansion(entryNode, flags, options, results, retainEntryTypes) {
|
|
309
|
+
let expectedType;
|
|
310
|
+
if (options.expectedKeyType && options.expectedValueType) {
|
|
311
|
+
if (context.prefetched?.supportsKeysAndGetItemClass &&
|
|
312
|
+
(0, types_1.isInstantiableClass)(context.prefetched.supportsKeysAndGetItemClass)) {
|
|
313
|
+
expectedType = types_1.ClassType.cloneAsInstance(types_1.ClassType.specialize(context.prefetched.supportsKeysAndGetItemClass, [
|
|
314
|
+
options.expectedKeyType,
|
|
315
|
+
options.expectedValueType,
|
|
316
|
+
]));
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
const entryInferenceContext = (0, typeUtils_1.makeInferenceContext)(expectedType);
|
|
320
|
+
let unexpandedTypeResult = getTypeOfExpression(entryNode.d.expr, flags | 268435456 /* EvalFlags.StripTupleLiterals */, entryInferenceContext);
|
|
321
|
+
if (entryInferenceContext && !unexpandedTypeResult.typeErrors) {
|
|
322
|
+
const fromExpectedType = inferTypeArgFromExpectedEntryType(entryInferenceContext, [unexpandedTypeResult.type], !options.isValueTypeInvariant);
|
|
323
|
+
if (fromExpectedType) {
|
|
324
|
+
unexpandedTypeResult = { ...unexpandedTypeResult, type: fromExpectedType };
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (unexpandedTypeResult.isIncomplete) {
|
|
328
|
+
results.isIncomplete = true;
|
|
329
|
+
}
|
|
330
|
+
if (unexpandedTypeResult.typeErrors) {
|
|
331
|
+
results.typeErrors = true;
|
|
332
|
+
}
|
|
333
|
+
const unexpandedType = unexpandedTypeResult.type;
|
|
334
|
+
if ((0, types_1.isAnyOrUnknown)(unexpandedType)) {
|
|
335
|
+
if (retainEntryTypes) {
|
|
336
|
+
results.keyTypes.push({ node: entryNode, type: unexpandedType });
|
|
337
|
+
results.valueTypes.push({ node: entryNode, type: unexpandedType });
|
|
338
|
+
}
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
if ((0, types_1.isClassInstance)(unexpandedType) && types_1.ClassType.isTypedDictClass(unexpandedType)) {
|
|
342
|
+
if (context.prefetched?.strClass && (0, types_1.isInstantiableClass)(context.prefetched.strClass)) {
|
|
343
|
+
const strObject = types_1.ClassType.cloneAsInstance(context.prefetched.strClass);
|
|
344
|
+
const tdEntries = (0, typedDicts_1.getTypedDictMembersForClass)(evaluatorInterface, unexpandedType,
|
|
345
|
+
/* allowNarrowed */ true);
|
|
346
|
+
tdEntries.knownItems.forEach((entry, name) => {
|
|
347
|
+
if (!options.expectedTypedDictEntries || entry.isRequired || entry.isProvided) {
|
|
348
|
+
results.keyTypes.push({
|
|
349
|
+
node: entryNode,
|
|
350
|
+
type: types_1.ClassType.cloneWithLiteral(strObject, name),
|
|
351
|
+
});
|
|
352
|
+
results.valueTypes.push({ node: entryNode, type: entry.valueType });
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
if (!options.expectedTypedDictEntries) {
|
|
356
|
+
// Open TypedDicts can contain extra items with arbitrary value types.
|
|
357
|
+
results.keyTypes.push({ node: entryNode, type: types_1.ClassType.cloneAsInstance(strObject) });
|
|
358
|
+
results.valueTypes.push({
|
|
359
|
+
node: entryNode,
|
|
360
|
+
type: tdEntries.extraItems?.valueType ?? getObjectType(),
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
else if (context.prefetched?.supportsKeysAndGetItemClass &&
|
|
367
|
+
(0, types_1.isInstantiableClass)(context.prefetched.supportsKeysAndGetItemClass)) {
|
|
368
|
+
const mappingConstraints = new constraintTracker_1.ConstraintTracker();
|
|
369
|
+
const supportsKeysAndGetItemClass = (0, typeUtils_1.selfSpecializeClass)(context.prefetched.supportsKeysAndGetItemClass);
|
|
370
|
+
if (assignType(types_1.ClassType.cloneAsInstance(supportsKeysAndGetItemClass), unexpandedType,
|
|
371
|
+
/* diag */ undefined, mappingConstraints, 256 /* AssignTypeFlags.RetainLiteralsForTypeVar */)) {
|
|
372
|
+
const specializedMapping = solveAndApplyConstraints(supportsKeysAndGetItemClass, mappingConstraints);
|
|
373
|
+
const typeArgs = specializedMapping.priv.typeArgs;
|
|
374
|
+
if (typeArgs && typeArgs.length >= 2) {
|
|
375
|
+
if (retainEntryTypes) {
|
|
376
|
+
results.keyTypes.push({ node: entryNode, type: typeArgs[0] });
|
|
377
|
+
results.valueTypes.push({ node: entryNode, type: typeArgs[1] });
|
|
378
|
+
}
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
addDiagnostic(diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.LocMessage.dictUnpackIsNotMapping(), entryNode);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
function getTypeOfListOrSetWithContext(node, flags, inferenceContext) {
|
|
389
|
+
const builtInClassName = node.nodeType === 34 /* ParseNodeType.List */ ? 'list' : 'set';
|
|
390
|
+
inferenceContext.expectedType = (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(inferenceContext.expectedType);
|
|
391
|
+
let isIncomplete = false;
|
|
392
|
+
let typeErrors = false;
|
|
393
|
+
const verifyHashable = node.nodeType === 45 /* ParseNodeType.Set */;
|
|
394
|
+
const expectedEntryType = getExpectedEntryTypeForIterable(node, getBuiltInType(node, builtInClassName), inferenceContext);
|
|
395
|
+
if (!expectedEntryType) {
|
|
396
|
+
return undefined;
|
|
397
|
+
}
|
|
398
|
+
const entryTypes = [];
|
|
399
|
+
const expectedTypeDiagAddendum = new diagnostic_1.DiagnosticAddendum();
|
|
400
|
+
node.d.items.forEach((entry) => {
|
|
401
|
+
let entryTypeResult;
|
|
402
|
+
if (entry.nodeType === 11 /* ParseNodeType.Comprehension */) {
|
|
403
|
+
entryTypeResult = getElementTypeFromComprehension(entry, flags | 268435456 /* EvalFlags.StripTupleLiterals */, expectedEntryType);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
entryTypeResult = getTypeOfExpression(entry, flags | 268435456 /* EvalFlags.StripTupleLiterals */, (0, typeUtils_1.makeInferenceContext)(expectedEntryType));
|
|
407
|
+
}
|
|
408
|
+
entryTypes.push(entryTypeResult.type);
|
|
409
|
+
if (entryTypeResult.isIncomplete) {
|
|
410
|
+
isIncomplete = true;
|
|
411
|
+
}
|
|
412
|
+
if (entryTypeResult.typeErrors) {
|
|
413
|
+
typeErrors = true;
|
|
414
|
+
}
|
|
415
|
+
if (entryTypeResult.expectedTypeDiagAddendum) {
|
|
416
|
+
expectedTypeDiagAddendum.addAddendum(entryTypeResult.expectedTypeDiagAddendum);
|
|
417
|
+
}
|
|
418
|
+
if (verifyHashable && !entryTypeResult.isIncomplete && !entryTypeResult.typeErrors) {
|
|
419
|
+
verifySetEntryOrDictKeyIsHashable(entry, entryTypeResult.type, /* isDictKey */ false);
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
let isTypeInvariant = false;
|
|
423
|
+
if ((0, types_1.isClassInstance)(inferenceContext.expectedType)) {
|
|
424
|
+
inferVarianceForClass(inferenceContext.expectedType);
|
|
425
|
+
if (inferenceContext.expectedType.shared.typeParams.some((t) => types_1.TypeVarType.getVariance(t) === 2 /* Variance.Invariant */)) {
|
|
426
|
+
isTypeInvariant = true;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
const specializedEntryType = inferTypeArgFromExpectedEntryType((0, typeUtils_1.makeInferenceContext)(expectedEntryType), entryTypes, !isTypeInvariant);
|
|
430
|
+
if (!specializedEntryType) {
|
|
431
|
+
return { type: types_1.UnknownType.create(), isIncomplete, typeErrors: true, expectedTypeDiagAddendum };
|
|
432
|
+
}
|
|
433
|
+
const type = getBuiltInObject(node, builtInClassName, [specializedEntryType]);
|
|
434
|
+
return { type, isIncomplete, typeErrors, expectedTypeDiagAddendum };
|
|
435
|
+
}
|
|
436
|
+
function getExpectedEntryTypeForIterable(node, expectedClassType, inferenceContext) {
|
|
437
|
+
if (!inferenceContext) {
|
|
438
|
+
return undefined;
|
|
439
|
+
}
|
|
440
|
+
if (!expectedClassType || !(0, types_1.isInstantiableClass)(expectedClassType)) {
|
|
441
|
+
return undefined;
|
|
442
|
+
}
|
|
443
|
+
if ((0, types_1.isAnyOrUnknown)(inferenceContext.expectedType)) {
|
|
444
|
+
return inferenceContext.expectedType;
|
|
445
|
+
}
|
|
446
|
+
if (!(0, types_1.isClassInstance)(inferenceContext.expectedType)) {
|
|
447
|
+
return undefined;
|
|
448
|
+
}
|
|
449
|
+
const constraints = new constraintTracker_1.ConstraintTracker();
|
|
450
|
+
if (!(0, constraintSolver_1.addConstraintsForExpectedType)(evaluatorInterface, types_1.ClassType.cloneAsInstance(expectedClassType), inferenceContext.expectedType, constraints, getTypeVarScopesForNode(node), node.start)) {
|
|
451
|
+
return undefined;
|
|
452
|
+
}
|
|
453
|
+
const specializedListOrSet = solveAndApplyConstraints(expectedClassType, constraints);
|
|
454
|
+
if (!specializedListOrSet.priv.typeArgs) {
|
|
455
|
+
return undefined;
|
|
456
|
+
}
|
|
457
|
+
return specializedListOrSet.priv.typeArgs[0];
|
|
458
|
+
}
|
|
459
|
+
function getTypeOfListOrSetInferred(node, flags, hasExpectedType) {
|
|
460
|
+
const builtInClassName = node.nodeType === 34 /* ParseNodeType.List */ ? 'list' : 'set';
|
|
461
|
+
const verifyHashable = node.nodeType === 45 /* ParseNodeType.Set */;
|
|
462
|
+
let isEmptyContainer = false;
|
|
463
|
+
let isIncomplete = false;
|
|
464
|
+
let typeErrors = false;
|
|
465
|
+
let entryTypes = [];
|
|
466
|
+
node.d.items.forEach((entry, index) => {
|
|
467
|
+
let entryTypeResult;
|
|
468
|
+
if (entry.nodeType === 11 /* ParseNodeType.Comprehension */ && !entry.d.isGenerator) {
|
|
469
|
+
entryTypeResult = getElementTypeFromComprehension(entry, flags | 268435456 /* EvalFlags.StripTupleLiterals */);
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
entryTypeResult = getTypeOfExpression(entry, flags | 268435456 /* EvalFlags.StripTupleLiterals */);
|
|
473
|
+
}
|
|
474
|
+
entryTypeResult.type = (0, typeUtils_1.stripTypeForm)(convertSpecialFormToRuntimeValue(entryTypeResult.type, flags, !hasExpectedType));
|
|
475
|
+
if (entryTypeResult.isIncomplete) {
|
|
476
|
+
isIncomplete = true;
|
|
477
|
+
}
|
|
478
|
+
if (entryTypeResult.typeErrors) {
|
|
479
|
+
typeErrors = true;
|
|
480
|
+
}
|
|
481
|
+
if (hasExpectedType || index < maxEntriesToUseForInference) {
|
|
482
|
+
entryTypes.push(entryTypeResult.type);
|
|
483
|
+
}
|
|
484
|
+
if (verifyHashable && !entryTypeResult.isIncomplete && !entryTypeResult.typeErrors) {
|
|
485
|
+
verifySetEntryOrDictKeyIsHashable(entry, entryTypeResult.type, /* isDictKey */ false);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
entryTypes = entryTypes.map((t) => stripLiteralValue(t));
|
|
489
|
+
let inferredEntryType = hasExpectedType ? types_1.AnyType.create() : types_1.UnknownType.create();
|
|
490
|
+
if (entryTypes.length > 0) {
|
|
491
|
+
const fileInfo = nodeInfo.getFileInfo(node);
|
|
492
|
+
// If there was an expected type or we're using strict list inference,
|
|
493
|
+
// combine the types into a union.
|
|
494
|
+
if ((builtInClassName === 'list' && fileInfo.diagnosticRuleSet.strictListInference) ||
|
|
495
|
+
(builtInClassName === 'set' && fileInfo.diagnosticRuleSet.strictSetInference) ||
|
|
496
|
+
hasExpectedType) {
|
|
497
|
+
inferredEntryType = (0, types_1.combineTypes)(entryTypes, { maxSubtypeCount: typeEvaluatorTypes_1.maxSubtypesForInferredType });
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
// Is the list or set homogeneous? If so, use stricter rules. Otherwise relax the rules.
|
|
501
|
+
inferredEntryType = (0, typeUtils_1.areTypesSame)(entryTypes, { ignorePseudoGeneric: true })
|
|
502
|
+
? entryTypes[0]
|
|
503
|
+
: inferredEntryType;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
isEmptyContainer = true;
|
|
508
|
+
}
|
|
509
|
+
const listOrSetClass = getBuiltInType(node, builtInClassName);
|
|
510
|
+
const type = (0, types_1.isInstantiableClass)(listOrSetClass)
|
|
511
|
+
? types_1.ClassType.cloneAsInstance(types_1.ClassType.specialize(listOrSetClass, [inferredEntryType],
|
|
512
|
+
/* isTypeArgExplicit */ true,
|
|
513
|
+
/* includeSubclasses */ undefined,
|
|
514
|
+
/* tupleTypeArgs */ undefined, isEmptyContainer))
|
|
515
|
+
: types_1.UnknownType.create();
|
|
516
|
+
if (isIncomplete) {
|
|
517
|
+
if ((0, typeUtils_1.getContainerDepth)(type) > typeEvaluatorTypes_1.maxInferredContainerDepth) {
|
|
518
|
+
return { type: types_1.UnknownType.create() };
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return { type, isIncomplete, typeErrors };
|
|
522
|
+
}
|
|
523
|
+
function getTypeOfComprehension(node, flags, inferenceContext) {
|
|
524
|
+
let isIncomplete = false;
|
|
525
|
+
let typeErrors = false;
|
|
526
|
+
// If any of the "for" clauses are marked async or any of the "if" clauses
|
|
527
|
+
// or any clause other than the leftmost "for" contain an "await" operator,
|
|
528
|
+
// it is treated as an async generator.
|
|
529
|
+
let isAsync = node.d.forIfNodes.some((comp, index) => {
|
|
530
|
+
if (comp.nodeType === 12 /* ParseNodeType.ComprehensionFor */ && comp.d.isAsync) {
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
533
|
+
return index > 0 && ParseTreeUtils.containsAwaitNode(comp);
|
|
534
|
+
});
|
|
535
|
+
let type = types_1.UnknownType.create();
|
|
536
|
+
if (ParseTreeUtils.containsAwaitNode(node.d.expr)) {
|
|
537
|
+
isAsync = true;
|
|
538
|
+
}
|
|
539
|
+
const builtInIteratorType = getTypingType(node, isAsync ? 'AsyncGenerator' : 'Generator');
|
|
540
|
+
const expectedEntryType = getExpectedEntryTypeForIterable(node, builtInIteratorType, inferenceContext);
|
|
541
|
+
const elementTypeResult = getElementTypeFromComprehension(node, flags | 268435456 /* EvalFlags.StripTupleLiterals */, expectedEntryType);
|
|
542
|
+
if (elementTypeResult.isIncomplete) {
|
|
543
|
+
isIncomplete = true;
|
|
544
|
+
}
|
|
545
|
+
if (elementTypeResult.typeErrors) {
|
|
546
|
+
typeErrors = true;
|
|
547
|
+
}
|
|
548
|
+
let elementType = elementTypeResult.type;
|
|
549
|
+
if (!expectedEntryType || !(0, typeUtils_1.containsLiteralType)(expectedEntryType)) {
|
|
550
|
+
elementType = stripLiteralValue(elementType);
|
|
551
|
+
}
|
|
552
|
+
if (builtInIteratorType && (0, types_1.isInstantiableClass)(builtInIteratorType)) {
|
|
553
|
+
type = types_1.ClassType.cloneAsInstance(types_1.ClassType.specialize(builtInIteratorType, isAsync ? [elementType, getNoneType()] : [elementType, getNoneType(), getNoneType()]));
|
|
554
|
+
}
|
|
555
|
+
return { type, isIncomplete, typeErrors };
|
|
556
|
+
}
|
|
557
|
+
function getElementTypeFromComprehension(node, flags, expectedValueOrElementType, expectedKeyType) {
|
|
558
|
+
let isIncomplete = false;
|
|
559
|
+
let typeErrors = false;
|
|
560
|
+
// "Execute" the list comprehensions from start to finish.
|
|
561
|
+
for (const forIfNode of node.d.forIfNodes) {
|
|
562
|
+
if (evaluateComprehensionForIf(forIfNode)) {
|
|
563
|
+
isIncomplete = true;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
let type = types_1.UnknownType.create();
|
|
567
|
+
if (node.d.expr.nodeType === 20 /* ParseNodeType.DictionaryKeyEntry */) {
|
|
568
|
+
// Create a tuple with the key/value types.
|
|
569
|
+
const keyTypeResult = getTypeOfExpression(node.d.expr.d.keyExpr, flags, (0, typeUtils_1.makeInferenceContext)(expectedKeyType));
|
|
570
|
+
if (keyTypeResult.isIncomplete) {
|
|
571
|
+
isIncomplete = true;
|
|
572
|
+
}
|
|
573
|
+
if (keyTypeResult.typeErrors) {
|
|
574
|
+
typeErrors = true;
|
|
575
|
+
}
|
|
576
|
+
let keyType = keyTypeResult.type;
|
|
577
|
+
if (!expectedKeyType || !(0, typeUtils_1.containsLiteralType)(expectedKeyType)) {
|
|
578
|
+
keyType = stripLiteralValue(keyType);
|
|
579
|
+
}
|
|
580
|
+
const valueTypeResult = getTypeOfExpression(node.d.expr.d.valueExpr, flags, (0, typeUtils_1.makeInferenceContext)(expectedValueOrElementType));
|
|
581
|
+
if (valueTypeResult.isIncomplete) {
|
|
582
|
+
isIncomplete = true;
|
|
583
|
+
}
|
|
584
|
+
if (valueTypeResult.typeErrors) {
|
|
585
|
+
typeErrors = true;
|
|
586
|
+
}
|
|
587
|
+
let valueType = valueTypeResult.type;
|
|
588
|
+
if (!expectedValueOrElementType || !(0, typeUtils_1.containsLiteralType)(expectedValueOrElementType)) {
|
|
589
|
+
valueType = stripLiteralValue(valueType);
|
|
590
|
+
}
|
|
591
|
+
type = (0, tuples_1.makeTupleObject)(evaluatorInterface, [
|
|
592
|
+
{ type: keyType, isUnbounded: false },
|
|
593
|
+
{ type: valueType, isUnbounded: false },
|
|
594
|
+
]);
|
|
595
|
+
}
|
|
596
|
+
else if (node.d.expr.nodeType === 19 /* ParseNodeType.DictionaryExpandEntry */) {
|
|
597
|
+
// The parser should have reported an error in this case because it's not allowed.
|
|
598
|
+
getTypeOfExpression(node.d.expr.d.expr, flags, (0, typeUtils_1.makeInferenceContext)(expectedValueOrElementType));
|
|
599
|
+
}
|
|
600
|
+
else if ((0, parseNodes_1.isExpressionNode)(node)) {
|
|
601
|
+
const exprTypeResult = getTypeOfExpression(node.d.expr, flags, (0, typeUtils_1.makeInferenceContext)(expectedValueOrElementType));
|
|
602
|
+
if (exprTypeResult.isIncomplete) {
|
|
603
|
+
isIncomplete = true;
|
|
604
|
+
}
|
|
605
|
+
if (exprTypeResult.typeErrors) {
|
|
606
|
+
typeErrors = true;
|
|
607
|
+
}
|
|
608
|
+
type = exprTypeResult.type;
|
|
609
|
+
}
|
|
610
|
+
return { type, isIncomplete, typeErrors };
|
|
611
|
+
}
|
|
612
|
+
function verifySetEntryOrDictKeyIsHashable(entry, type, isDictKey) {
|
|
613
|
+
// Verify that the type is hashable.
|
|
614
|
+
if (!isTypeHashable(type)) {
|
|
615
|
+
const diag = new diagnostic_1.DiagnosticAddendum();
|
|
616
|
+
diag.addMessage(localize_1.LocAddendum.unhashableType().format({ type: printType(type) }));
|
|
617
|
+
const message = isDictKey ? localize_1.LocMessage.unhashableDictKey() : localize_1.LocMessage.unhashableSetEntry();
|
|
618
|
+
addDiagnostic(diagnosticRules_1.DiagnosticRule.reportUnhashable, message + diag.getString(), entry);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
function inferTypeArgFromExpectedEntryType(inferenceContext, entryTypes, isNarrowable) {
|
|
622
|
+
// If the expected type is Any, the resulting type becomes Any.
|
|
623
|
+
if ((0, types_1.isAny)(inferenceContext.expectedType)) {
|
|
624
|
+
return inferenceContext.expectedType;
|
|
625
|
+
}
|
|
626
|
+
const constraints = new constraintTracker_1.ConstraintTracker();
|
|
627
|
+
const expectedType = inferenceContext.expectedType;
|
|
628
|
+
let isCompatible = true;
|
|
629
|
+
entryTypes.forEach((entryType) => {
|
|
630
|
+
if (isCompatible && !assignType(expectedType, entryType, /* diag */ undefined, constraints)) {
|
|
631
|
+
isCompatible = false;
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
if (!isCompatible) {
|
|
635
|
+
return undefined;
|
|
636
|
+
}
|
|
637
|
+
if (isNarrowable && entryTypes.length > 0) {
|
|
638
|
+
const combinedTypes = (0, types_1.combineTypes)(entryTypes);
|
|
639
|
+
return (0, typeUtils_1.containsLiteralType)(inferenceContext.expectedType)
|
|
640
|
+
? combinedTypes
|
|
641
|
+
: stripLiteralValue(combinedTypes);
|
|
642
|
+
}
|
|
643
|
+
return (0, typeUtils_1.mapSubtypes)(solveAndApplyConstraints(inferenceContext.expectedType, constraints, {
|
|
644
|
+
replaceUnsolved: {
|
|
645
|
+
scopeIds: [],
|
|
646
|
+
tupleClassType: getTupleClassType(),
|
|
647
|
+
},
|
|
648
|
+
}), (subtype) => {
|
|
649
|
+
if (entryTypes.length !== 1) {
|
|
650
|
+
return subtype;
|
|
651
|
+
}
|
|
652
|
+
const entryType = entryTypes[0];
|
|
653
|
+
// If the entry type is a TypedDict instance, clone it with additional information.
|
|
654
|
+
if ((0, types_1.isTypeSame)(subtype, entryType, { ignoreTypedDictNarrowEntries: true }) &&
|
|
655
|
+
(0, types_1.isClass)(subtype) &&
|
|
656
|
+
(0, types_1.isClass)(entryType) &&
|
|
657
|
+
types_1.ClassType.isTypedDictClass(entryType)) {
|
|
658
|
+
return types_1.ClassType.cloneForNarrowedTypedDictEntries(subtype, entryType.priv.typedDictNarrowedEntries);
|
|
659
|
+
}
|
|
660
|
+
return subtype;
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
function evaluateComprehensionForIf(node) {
|
|
664
|
+
let isIncomplete = false;
|
|
665
|
+
if (node.nodeType === 12 /* ParseNodeType.ComprehensionFor */) {
|
|
666
|
+
const iterableTypeResult = getTypeOfExpression(node.d.iterableExpr);
|
|
667
|
+
if (iterableTypeResult.isIncomplete) {
|
|
668
|
+
isIncomplete = true;
|
|
669
|
+
}
|
|
670
|
+
const iterableType = stripLiteralValue(iterableTypeResult.type);
|
|
671
|
+
const itemTypeResult = getTypeOfIterator({ type: iterableType, isIncomplete: iterableTypeResult.isIncomplete }, !!node.d.isAsync, node.d.iterableExpr) ?? { type: types_1.UnknownType.create(), isIncomplete: iterableTypeResult.isIncomplete };
|
|
672
|
+
const targetExpr = node.d.targetExpr;
|
|
673
|
+
assignTypeToExpression(targetExpr, itemTypeResult, node.d.iterableExpr);
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
(0, debug_1.assert)(node.nodeType === 13 /* ParseNodeType.ComprehensionIf */);
|
|
677
|
+
// Evaluate the test expression to validate it and mark symbols
|
|
678
|
+
// as referenced. This doesn't affect the type of the evaluated
|
|
679
|
+
// comprehension, but it is important for evaluating intermediate
|
|
680
|
+
// expressions such as assignment expressions that can affect other
|
|
681
|
+
// subexpressions.
|
|
682
|
+
getTypeOfExpression(node.d.testExpr);
|
|
683
|
+
}
|
|
684
|
+
return isIncomplete;
|
|
685
|
+
}
|
|
686
|
+
return {
|
|
687
|
+
getTypeOfDictionaryWithContext,
|
|
688
|
+
getTypeOfDictionaryInferred,
|
|
689
|
+
getTypeOfListOrSetWithContext,
|
|
690
|
+
getTypeOfListOrSetInferred,
|
|
691
|
+
getTypeOfComprehension,
|
|
692
|
+
evaluateComprehensionForIf,
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
//# sourceMappingURL=collectionInference.js.map
|