@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.
Files changed (145) hide show
  1. package/dist/analyzer/checker.js +33 -37
  2. package/dist/analyzer/checker.js.map +1 -1
  3. package/dist/analyzer/codeFlowEngine.js +2 -2
  4. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  5. package/dist/analyzer/constraintSolver.js +262 -168
  6. package/dist/analyzer/constraintSolver.js.map +1 -1
  7. package/dist/analyzer/constructors.js +3 -4
  8. package/dist/analyzer/constructors.js.map +1 -1
  9. package/dist/analyzer/decorators.js +3 -1
  10. package/dist/analyzer/decorators.js.map +1 -1
  11. package/dist/analyzer/parseTreeUtils.d.ts +1 -1
  12. package/dist/analyzer/patternMatching.js +4 -0
  13. package/dist/analyzer/patternMatching.js.map +1 -1
  14. package/dist/analyzer/program.js +7 -1
  15. package/dist/analyzer/program.js.map +1 -1
  16. package/dist/analyzer/properties.d.ts +2 -2
  17. package/dist/analyzer/properties.js +10 -4
  18. package/dist/analyzer/properties.js.map +1 -1
  19. package/dist/analyzer/protocols.js +119 -174
  20. package/dist/analyzer/protocols.js.map +1 -1
  21. package/dist/analyzer/service.js +13 -13
  22. package/dist/analyzer/service.js.map +1 -1
  23. package/dist/analyzer/sourceFile.d.ts +3 -2
  24. package/dist/analyzer/sourceFile.js +31 -11
  25. package/dist/analyzer/sourceFile.js.map +1 -1
  26. package/dist/analyzer/sourceFileInfo.d.ts +4 -4
  27. package/dist/analyzer/sourceFileInfo.js +2 -0
  28. package/dist/analyzer/sourceFileInfo.js.map +1 -1
  29. package/dist/analyzer/staticExpressions.js +2 -1
  30. package/dist/analyzer/staticExpressions.js.map +1 -1
  31. package/dist/analyzer/typeEvaluator.js +138 -123
  32. package/dist/analyzer/typeEvaluator.js.map +1 -1
  33. package/dist/analyzer/typeEvaluatorTypes.d.ts +4 -3
  34. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  35. package/dist/analyzer/typeGuards.js +101 -33
  36. package/dist/analyzer/typeGuards.js.map +1 -1
  37. package/dist/analyzer/typePrinter.js +4 -1
  38. package/dist/analyzer/typePrinter.js.map +1 -1
  39. package/dist/analyzer/typeUtils.d.ts +13 -2
  40. package/dist/analyzer/typeUtils.js +130 -51
  41. package/dist/analyzer/typeUtils.js.map +1 -1
  42. package/dist/analyzer/typeVarContext.d.ts +4 -1
  43. package/dist/analyzer/typeVarContext.js +7 -2
  44. package/dist/analyzer/typeVarContext.js.map +1 -1
  45. package/dist/analyzer/typedDicts.js +99 -27
  46. package/dist/analyzer/typedDicts.js.map +1 -1
  47. package/dist/analyzer/types.d.ts +6 -2
  48. package/dist/analyzer/types.js +49 -17
  49. package/dist/analyzer/types.js.map +1 -1
  50. package/dist/backgroundThreadBase.js +5 -1
  51. package/dist/backgroundThreadBase.js.map +1 -1
  52. package/dist/common/configOptions.d.ts +2 -1
  53. package/dist/common/configOptions.js +9 -5
  54. package/dist/common/configOptions.js.map +1 -1
  55. package/dist/common/extensibility.d.ts +0 -2
  56. package/dist/common/extensibility.js.map +1 -1
  57. package/dist/common/fileSystem.d.ts +9 -4
  58. package/dist/common/fileSystem.js +8 -1
  59. package/dist/common/fileSystem.js.map +1 -1
  60. package/dist/common/pathUtils.d.ts +8 -5
  61. package/dist/common/pathUtils.js +90 -33
  62. package/dist/common/pathUtils.js.map +1 -1
  63. package/dist/common/realFileSystem.d.ts +7 -1
  64. package/dist/common/realFileSystem.js +35 -22
  65. package/dist/common/realFileSystem.js.map +1 -1
  66. package/dist/common/serviceProviderExtensions.d.ts +3 -4
  67. package/dist/common/serviceProviderExtensions.js +3 -6
  68. package/dist/common/serviceProviderExtensions.js.map +1 -1
  69. package/dist/common/uriParser.d.ts +10 -1
  70. package/dist/common/uriParser.js.map +1 -1
  71. package/dist/languageServerBase.d.ts +4 -4
  72. package/dist/languageServerBase.js +3 -17
  73. package/dist/languageServerBase.js.map +1 -1
  74. package/dist/languageService/autoImporter.d.ts +1 -1
  75. package/dist/languageService/completionProvider.d.ts +2 -2
  76. package/dist/languageService/completionProvider.js +20 -23
  77. package/dist/languageService/completionProvider.js.map +1 -1
  78. package/dist/languageService/hoverProvider.d.ts +6 -2
  79. package/dist/languageService/hoverProvider.js +33 -65
  80. package/dist/languageService/hoverProvider.js.map +1 -1
  81. package/dist/languageService/navigationUtils.d.ts +1 -1
  82. package/dist/languageService/navigationUtils.js +2 -2
  83. package/dist/languageService/navigationUtils.js.map +1 -1
  84. package/dist/languageService/referencesProvider.d.ts +9 -2
  85. package/dist/languageService/referencesProvider.js +19 -12
  86. package/dist/languageService/referencesProvider.js.map +1 -1
  87. package/dist/languageService/tooltipUtils.js +1 -3
  88. package/dist/languageService/tooltipUtils.js.map +1 -1
  89. package/dist/localization/localize.d.ts +4 -3
  90. package/dist/localization/localize.js +1 -1
  91. package/dist/localization/localize.js.map +1 -1
  92. package/dist/localization/package.nls.cs.json +7 -1
  93. package/dist/localization/package.nls.de.json +7 -1
  94. package/dist/localization/package.nls.en-us.json +1 -1
  95. package/dist/localization/package.nls.es.json +7 -1
  96. package/dist/localization/package.nls.fr.json +7 -1
  97. package/dist/localization/package.nls.it.json +7 -1
  98. package/dist/localization/package.nls.ja.json +7 -1
  99. package/dist/localization/package.nls.ko.json +7 -1
  100. package/dist/localization/package.nls.pl.json +7 -1
  101. package/dist/localization/package.nls.pt-br.json +7 -1
  102. package/dist/localization/package.nls.qps-ploc.json +7 -1
  103. package/dist/localization/package.nls.ru.json +7 -1
  104. package/dist/localization/package.nls.tr.json +7 -1
  105. package/dist/localization/package.nls.zh-cn.json +7 -1
  106. package/dist/localization/package.nls.zh-tw.json +7 -1
  107. package/dist/pyright.js +2 -1
  108. package/dist/pyright.js.map +1 -1
  109. package/dist/pyrightFileSystem.d.ts +1 -16
  110. package/dist/pyrightFileSystem.js +1 -60
  111. package/dist/pyrightFileSystem.js.map +1 -1
  112. package/dist/readonlyAugmentedFileSystem.d.ts +1 -4
  113. package/dist/readonlyAugmentedFileSystem.js +0 -10
  114. package/dist/readonlyAugmentedFileSystem.js.map +1 -1
  115. package/dist/server.js +2 -1
  116. package/dist/server.js.map +1 -1
  117. package/dist/tests/config.test.js +5 -3
  118. package/dist/tests/config.test.js.map +1 -1
  119. package/dist/tests/fourslash/completions.indexer.keys.getitem.fourslash.js +56 -10
  120. package/dist/tests/fourslash/completions.indexer.keys.getitem.fourslash.js.map +1 -1
  121. package/dist/tests/harness/fourslash/testState.d.ts +5 -2
  122. package/dist/tests/harness/fourslash/testState.js +13 -14
  123. package/dist/tests/harness/fourslash/testState.js.map +1 -1
  124. package/dist/tests/harness/vfs/filesystem.d.ts +2 -2
  125. package/dist/tests/harness/vfs/filesystem.js +4 -0
  126. package/dist/tests/harness/vfs/filesystem.js.map +1 -1
  127. package/dist/tests/harness/vfs/pathValidation.js +10 -1
  128. package/dist/tests/harness/vfs/pathValidation.js.map +1 -1
  129. package/dist/tests/importResolver.test.js +0 -9
  130. package/dist/tests/importResolver.test.js.map +1 -1
  131. package/dist/tests/pathUtils.test.js +2 -2
  132. package/dist/tests/pathUtils.test.js.map +1 -1
  133. package/dist/tests/pyrightFileSystem.test.js +0 -20
  134. package/dist/tests/pyrightFileSystem.test.js.map +1 -1
  135. package/dist/tests/typeEvaluator1.test.js +4 -0
  136. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  137. package/dist/tests/typeEvaluator2.test.js +14 -2
  138. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  139. package/dist/tests/typeEvaluator3.test.js +5 -1
  140. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  141. package/dist/tests/typeEvaluator4.test.js +10 -2
  142. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  143. package/dist/tests/typeEvaluator5.test.js +7 -1
  144. package/dist/tests/typeEvaluator5.test.js.map +1 -1
  145. 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) && (flags & 1 /* EnforceInvariance */) === 0) {
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
- let constrainedType;
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 ((flags & 1 /* EnforceInvariance */) !== 0) {
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
- typeVarContext.setTypeVarType(destType, (0, typeUtils_1.convertTypeToParamSpecValue)(srcType));
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
- const assignedFunction = types_1.FunctionType.createInstance('', '', '', srcType.details.flags);
531
- parameters.forEach((param) => {
532
- types_1.FunctionType.addParameter(assignedFunction, param);
533
- });
534
- assignedFunction.details.typeVarScopeId = srcType.details.typeVarScopeId;
535
- if (evaluator.assignType(existingFunction, assignedFunction,
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
- const newFunction = types_1.FunctionType.createInstance('', '', '', srcType.details.flags);
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((_, index) => {
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 && (0, types_1.isUnion)(synthTypeVar)) {
658
- let foundSynthTypeVar;
659
- synthTypeVar.subtypes.forEach((subtype) => {
660
- if ((0, types_1.isTypeVar)(subtype) &&
661
- subtype.details.isSynthesized &&
662
- subtype.details.synthesizedIndex !== undefined &&
663
- !foundSynthTypeVar) {
664
- foundSynthTypeVar = subtype;
665
- }
666
- else {
667
- otherSubtypes.push(subtype);
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