@zzzen/pyright-internal 1.2.0-dev.20231008 → 1.2.0-dev.20231022
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/checker.js +33 -37
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/codeFlowEngine.js +2 -2
- package/dist/analyzer/codeFlowEngine.js.map +1 -1
- package/dist/analyzer/constraintSolver.js +262 -168
- package/dist/analyzer/constraintSolver.js.map +1 -1
- package/dist/analyzer/constructors.js +3 -4
- package/dist/analyzer/constructors.js.map +1 -1
- package/dist/analyzer/decorators.js +3 -1
- package/dist/analyzer/decorators.js.map +1 -1
- package/dist/analyzer/parseTreeUtils.d.ts +1 -1
- package/dist/analyzer/patternMatching.js +4 -0
- package/dist/analyzer/patternMatching.js.map +1 -1
- package/dist/analyzer/program.js +7 -1
- package/dist/analyzer/program.js.map +1 -1
- package/dist/analyzer/properties.d.ts +2 -2
- package/dist/analyzer/properties.js +10 -4
- package/dist/analyzer/properties.js.map +1 -1
- package/dist/analyzer/protocols.js +119 -174
- package/dist/analyzer/protocols.js.map +1 -1
- package/dist/analyzer/service.js +13 -13
- package/dist/analyzer/service.js.map +1 -1
- package/dist/analyzer/sourceFile.d.ts +3 -2
- package/dist/analyzer/sourceFile.js +31 -11
- package/dist/analyzer/sourceFile.js.map +1 -1
- package/dist/analyzer/sourceFileInfo.d.ts +4 -4
- package/dist/analyzer/sourceFileInfo.js +2 -0
- package/dist/analyzer/sourceFileInfo.js.map +1 -1
- package/dist/analyzer/staticExpressions.js +2 -1
- package/dist/analyzer/staticExpressions.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +138 -123
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +4 -3
- package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
- package/dist/analyzer/typeGuards.js +101 -33
- package/dist/analyzer/typeGuards.js.map +1 -1
- package/dist/analyzer/typePrinter.js +4 -1
- package/dist/analyzer/typePrinter.js.map +1 -1
- package/dist/analyzer/typeUtils.d.ts +13 -2
- package/dist/analyzer/typeUtils.js +130 -51
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/analyzer/typeVarContext.d.ts +4 -1
- package/dist/analyzer/typeVarContext.js +7 -2
- package/dist/analyzer/typeVarContext.js.map +1 -1
- package/dist/analyzer/typedDicts.js +99 -27
- package/dist/analyzer/typedDicts.js.map +1 -1
- package/dist/analyzer/types.d.ts +6 -2
- package/dist/analyzer/types.js +49 -17
- package/dist/analyzer/types.js.map +1 -1
- package/dist/backgroundThreadBase.js +5 -1
- package/dist/backgroundThreadBase.js.map +1 -1
- package/dist/common/configOptions.d.ts +2 -1
- package/dist/common/configOptions.js +9 -5
- package/dist/common/configOptions.js.map +1 -1
- package/dist/common/extensibility.d.ts +0 -2
- package/dist/common/extensibility.js.map +1 -1
- package/dist/common/fileSystem.d.ts +9 -4
- package/dist/common/fileSystem.js +8 -1
- package/dist/common/fileSystem.js.map +1 -1
- package/dist/common/pathUtils.d.ts +8 -5
- package/dist/common/pathUtils.js +90 -33
- package/dist/common/pathUtils.js.map +1 -1
- package/dist/common/realFileSystem.d.ts +7 -1
- package/dist/common/realFileSystem.js +35 -22
- package/dist/common/realFileSystem.js.map +1 -1
- package/dist/common/serviceProviderExtensions.d.ts +3 -4
- package/dist/common/serviceProviderExtensions.js +3 -6
- package/dist/common/serviceProviderExtensions.js.map +1 -1
- package/dist/common/uriParser.d.ts +10 -1
- package/dist/common/uriParser.js.map +1 -1
- package/dist/languageServerBase.d.ts +4 -4
- package/dist/languageServerBase.js +3 -17
- package/dist/languageServerBase.js.map +1 -1
- package/dist/languageService/autoImporter.d.ts +1 -1
- package/dist/languageService/completionProvider.d.ts +2 -2
- package/dist/languageService/completionProvider.js +20 -23
- package/dist/languageService/completionProvider.js.map +1 -1
- package/dist/languageService/hoverProvider.d.ts +6 -2
- package/dist/languageService/hoverProvider.js +33 -65
- package/dist/languageService/hoverProvider.js.map +1 -1
- package/dist/languageService/navigationUtils.d.ts +1 -1
- package/dist/languageService/navigationUtils.js +2 -2
- package/dist/languageService/navigationUtils.js.map +1 -1
- package/dist/languageService/referencesProvider.d.ts +9 -2
- package/dist/languageService/referencesProvider.js +19 -12
- package/dist/languageService/referencesProvider.js.map +1 -1
- package/dist/languageService/tooltipUtils.js +1 -3
- package/dist/languageService/tooltipUtils.js.map +1 -1
- package/dist/localization/localize.d.ts +4 -3
- package/dist/localization/localize.js +1 -1
- package/dist/localization/localize.js.map +1 -1
- package/dist/localization/package.nls.cs.json +7 -1
- package/dist/localization/package.nls.de.json +7 -1
- package/dist/localization/package.nls.en-us.json +1 -1
- package/dist/localization/package.nls.es.json +7 -1
- package/dist/localization/package.nls.fr.json +7 -1
- package/dist/localization/package.nls.it.json +7 -1
- package/dist/localization/package.nls.ja.json +7 -1
- package/dist/localization/package.nls.ko.json +7 -1
- package/dist/localization/package.nls.pl.json +7 -1
- package/dist/localization/package.nls.pt-br.json +7 -1
- package/dist/localization/package.nls.qps-ploc.json +7 -1
- package/dist/localization/package.nls.ru.json +7 -1
- package/dist/localization/package.nls.tr.json +7 -1
- package/dist/localization/package.nls.zh-cn.json +7 -1
- package/dist/localization/package.nls.zh-tw.json +7 -1
- package/dist/pyright.js +2 -1
- package/dist/pyright.js.map +1 -1
- package/dist/pyrightFileSystem.d.ts +1 -16
- package/dist/pyrightFileSystem.js +1 -60
- package/dist/pyrightFileSystem.js.map +1 -1
- package/dist/readonlyAugmentedFileSystem.d.ts +1 -4
- package/dist/readonlyAugmentedFileSystem.js +0 -10
- package/dist/readonlyAugmentedFileSystem.js.map +1 -1
- package/dist/server.js +2 -1
- package/dist/server.js.map +1 -1
- package/dist/tests/config.test.js +5 -3
- package/dist/tests/config.test.js.map +1 -1
- package/dist/tests/fourslash/completions.indexer.keys.getitem.fourslash.js +56 -10
- package/dist/tests/fourslash/completions.indexer.keys.getitem.fourslash.js.map +1 -1
- package/dist/tests/harness/fourslash/testState.d.ts +5 -2
- package/dist/tests/harness/fourslash/testState.js +13 -14
- package/dist/tests/harness/fourslash/testState.js.map +1 -1
- package/dist/tests/harness/vfs/filesystem.d.ts +2 -2
- package/dist/tests/harness/vfs/filesystem.js +4 -0
- package/dist/tests/harness/vfs/filesystem.js.map +1 -1
- package/dist/tests/harness/vfs/pathValidation.js +10 -1
- package/dist/tests/harness/vfs/pathValidation.js.map +1 -1
- package/dist/tests/importResolver.test.js +0 -9
- package/dist/tests/importResolver.test.js.map +1 -1
- package/dist/tests/pathUtils.test.js +2 -2
- package/dist/tests/pathUtils.test.js.map +1 -1
- package/dist/tests/pyrightFileSystem.test.js +0 -20
- package/dist/tests/pyrightFileSystem.test.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +4 -0
- package/dist/tests/typeEvaluator1.test.js.map +1 -1
- package/dist/tests/typeEvaluator2.test.js +14 -2
- package/dist/tests/typeEvaluator2.test.js.map +1 -1
- package/dist/tests/typeEvaluator3.test.js +5 -1
- package/dist/tests/typeEvaluator3.test.js.map +1 -1
- package/dist/tests/typeEvaluator4.test.js +10 -2
- package/dist/tests/typeEvaluator4.test.js.map +1 -1
- package/dist/tests/typeEvaluator5.test.js +7 -1
- package/dist/tests/typeEvaluator5.test.js.map +1 -1
- package/package.json +1 -1
@@ -21,6 +21,9 @@ const typeVarContext_1 = require("./typeVarContext");
|
|
21
21
|
// many subtypes. For performance reasons, we need to cap this at some
|
22
22
|
// point. This constant determines the cap.
|
23
23
|
const maxSubtypeCountForTypeVarNarrowBound = 64;
|
24
|
+
// This debugging switch enables logging of the TypeVarContext before and
|
25
|
+
// after it is updated by the constraint solver.
|
26
|
+
const logTypeVarContextUpdates = false;
|
24
27
|
// Assigns the source type to the dest type var in the type var context. If an existing
|
25
28
|
// type is already associated with that type var name, it attempts to either widen or
|
26
29
|
// narrow the type (depending on the value of the isContravariant parameter). The goal is
|
@@ -28,7 +31,19 @@ const maxSubtypeCountForTypeVarNarrowBound = 64;
|
|
28
31
|
// has been "locked", it simply validates that the srcType is compatible (with no attempt
|
29
32
|
// to widen or narrow).
|
30
33
|
function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext, flags = 0 /* Default */, recursionCount = 0) {
|
34
|
+
if (logTypeVarContextUpdates) {
|
35
|
+
const indent = ' '.repeat(recursionCount * 2);
|
36
|
+
console.log(`${indent}`);
|
37
|
+
console.log(`${indent}assignTypeToTypeVar called with`);
|
38
|
+
console.log(`${indent}destType: ${evaluator.printType(destType)}`);
|
39
|
+
console.log(`${indent}srcType: ${evaluator.printType(srcType)}`);
|
40
|
+
console.log(`${indent}flags: ${flags}`);
|
41
|
+
console.log(`${indent}scopes: ${(typeVarContext.getSolveForScopes() || []).join(', ')}`);
|
42
|
+
console.log(`${indent}pre-call context #${typeVarContext.getId()}: `);
|
43
|
+
logTypeVarContext(evaluator, typeVarContext, indent);
|
44
|
+
}
|
31
45
|
let isTypeVarInScope = true;
|
46
|
+
const isInvariant = (flags & 1 /* EnforceInvariance */) !== 0;
|
32
47
|
const isContravariant = (flags & 2 /* ReverseTypeVarMatching */) !== 0;
|
33
48
|
// If the TypeVar doesn't have a scope ID, then it's being used
|
34
49
|
// outside of a valid TypeVar scope. This will be reported as a
|
@@ -51,7 +66,7 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
51
66
|
}
|
52
67
|
// Never or NoReturn is always assignable to all type variables unless
|
53
68
|
// we're enforcing invariance.
|
54
|
-
if ((0, types_1.isNever)(srcType) &&
|
69
|
+
if ((0, types_1.isNever)(srcType) && !isInvariant) {
|
55
70
|
return true;
|
56
71
|
}
|
57
72
|
// If we're in "ignore type var scope" mode, don't generate
|
@@ -103,144 +118,20 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
103
118
|
!srcType.typeArguments) {
|
104
119
|
srcType = types_1.AnyType.create();
|
105
120
|
}
|
106
|
-
const curEntry = typeVarContext.getPrimarySignature().getTypeVar(destType);
|
107
|
-
const curNarrowTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.narrowBound;
|
108
|
-
let curWideTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.wideBound;
|
109
|
-
if (!curWideTypeBound && !destType.details.isSynthesizedSelf) {
|
110
|
-
curWideTypeBound = destType.details.boundType;
|
111
|
-
}
|
112
121
|
// Handle the constrained case. This case needs to be handled specially
|
113
122
|
// because type narrowing isn't used in this case. For example, if the
|
114
123
|
// source type is "Literal[1]" and the constraint list includes the type
|
115
124
|
// "float", the resulting type is float.
|
116
125
|
if (destType.details.constraints.length > 0) {
|
117
|
-
|
118
|
-
const concreteSrcType = evaluator.makeTopLevelTypeVarsConcrete(srcType);
|
119
|
-
if ((0, types_1.isTypeVar)(srcType)) {
|
120
|
-
if (evaluator.assignType(destType, concreteSrcType,
|
121
|
-
/* diag */ undefined, new typeVarContext_1.TypeVarContext(destType.scopeId),
|
122
|
-
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
123
|
-
constrainedType = srcType;
|
124
|
-
// If the source and dest are both instantiables (type[T]), then
|
125
|
-
// we need to convert to an instance (T).
|
126
|
-
if (types_1.TypeBase.isInstantiable(srcType)) {
|
127
|
-
constrainedType = (0, typeUtils_1.convertToInstance)(srcType, /* includeSubclasses */ false);
|
128
|
-
}
|
129
|
-
}
|
130
|
-
}
|
131
|
-
else {
|
132
|
-
let isCompatible = true;
|
133
|
-
// Subtypes that are not conditionally dependent on the dest type var
|
134
|
-
// must all map to the same constraint. For example, Union[str, bytes]
|
135
|
-
// cannot be assigned to AnyStr.
|
136
|
-
let unconditionalConstraintIndex;
|
137
|
-
// Find the narrowest constrained type that is compatible.
|
138
|
-
constrainedType = (0, typeUtils_1.mapSubtypes)(concreteSrcType, (srcSubtype) => {
|
139
|
-
let constrainedSubtype;
|
140
|
-
if ((0, types_1.isAnyOrUnknown)(srcSubtype)) {
|
141
|
-
return srcSubtype;
|
142
|
-
}
|
143
|
-
let constraintIndexUsed;
|
144
|
-
destType.details.constraints.forEach((constraint, i) => {
|
145
|
-
const adjustedConstraint = types_1.TypeBase.isInstantiable(destType)
|
146
|
-
? (0, typeUtils_1.convertToInstantiable)(constraint)
|
147
|
-
: constraint;
|
148
|
-
if (evaluator.assignType(adjustedConstraint, srcSubtype,
|
149
|
-
/* diag */ undefined,
|
150
|
-
/* destTypeVarContext */ undefined,
|
151
|
-
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
152
|
-
if (!constrainedSubtype ||
|
153
|
-
evaluator.assignType(types_1.TypeBase.isInstantiable(destType)
|
154
|
-
? (0, typeUtils_1.convertToInstantiable)(constrainedSubtype)
|
155
|
-
: constrainedSubtype, adjustedConstraint,
|
156
|
-
/* diag */ undefined,
|
157
|
-
/* destTypeVarContext */ undefined,
|
158
|
-
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
159
|
-
constrainedSubtype = (0, typeUtils_1.addConditionToType)(constraint, (0, typeUtils_1.getTypeCondition)(srcSubtype));
|
160
|
-
constraintIndexUsed = i;
|
161
|
-
}
|
162
|
-
}
|
163
|
-
});
|
164
|
-
if (!constrainedSubtype) {
|
165
|
-
// We found a source subtype that is not compatible with the dest.
|
166
|
-
// This is OK if we're handling the contravariant case because only
|
167
|
-
// one subtype needs to be assignable in that case.
|
168
|
-
if (!isContravariant) {
|
169
|
-
isCompatible = false;
|
170
|
-
}
|
171
|
-
}
|
172
|
-
// If this subtype isn't conditional, make sure it maps to the same
|
173
|
-
// constraint index as previous unconditional subtypes.
|
174
|
-
if (constraintIndexUsed !== undefined && !(0, typeUtils_1.getTypeCondition)(srcSubtype)) {
|
175
|
-
if (unconditionalConstraintIndex !== undefined &&
|
176
|
-
unconditionalConstraintIndex !== constraintIndexUsed) {
|
177
|
-
isCompatible = false;
|
178
|
-
}
|
179
|
-
unconditionalConstraintIndex = constraintIndexUsed;
|
180
|
-
}
|
181
|
-
return constrainedSubtype;
|
182
|
-
});
|
183
|
-
if ((0, types_1.isNever)(constrainedType) || !isCompatible) {
|
184
|
-
constrainedType = undefined;
|
185
|
-
}
|
186
|
-
// If the type is a union, see if the entire union is assignable to one
|
187
|
-
// of the constraints.
|
188
|
-
if (!constrainedType && (0, types_1.isUnion)(concreteSrcType)) {
|
189
|
-
constrainedType = destType.details.constraints.find((constraint) => {
|
190
|
-
const adjustedConstraint = types_1.TypeBase.isInstantiable(destType)
|
191
|
-
? (0, typeUtils_1.convertToInstantiable)(constraint)
|
192
|
-
: constraint;
|
193
|
-
return evaluator.assignType(adjustedConstraint, concreteSrcType,
|
194
|
-
/* diag */ undefined,
|
195
|
-
/* destTypeVarContext */ undefined,
|
196
|
-
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount);
|
197
|
-
});
|
198
|
-
}
|
199
|
-
}
|
200
|
-
// If there was no constrained type that was assignable
|
201
|
-
// or there were multiple types that were assignable and they
|
202
|
-
// are not conditional, it's an error.
|
203
|
-
if (!constrainedType) {
|
204
|
-
diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.Localizer.DiagnosticAddendum.typeConstrainedTypeVar().format({
|
205
|
-
type: evaluator.printType(srcType),
|
206
|
-
name: destType.details.name,
|
207
|
-
}));
|
208
|
-
return false;
|
209
|
-
}
|
210
|
-
if (curNarrowTypeBound && !(0, types_1.isAnyOrUnknown)(curNarrowTypeBound)) {
|
211
|
-
if (!evaluator.assignType(curNarrowTypeBound, constrainedType,
|
212
|
-
/* diag */ undefined,
|
213
|
-
/* destTypeVarContext */ undefined,
|
214
|
-
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
215
|
-
// Handle the case where one of the constrained types is a wider
|
216
|
-
// version of another constrained type that was previously assigned
|
217
|
-
// to the type variable.
|
218
|
-
if (evaluator.assignType(constrainedType, curNarrowTypeBound,
|
219
|
-
/* diag */ undefined,
|
220
|
-
/* destTypeVarContext */ undefined,
|
221
|
-
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
222
|
-
if (!typeVarContext.isLocked() && isTypeVarInScope) {
|
223
|
-
updateTypeVarType(evaluator, typeVarContext, destType, constrainedType, curWideTypeBound);
|
224
|
-
}
|
225
|
-
}
|
226
|
-
else {
|
227
|
-
diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.Localizer.DiagnosticAddendum.typeConstrainedTypeVar().format({
|
228
|
-
type: evaluator.printType(constrainedType),
|
229
|
-
name: evaluator.printType(curNarrowTypeBound),
|
230
|
-
}));
|
231
|
-
return false;
|
232
|
-
}
|
233
|
-
}
|
234
|
-
}
|
235
|
-
else {
|
236
|
-
// Assign the type to the type var.
|
237
|
-
if (!typeVarContext.isLocked() && isTypeVarInScope) {
|
238
|
-
updateTypeVarType(evaluator, typeVarContext, destType, constrainedType, curWideTypeBound);
|
239
|
-
}
|
240
|
-
}
|
241
|
-
return true;
|
126
|
+
return assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, typeVarContext, flags, isTypeVarInScope, recursionCount);
|
242
127
|
}
|
243
128
|
// Handle the unconstrained (but possibly bound) case.
|
129
|
+
const curEntry = typeVarContext.getPrimarySignature().getTypeVar(destType);
|
130
|
+
let curWideTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.wideBound;
|
131
|
+
if (!curWideTypeBound && !destType.details.isSynthesizedSelf) {
|
132
|
+
curWideTypeBound = destType.details.boundType;
|
133
|
+
}
|
134
|
+
const curNarrowTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.narrowBound;
|
244
135
|
let newNarrowTypeBound = curNarrowTypeBound;
|
245
136
|
let newWideTypeBound = curWideTypeBound;
|
246
137
|
const diagAddendum = diag ? new diagnostic_1.DiagnosticAddendum() : undefined;
|
@@ -284,7 +175,7 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
284
175
|
// narrow type bound, wide type bound or both. Don't overwrite
|
285
176
|
// an existing entry.
|
286
177
|
if (!curEntry) {
|
287
|
-
if (
|
178
|
+
if (isInvariant) {
|
288
179
|
newNarrowTypeBound = adjSrcType;
|
289
180
|
newWideTypeBound = adjSrcType;
|
290
181
|
}
|
@@ -298,7 +189,7 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
298
189
|
}
|
299
190
|
else if (isContravariant) {
|
300
191
|
// Update the wide type bound.
|
301
|
-
if (!curWideTypeBound) {
|
192
|
+
if (!curWideTypeBound || (0, types_1.isTypeSame)(destType, curWideTypeBound)) {
|
302
193
|
newWideTypeBound = adjSrcType;
|
303
194
|
}
|
304
195
|
else if (!(0, types_1.isTypeSame)(curWideTypeBound, adjSrcType, {}, recursionCount)) {
|
@@ -336,7 +227,7 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
336
227
|
}
|
337
228
|
}
|
338
229
|
else {
|
339
|
-
if (!curNarrowTypeBound) {
|
230
|
+
if (!curNarrowTypeBound || (0, types_1.isTypeSame)(destType, curNarrowTypeBound)) {
|
340
231
|
// There was previously no narrow bound. We've now established one.
|
341
232
|
newNarrowTypeBound = adjSrcType;
|
342
233
|
}
|
@@ -462,6 +353,12 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
462
353
|
if (!typeVarContext.isLocked() && isTypeVarInScope) {
|
463
354
|
updateTypeVarType(evaluator, typeVarContext, destType, newNarrowTypeBound, newWideTypeBound, (flags & (1024 /* PopulatingExpectedType */ | 128 /* RetainLiteralsForTypeVar */)) !== 0);
|
464
355
|
}
|
356
|
+
if (logTypeVarContextUpdates) {
|
357
|
+
const indent = ' '.repeat(recursionCount * 2);
|
358
|
+
console.log(`${indent}`);
|
359
|
+
console.log(`${indent}post-call context #${typeVarContext.getId()}: `);
|
360
|
+
logTypeVarContext(evaluator, typeVarContext, indent);
|
361
|
+
}
|
465
362
|
return true;
|
466
363
|
}
|
467
364
|
exports.assignTypeToTypeVar = assignTypeToTypeVar;
|
@@ -487,6 +384,136 @@ function updateTypeVarType(evaluator, typeVarContext, destType, narrowTypeBound,
|
|
487
384
|
typeVarContext.setTypeVarType(destType, narrowTypeBound, narrowTypeBoundNoLiterals, wideTypeBound);
|
488
385
|
}
|
489
386
|
exports.updateTypeVarType = updateTypeVarType;
|
387
|
+
function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, typeVarContext, flags, isTypeVarInScope, recursionCount) {
|
388
|
+
let constrainedType;
|
389
|
+
const concreteSrcType = evaluator.makeTopLevelTypeVarsConcrete(srcType);
|
390
|
+
const curEntry = typeVarContext.getPrimarySignature().getTypeVar(destType);
|
391
|
+
const curWideTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.wideBound;
|
392
|
+
const curNarrowTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.narrowBound;
|
393
|
+
if ((0, types_1.isTypeVar)(srcType)) {
|
394
|
+
if (evaluator.assignType(destType, concreteSrcType,
|
395
|
+
/* diag */ undefined, new typeVarContext_1.TypeVarContext(destType.scopeId),
|
396
|
+
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
397
|
+
constrainedType = srcType;
|
398
|
+
// If the source and dest are both instantiables (type[T]), then
|
399
|
+
// we need to convert to an instance (T).
|
400
|
+
if (types_1.TypeBase.isInstantiable(srcType)) {
|
401
|
+
constrainedType = (0, typeUtils_1.convertToInstance)(srcType, /* includeSubclasses */ false);
|
402
|
+
}
|
403
|
+
}
|
404
|
+
}
|
405
|
+
else {
|
406
|
+
let isCompatible = true;
|
407
|
+
// Subtypes that are not conditionally dependent on the dest type var
|
408
|
+
// must all map to the same constraint. For example, Union[str, bytes]
|
409
|
+
// cannot be assigned to AnyStr.
|
410
|
+
let unconditionalConstraintIndex;
|
411
|
+
// Find the narrowest constrained type that is compatible.
|
412
|
+
constrainedType = (0, typeUtils_1.mapSubtypes)(concreteSrcType, (srcSubtype) => {
|
413
|
+
let constrainedSubtype;
|
414
|
+
if ((0, types_1.isAnyOrUnknown)(srcSubtype)) {
|
415
|
+
return srcSubtype;
|
416
|
+
}
|
417
|
+
let constraintIndexUsed;
|
418
|
+
destType.details.constraints.forEach((constraint, i) => {
|
419
|
+
const adjustedConstraint = types_1.TypeBase.isInstantiable(destType)
|
420
|
+
? (0, typeUtils_1.convertToInstantiable)(constraint)
|
421
|
+
: constraint;
|
422
|
+
if (evaluator.assignType(adjustedConstraint, srcSubtype,
|
423
|
+
/* diag */ undefined,
|
424
|
+
/* destTypeVarContext */ undefined,
|
425
|
+
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
426
|
+
if (!constrainedSubtype ||
|
427
|
+
evaluator.assignType(types_1.TypeBase.isInstantiable(destType)
|
428
|
+
? (0, typeUtils_1.convertToInstantiable)(constrainedSubtype)
|
429
|
+
: constrainedSubtype, adjustedConstraint,
|
430
|
+
/* diag */ undefined,
|
431
|
+
/* destTypeVarContext */ undefined,
|
432
|
+
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
433
|
+
constrainedSubtype = (0, typeUtils_1.addConditionToType)(constraint, (0, typeUtils_1.getTypeCondition)(srcSubtype));
|
434
|
+
constraintIndexUsed = i;
|
435
|
+
}
|
436
|
+
}
|
437
|
+
});
|
438
|
+
if (!constrainedSubtype) {
|
439
|
+
// We found a source subtype that is not compatible with the dest.
|
440
|
+
// This is OK if we're handling the contravariant case because only
|
441
|
+
// one subtype needs to be assignable in that case.
|
442
|
+
if ((flags & 2 /* ReverseTypeVarMatching */) === 0) {
|
443
|
+
isCompatible = false;
|
444
|
+
}
|
445
|
+
}
|
446
|
+
// If this subtype isn't conditional, make sure it maps to the same
|
447
|
+
// constraint index as previous unconditional subtypes.
|
448
|
+
if (constraintIndexUsed !== undefined && !(0, typeUtils_1.getTypeCondition)(srcSubtype)) {
|
449
|
+
if (unconditionalConstraintIndex !== undefined &&
|
450
|
+
unconditionalConstraintIndex !== constraintIndexUsed) {
|
451
|
+
isCompatible = false;
|
452
|
+
}
|
453
|
+
unconditionalConstraintIndex = constraintIndexUsed;
|
454
|
+
}
|
455
|
+
return constrainedSubtype;
|
456
|
+
});
|
457
|
+
if ((0, types_1.isNever)(constrainedType) || !isCompatible) {
|
458
|
+
constrainedType = undefined;
|
459
|
+
}
|
460
|
+
// If the type is a union, see if the entire union is assignable to one
|
461
|
+
// of the constraints.
|
462
|
+
if (!constrainedType && (0, types_1.isUnion)(concreteSrcType)) {
|
463
|
+
constrainedType = destType.details.constraints.find((constraint) => {
|
464
|
+
const adjustedConstraint = types_1.TypeBase.isInstantiable(destType)
|
465
|
+
? (0, typeUtils_1.convertToInstantiable)(constraint)
|
466
|
+
: constraint;
|
467
|
+
return evaluator.assignType(adjustedConstraint, concreteSrcType,
|
468
|
+
/* diag */ undefined,
|
469
|
+
/* destTypeVarContext */ undefined,
|
470
|
+
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount);
|
471
|
+
});
|
472
|
+
}
|
473
|
+
}
|
474
|
+
// If there was no constrained type that was assignable
|
475
|
+
// or there were multiple types that were assignable and they
|
476
|
+
// are not conditional, it's an error.
|
477
|
+
if (!constrainedType) {
|
478
|
+
diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.Localizer.DiagnosticAddendum.typeConstrainedTypeVar().format({
|
479
|
+
type: evaluator.printType(srcType),
|
480
|
+
name: destType.details.name,
|
481
|
+
}));
|
482
|
+
return false;
|
483
|
+
}
|
484
|
+
if (curNarrowTypeBound && !(0, types_1.isAnyOrUnknown)(curNarrowTypeBound)) {
|
485
|
+
if (!evaluator.assignType(curNarrowTypeBound, constrainedType,
|
486
|
+
/* diag */ undefined,
|
487
|
+
/* destTypeVarContext */ undefined,
|
488
|
+
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
489
|
+
// Handle the case where one of the constrained types is a wider
|
490
|
+
// version of another constrained type that was previously assigned
|
491
|
+
// to the type variable.
|
492
|
+
if (evaluator.assignType(constrainedType, curNarrowTypeBound,
|
493
|
+
/* diag */ undefined,
|
494
|
+
/* destTypeVarContext */ undefined,
|
495
|
+
/* srcTypeVarContext */ undefined, 0 /* Default */, recursionCount)) {
|
496
|
+
if (!typeVarContext.isLocked() && isTypeVarInScope) {
|
497
|
+
updateTypeVarType(evaluator, typeVarContext, destType, constrainedType, curWideTypeBound);
|
498
|
+
}
|
499
|
+
}
|
500
|
+
else {
|
501
|
+
diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.Localizer.DiagnosticAddendum.typeConstrainedTypeVar().format({
|
502
|
+
type: evaluator.printType(constrainedType),
|
503
|
+
name: evaluator.printType(curNarrowTypeBound),
|
504
|
+
}));
|
505
|
+
return false;
|
506
|
+
}
|
507
|
+
}
|
508
|
+
}
|
509
|
+
else {
|
510
|
+
// Assign the type to the type var.
|
511
|
+
if (!typeVarContext.isLocked() && isTypeVarInScope) {
|
512
|
+
updateTypeVarType(evaluator, typeVarContext, destType, constrainedType, curWideTypeBound);
|
513
|
+
}
|
514
|
+
}
|
515
|
+
return true;
|
516
|
+
}
|
490
517
|
function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContext, recursionCount = 0) {
|
491
518
|
let isAssignable = true;
|
492
519
|
typeVarContext.doForEachSignature((signatureContext) => {
|
@@ -503,7 +530,7 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
|
|
503
530
|
}
|
504
531
|
else {
|
505
532
|
if (!typeVarContext.isLocked() && typeVarContext.hasSolveForScope(destType.scopeId)) {
|
506
|
-
|
533
|
+
signatureContext.setTypeVarType(destType, (0, typeUtils_1.convertTypeToParamSpecValue)(srcType));
|
507
534
|
}
|
508
535
|
return;
|
509
536
|
}
|
@@ -517,42 +544,51 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
|
|
517
544
|
isNameSynthesized: p.isNameSynthesized,
|
518
545
|
hasDefault: !!p.hasDefault,
|
519
546
|
defaultValueExpression: p.defaultValueExpression,
|
547
|
+
hasDeclaredType: p.hasDeclaredType,
|
520
548
|
type: types_1.FunctionType.getEffectiveParameterType(functionSrcType, index),
|
521
549
|
};
|
522
550
|
return param;
|
523
551
|
});
|
552
|
+
const newFunction = types_1.FunctionType.createInstance('', '', '', srcType.details.flags | 65536 /* ParamSpecValue */);
|
553
|
+
parameters.forEach((param) => {
|
554
|
+
types_1.FunctionType.addParameter(newFunction, param);
|
555
|
+
});
|
556
|
+
newFunction.details.typeVarScopeId = srcType.details.typeVarScopeId;
|
557
|
+
newFunction.details.constructorTypeVarScopeId = srcType.details.constructorTypeVarScopeId;
|
558
|
+
newFunction.details.paramSpecTypeVarScopeId = srcType.details.paramSpecTypeVarScopeId;
|
559
|
+
newFunction.details.docString = srcType.details.docString;
|
560
|
+
newFunction.details.deprecatedMessage = srcType.details.deprecatedMessage;
|
561
|
+
newFunction.details.paramSpec = srcType.details.paramSpec;
|
562
|
+
let updateContextWithNewFunction = false;
|
524
563
|
const existingType = signatureContext.getParamSpecType(destType);
|
525
564
|
if (existingType) {
|
526
565
|
if ((0, types_1.isTypeSame)((_a = existingType.details.paramSpec) !== null && _a !== void 0 ? _a : types_1.NoneType.createInstance(), (_b = srcType.details.paramSpec) !== null && _b !== void 0 ? _b : types_1.NoneType.createInstance())) {
|
527
566
|
// Convert the remaining portion of the signature to a function
|
528
567
|
// for comparison purposes.
|
529
568
|
const existingFunction = (0, typeUtils_1.convertParamSpecValueToType)(existingType, /* omitParamSpec */ true);
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
569
|
+
// Should we narrow the type?
|
570
|
+
if (evaluator.assignType(existingFunction, newFunction,
|
571
|
+
/* diag */ undefined,
|
572
|
+
/* destTypeVarContext */ undefined,
|
573
|
+
/* srcTypeVarContext */ undefined, 32 /* SkipFunctionReturnTypeCheck */, recursionCount)) {
|
574
|
+
updateContextWithNewFunction = true;
|
575
|
+
}
|
576
|
+
else if (evaluator.assignType(newFunction, existingFunction,
|
536
577
|
/* diag */ undefined,
|
537
578
|
/* destTypeVarContext */ undefined,
|
538
579
|
/* srcTypeVarContext */ undefined, 32 /* SkipFunctionReturnTypeCheck */, recursionCount)) {
|
580
|
+
// The existing function is already narrower than the new function, so
|
581
|
+
// no need to narrow it further.
|
539
582
|
return;
|
540
583
|
}
|
541
584
|
}
|
542
585
|
}
|
543
586
|
else {
|
587
|
+
updateContextWithNewFunction = true;
|
588
|
+
}
|
589
|
+
if (updateContextWithNewFunction) {
|
544
590
|
if (!typeVarContext.isLocked() && typeVarContext.hasSolveForScope(destType.scopeId)) {
|
545
|
-
|
546
|
-
parameters.forEach((param) => {
|
547
|
-
types_1.FunctionType.addParameter(newFunction, param);
|
548
|
-
});
|
549
|
-
newFunction.details.typeVarScopeId = srcType.details.typeVarScopeId;
|
550
|
-
newFunction.details.constructorTypeVarScopeId = srcType.details.constructorTypeVarScopeId;
|
551
|
-
newFunction.details.paramSpecTypeVarScopeId = srcType.details.paramSpecTypeVarScopeId;
|
552
|
-
newFunction.details.docString = srcType.details.docString;
|
553
|
-
newFunction.details.deprecatedMessage = srcType.details.deprecatedMessage;
|
554
|
-
newFunction.details.paramSpec = srcType.details.paramSpec;
|
555
|
-
typeVarContext.setTypeVarType(destType, newFunction);
|
591
|
+
signatureContext.setTypeVarType(destType, newFunction);
|
556
592
|
}
|
557
593
|
return;
|
558
594
|
}
|
@@ -566,6 +602,12 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
|
|
566
602
|
}));
|
567
603
|
isAssignable = false;
|
568
604
|
});
|
605
|
+
if (logTypeVarContextUpdates) {
|
606
|
+
const indent = ' '.repeat(recursionCount * 2);
|
607
|
+
console.log(`${indent}`);
|
608
|
+
console.log(`${indent}post-call typeVarContext: `);
|
609
|
+
logTypeVarContext(evaluator, typeVarContext, indent);
|
610
|
+
}
|
569
611
|
return isAssignable;
|
570
612
|
}
|
571
613
|
// In cases where the expected type is a specialized base class of the
|
@@ -628,6 +670,9 @@ function populateTypeVarContextBasedOnExpectedType(evaluator, type, expectedType
|
|
628
670
|
const synthExpectedTypeArgs = types_1.ClassType.getTypeParameters(expectedType).map((typeParam, index) => {
|
629
671
|
const typeVar = types_1.TypeVarType.createInstance(`__dest${index}`);
|
630
672
|
typeVar.details.isSynthesized = true;
|
673
|
+
if (typeParam.details.isParamSpec) {
|
674
|
+
typeVar.details.isParamSpec = true;
|
675
|
+
}
|
631
676
|
// Use invariance here so we set the narrow and wide values on the TypeVar.
|
632
677
|
typeVar.details.declaredVariance = 2 /* Invariant */;
|
633
678
|
typeVar.scopeId = expectedTypeScopeId;
|
@@ -636,11 +681,14 @@ function populateTypeVarContextBasedOnExpectedType(evaluator, type, expectedType
|
|
636
681
|
const genericExpectedType = types_1.ClassType.cloneForSpecialization(expectedType, synthExpectedTypeArgs,
|
637
682
|
/* isTypeArgumentExplicit */ true);
|
638
683
|
// For each type param in the target type, create a placeholder type variable.
|
639
|
-
const typeArgs = types_1.ClassType.getTypeParameters(type).map((
|
684
|
+
const typeArgs = types_1.ClassType.getTypeParameters(type).map((typeParam, index) => {
|
640
685
|
const typeVar = types_1.TypeVarType.createInstance(`__source${index}`);
|
641
686
|
typeVar.details.isSynthesized = true;
|
642
687
|
typeVar.details.synthesizedIndex = index;
|
643
688
|
typeVar.details.isExemptFromBoundCheck = true;
|
689
|
+
if (typeParam.details.isParamSpec) {
|
690
|
+
typeVar.details.isParamSpec = true;
|
691
|
+
}
|
644
692
|
return types_1.TypeVarType.cloneAsInScopePlaceholder(typeVar);
|
645
693
|
});
|
646
694
|
const specializedType = types_1.ClassType.cloneForSpecialization(type, typeArgs, /* isTypeArgumentExplicit */ true);
|
@@ -654,21 +702,26 @@ function populateTypeVarContextBasedOnExpectedType(evaluator, type, expectedType
|
|
654
702
|
const otherSubtypes = [];
|
655
703
|
// If the resulting type is a union, try to find a matching type var and move
|
656
704
|
// the remaining subtypes to the "otherSubtypes" array.
|
657
|
-
if (synthTypeVar
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
705
|
+
if (synthTypeVar) {
|
706
|
+
if (typeVar.details.isParamSpec && (0, types_1.isFunction)(synthTypeVar)) {
|
707
|
+
synthTypeVar = (0, typeUtils_1.convertParamSpecValueToType)(synthTypeVar);
|
708
|
+
}
|
709
|
+
if ((0, types_1.isUnion)(synthTypeVar)) {
|
710
|
+
let foundSynthTypeVar;
|
711
|
+
synthTypeVar.subtypes.forEach((subtype) => {
|
712
|
+
if ((0, types_1.isTypeVar)(subtype) &&
|
713
|
+
subtype.details.isSynthesized &&
|
714
|
+
subtype.details.synthesizedIndex !== undefined &&
|
715
|
+
!foundSynthTypeVar) {
|
716
|
+
foundSynthTypeVar = subtype;
|
717
|
+
}
|
718
|
+
else {
|
719
|
+
otherSubtypes.push(subtype);
|
720
|
+
}
|
721
|
+
});
|
722
|
+
if (foundSynthTypeVar) {
|
723
|
+
synthTypeVar = foundSynthTypeVar;
|
668
724
|
}
|
669
|
-
});
|
670
|
-
if (foundSynthTypeVar) {
|
671
|
-
synthTypeVar = foundSynthTypeVar;
|
672
725
|
}
|
673
726
|
}
|
674
727
|
// Is this one of the synthesized type vars we allocated above? If so,
|
@@ -762,4 +815,45 @@ function stripLiteralValueForUnpackedTuple(evaluator, type) {
|
|
762
815
|
}
|
763
816
|
return (0, typeUtils_1.specializeTupleClass)(type, tupleTypeArgs, /* isTypeArgumentExplicit */ true, /* isUnpackedTuple */ true);
|
764
817
|
}
|
818
|
+
// This function is used for debugging only. It dumps the current contents of
|
819
|
+
// the TypeVarContext to the console.
|
820
|
+
function logTypeVarContext(evaluator, typeVarContext, indent) {
|
821
|
+
const signatureContextCount = typeVarContext.getSignatureContexts().length;
|
822
|
+
if (signatureContextCount === 0) {
|
823
|
+
console.log(`${indent} no signatures`);
|
824
|
+
}
|
825
|
+
else if (signatureContextCount === 1) {
|
826
|
+
logTypeVarSignatureContext(evaluator, typeVarContext.getSignatureContexts()[0], `${indent} `);
|
827
|
+
}
|
828
|
+
else {
|
829
|
+
typeVarContext.doForEachSignatureContext((context, signatureIndex) => {
|
830
|
+
console.log(`${indent} signature ${signatureIndex}`);
|
831
|
+
logTypeVarSignatureContext(evaluator, context, `${indent} `);
|
832
|
+
});
|
833
|
+
}
|
834
|
+
}
|
835
|
+
function logTypeVarSignatureContext(evaluator, context, indent) {
|
836
|
+
let loggedConstraint = false;
|
837
|
+
context.getTypeVars().forEach((entry) => {
|
838
|
+
const typeVarName = `${indent}${entry.typeVar.details.name}`;
|
839
|
+
// Log the narrow and wide bounds.
|
840
|
+
if (entry.narrowBound && entry.wideBound && (0, types_1.isTypeSame)(entry.narrowBound, entry.wideBound)) {
|
841
|
+
console.log(`${typeVarName} = ${evaluator.printType(entry.narrowBound)}`);
|
842
|
+
loggedConstraint = true;
|
843
|
+
}
|
844
|
+
else {
|
845
|
+
if (entry.narrowBound) {
|
846
|
+
console.log(`${typeVarName} ≤ ${evaluator.printType(entry.narrowBound)}`);
|
847
|
+
loggedConstraint = true;
|
848
|
+
}
|
849
|
+
if (entry.wideBound) {
|
850
|
+
console.log(`${typeVarName} ≥ ${evaluator.printType(entry.wideBound)}`);
|
851
|
+
loggedConstraint = true;
|
852
|
+
}
|
853
|
+
}
|
854
|
+
});
|
855
|
+
if (!loggedConstraint) {
|
856
|
+
console.log(`${indent}no constraints`);
|
857
|
+
}
|
858
|
+
}
|
765
859
|
//# sourceMappingURL=constraintSolver.js.map
|