@zzzen/pyright-internal 1.2.0-dev.20240721 → 1.2.0-dev.20240804

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 (228) hide show
  1. package/dist/analyzer/analyzerNodeInfo.js +2 -2
  2. package/dist/analyzer/analyzerNodeInfo.js.map +1 -1
  3. package/dist/analyzer/binder.js +15 -12
  4. package/dist/analyzer/binder.js.map +1 -1
  5. package/dist/analyzer/cacheManager.js +3 -0
  6. package/dist/analyzer/cacheManager.js.map +1 -1
  7. package/dist/analyzer/checker.d.ts +5 -3
  8. package/dist/analyzer/checker.js +238 -193
  9. package/dist/analyzer/checker.js.map +1 -1
  10. package/dist/analyzer/codeFlowEngine.d.ts +2 -2
  11. package/dist/analyzer/codeFlowEngine.js +53 -46
  12. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  13. package/dist/analyzer/codeFlowTypes.js +1 -1
  14. package/dist/analyzer/codeFlowTypes.js.map +1 -1
  15. package/dist/analyzer/constraintSolution.d.ts +21 -0
  16. package/dist/analyzer/constraintSolution.js +71 -0
  17. package/dist/analyzer/constraintSolution.js.map +1 -0
  18. package/dist/analyzer/constraintSolver.d.ts +10 -6
  19. package/dist/analyzer/constraintSolver.js +520 -462
  20. package/dist/analyzer/constraintSolver.js.map +1 -1
  21. package/dist/analyzer/constraintTracker.d.ts +44 -0
  22. package/dist/analyzer/constraintTracker.js +230 -0
  23. package/dist/analyzer/constraintTracker.js.map +1 -0
  24. package/dist/analyzer/constructorTransform.d.ts +2 -2
  25. package/dist/analyzer/constructorTransform.js +25 -25
  26. package/dist/analyzer/constructorTransform.js.map +1 -1
  27. package/dist/analyzer/constructors.d.ts +3 -3
  28. package/dist/analyzer/constructors.js +80 -64
  29. package/dist/analyzer/constructors.js.map +1 -1
  30. package/dist/analyzer/dataClasses.d.ts +2 -2
  31. package/dist/analyzer/dataClasses.js +87 -61
  32. package/dist/analyzer/dataClasses.js.map +1 -1
  33. package/dist/analyzer/declaration.d.ts +9 -9
  34. package/dist/analyzer/declaration.js +9 -9
  35. package/dist/analyzer/declaration.js.map +1 -1
  36. package/dist/analyzer/declarationUtils.d.ts +1 -1
  37. package/dist/analyzer/declarationUtils.js +6 -6
  38. package/dist/analyzer/declarationUtils.js.map +1 -1
  39. package/dist/analyzer/decorators.js +5 -5
  40. package/dist/analyzer/decorators.js.map +1 -1
  41. package/dist/analyzer/docStringConversion.js +2 -2
  42. package/dist/analyzer/docStringConversion.js.map +1 -1
  43. package/dist/analyzer/enums.d.ts +2 -2
  44. package/dist/analyzer/enums.js +6 -6
  45. package/dist/analyzer/enums.js.map +1 -1
  46. package/dist/analyzer/functionTransform.d.ts +2 -2
  47. package/dist/analyzer/functionTransform.js +5 -5
  48. package/dist/analyzer/functionTransform.js.map +1 -1
  49. package/dist/analyzer/importResolver.js +5 -3
  50. package/dist/analyzer/importResolver.js.map +1 -1
  51. package/dist/analyzer/namedTuples.d.ts +3 -3
  52. package/dist/analyzer/namedTuples.js +21 -22
  53. package/dist/analyzer/namedTuples.js.map +1 -1
  54. package/dist/analyzer/operations.d.ts +1 -2
  55. package/dist/analyzer/operations.js +105 -82
  56. package/dist/analyzer/operations.js.map +1 -1
  57. package/dist/analyzer/packageTypeVerifier.js +16 -12
  58. package/dist/analyzer/packageTypeVerifier.js.map +1 -1
  59. package/dist/analyzer/parameterUtils.d.ts +12 -12
  60. package/dist/analyzer/parameterUtils.js +67 -69
  61. package/dist/analyzer/parameterUtils.js.map +1 -1
  62. package/dist/analyzer/parseTreeUtils.d.ts +6 -6
  63. package/dist/analyzer/parseTreeUtils.js +22 -22
  64. package/dist/analyzer/parseTreeUtils.js.map +1 -1
  65. package/dist/analyzer/patternMatching.js +122 -101
  66. package/dist/analyzer/patternMatching.js.map +1 -1
  67. package/dist/analyzer/program.js +11 -4
  68. package/dist/analyzer/program.js.map +1 -1
  69. package/dist/analyzer/properties.d.ts +3 -2
  70. package/dist/analyzer/properties.js +27 -27
  71. package/dist/analyzer/properties.js.map +1 -1
  72. package/dist/analyzer/protocols.d.ts +3 -3
  73. package/dist/analyzer/protocols.js +58 -57
  74. package/dist/analyzer/protocols.js.map +1 -1
  75. package/dist/analyzer/pythonPathUtils.js +1 -1
  76. package/dist/analyzer/pythonPathUtils.js.map +1 -1
  77. package/dist/analyzer/service.d.ts +3 -7
  78. package/dist/analyzer/service.js +28 -30
  79. package/dist/analyzer/service.js.map +1 -1
  80. package/dist/analyzer/serviceUtils.d.ts +8 -0
  81. package/dist/analyzer/serviceUtils.js +31 -0
  82. package/dist/analyzer/serviceUtils.js.map +1 -0
  83. package/dist/analyzer/sourceFile.js +5 -19
  84. package/dist/analyzer/sourceFile.js.map +1 -1
  85. package/dist/analyzer/sourceMapper.d.ts +1 -1
  86. package/dist/analyzer/sourceMapper.js +4 -4
  87. package/dist/analyzer/sourceMapper.js.map +1 -1
  88. package/dist/analyzer/staticExpressions.js +1 -1
  89. package/dist/analyzer/staticExpressions.js.map +1 -1
  90. package/dist/analyzer/tracePrinter.js +4 -4
  91. package/dist/analyzer/tracePrinter.js.map +1 -1
  92. package/dist/analyzer/tuples.d.ts +9 -0
  93. package/dist/analyzer/tuples.js +253 -0
  94. package/dist/analyzer/tuples.js.map +1 -0
  95. package/dist/analyzer/typeComplexity.d.ts +2 -0
  96. package/dist/analyzer/typeComplexity.js +94 -0
  97. package/dist/analyzer/typeComplexity.js.map +1 -0
  98. package/dist/analyzer/typeEvaluator.js +1758 -1979
  99. package/dist/analyzer/typeEvaluator.js.map +1 -1
  100. package/dist/analyzer/typeEvaluatorTypes.d.ts +69 -45
  101. package/dist/analyzer/typeEvaluatorTypes.js +7 -1
  102. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  103. package/dist/analyzer/typeGuards.js +157 -121
  104. package/dist/analyzer/typeGuards.js.map +1 -1
  105. package/dist/analyzer/typePrinter.d.ts +1 -1
  106. package/dist/analyzer/typePrinter.js +64 -61
  107. package/dist/analyzer/typePrinter.js.map +1 -1
  108. package/dist/analyzer/typeStubWriter.d.ts +3 -3
  109. package/dist/analyzer/typeStubWriter.js +15 -15
  110. package/dist/analyzer/typeStubWriter.js.map +1 -1
  111. package/dist/analyzer/typeUtils.d.ts +45 -41
  112. package/dist/analyzer/typeUtils.js +511 -748
  113. package/dist/analyzer/typeUtils.js.map +1 -1
  114. package/dist/analyzer/typeWalker.js +4 -4
  115. package/dist/analyzer/typeWalker.js.map +1 -1
  116. package/dist/analyzer/typedDicts.d.ts +4 -4
  117. package/dist/analyzer/typedDicts.js +73 -77
  118. package/dist/analyzer/typedDicts.js.map +1 -1
  119. package/dist/analyzer/types.d.ts +97 -72
  120. package/dist/analyzer/types.js +217 -208
  121. package/dist/analyzer/types.js.map +1 -1
  122. package/dist/commands/dumpFileDebugInfoCommand.js +11 -11
  123. package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
  124. package/dist/common/configOptions.d.ts +1 -0
  125. package/dist/common/configOptions.js +5 -0
  126. package/dist/common/configOptions.js.map +1 -1
  127. package/dist/common/diagnosticRules.d.ts +1 -0
  128. package/dist/common/diagnosticRules.js +1 -0
  129. package/dist/common/diagnosticRules.js.map +1 -1
  130. package/dist/common/fileSystem.d.ts +0 -1
  131. package/dist/common/fileSystem.js.map +1 -1
  132. package/dist/common/languageServerInterface.d.ts +13 -0
  133. package/dist/common/languageServerInterface.js +15 -1
  134. package/dist/common/languageServerInterface.js.map +1 -1
  135. package/dist/common/lspUtils.js +2 -2
  136. package/dist/common/memUtils.d.ts +4 -0
  137. package/dist/common/memUtils.js +33 -2
  138. package/dist/common/memUtils.js.map +1 -1
  139. package/dist/common/serviceKeys.d.ts +3 -0
  140. package/dist/common/serviceKeys.js +2 -0
  141. package/dist/common/serviceKeys.js.map +1 -1
  142. package/dist/common/serviceProviderExtensions.js +7 -0
  143. package/dist/common/serviceProviderExtensions.js.map +1 -1
  144. package/dist/languageServerBase.d.ts +5 -4
  145. package/dist/languageServerBase.js +19 -12
  146. package/dist/languageServerBase.js.map +1 -1
  147. package/dist/languageService/autoImporter.d.ts +3 -2
  148. package/dist/languageService/autoImporter.js +5 -1
  149. package/dist/languageService/autoImporter.js.map +1 -1
  150. package/dist/languageService/completionProvider.d.ts +5 -3
  151. package/dist/languageService/completionProvider.js +39 -38
  152. package/dist/languageService/completionProvider.js.map +1 -1
  153. package/dist/languageService/completionProviderUtils.d.ts +1 -1
  154. package/dist/languageService/completionProviderUtils.js +3 -3
  155. package/dist/languageService/completionProviderUtils.js.map +1 -1
  156. package/dist/languageService/fileWatcherDynamicFeature.js +2 -2
  157. package/dist/languageService/fileWatcherDynamicFeature.js.map +1 -1
  158. package/dist/languageService/hoverProvider.js +3 -3
  159. package/dist/languageService/hoverProvider.js.map +1 -1
  160. package/dist/languageService/referencesProvider.js +2 -2
  161. package/dist/languageService/signatureHelpProvider.js +1 -1
  162. package/dist/languageService/signatureHelpProvider.js.map +1 -1
  163. package/dist/languageService/tooltipUtils.js +3 -3
  164. package/dist/languageService/tooltipUtils.js.map +1 -1
  165. package/dist/localization/localize.d.ts +5 -0
  166. package/dist/localization/localize.js +6 -0
  167. package/dist/localization/localize.js.map +1 -1
  168. package/dist/localization/package.nls.cs.json +5 -1
  169. package/dist/localization/package.nls.de.json +5 -1
  170. package/dist/localization/package.nls.en-us.json +5 -0
  171. package/dist/localization/package.nls.es.json +5 -1
  172. package/dist/localization/package.nls.fr.json +5 -1
  173. package/dist/localization/package.nls.it.json +5 -1
  174. package/dist/localization/package.nls.ja.json +5 -1
  175. package/dist/localization/package.nls.ko.json +5 -1
  176. package/dist/localization/package.nls.pl.json +5 -1
  177. package/dist/localization/package.nls.pt-br.json +5 -1
  178. package/dist/localization/package.nls.qps-ploc.json +5 -1
  179. package/dist/localization/package.nls.ru.json +5 -1
  180. package/dist/localization/package.nls.tr.json +5 -1
  181. package/dist/localization/package.nls.zh-cn.json +5 -1
  182. package/dist/localization/package.nls.zh-tw.json +5 -1
  183. package/dist/parser/parseNodes.d.ts +9 -9
  184. package/dist/parser/parseNodes.js +20 -20
  185. package/dist/parser/parseNodes.js.map +1 -1
  186. package/dist/parser/parser.js +30 -30
  187. package/dist/parser/parser.js.map +1 -1
  188. package/dist/tests/checker.test.js +12 -4
  189. package/dist/tests/checker.test.js.map +1 -1
  190. package/dist/tests/fourslash/signature.builtinDocstrings.fourslash.js +4 -21
  191. package/dist/tests/fourslash/signature.builtinDocstrings.fourslash.js.map +1 -1
  192. package/dist/tests/fourslash/signature.complicated.fourslash.js +1 -1
  193. package/dist/tests/fourslash/signature.complicated.fourslash.js.map +1 -1
  194. package/dist/tests/harness/fourslash/fourSlashParser.js +1 -1
  195. package/dist/tests/harness/fourslash/fourSlashParser.js.map +1 -1
  196. package/dist/tests/harness/fourslash/testStateUtils.js +2 -2
  197. package/dist/tests/harness/fourslash/testStateUtils.js.map +1 -1
  198. package/dist/tests/harness/vfs/filesystem.d.ts +0 -1
  199. package/dist/tests/harness/vfs/filesystem.js +0 -4
  200. package/dist/tests/harness/vfs/filesystem.js.map +1 -1
  201. package/dist/tests/importResolver.test.js +62 -15
  202. package/dist/tests/importResolver.test.js.map +1 -1
  203. package/dist/tests/lsp/languageServerTestUtils.js +1 -1
  204. package/dist/tests/lsp/languageServerTestUtils.js.map +1 -1
  205. package/dist/tests/typeEvaluator1.test.js +1 -1
  206. package/dist/tests/typeEvaluator2.test.js +12 -0
  207. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  208. package/dist/tests/typeEvaluator3.test.js +5 -1
  209. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  210. package/dist/tests/typeEvaluator4.test.js +10 -2
  211. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  212. package/dist/tests/typeEvaluator5.test.js +9 -3
  213. package/dist/tests/typeEvaluator5.test.js.map +1 -1
  214. package/dist/tests/typeEvaluator6.test.js +72 -60
  215. package/dist/tests/typeEvaluator6.test.js.map +1 -1
  216. package/dist/tests/typeEvaluator7.test.js +6 -2
  217. package/dist/tests/typeEvaluator7.test.js.map +1 -1
  218. package/dist/tests/typeEvaluator8.test.js +4 -0
  219. package/dist/tests/typeEvaluator8.test.js.map +1 -1
  220. package/dist/tests/typePrinter.test.js +13 -18
  221. package/dist/tests/typePrinter.test.js.map +1 -1
  222. package/dist/workspaceFactory.d.ts +3 -2
  223. package/dist/workspaceFactory.js +15 -2
  224. package/dist/workspaceFactory.js.map +1 -1
  225. package/package.json +1 -1
  226. package/dist/analyzer/typeVarContext.d.ts +0 -60
  227. package/dist/analyzer/typeVarContext.js +0 -392
  228. package/dist/analyzer/typeVarContext.js.map +0 -1
@@ -10,152 +10,382 @@
10
10
  *
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.addConstraintsForExpectedType = exports.updateTypeVarType = exports.assignTypeToTypeVar = void 0;
13
+ exports.applyUnificationVars = exports.addConstraintsForExpectedType = exports.updateTypeVarType = exports.solveConstraintSet = exports.solveConstraints = exports.assignTypeVar = void 0;
14
14
  const diagnostic_1 = require("../common/diagnostic");
15
15
  const localize_1 = require("../localization/localize");
16
+ const constraintSolution_1 = require("./constraintSolution");
17
+ const constraintTracker_1 = require("./constraintTracker");
16
18
  const typeEvaluatorTypes_1 = require("./typeEvaluatorTypes");
17
19
  const types_1 = require("./types");
18
20
  const typeUtils_1 = require("./typeUtils");
19
- const typeVarContext_1 = require("./typeVarContext");
20
- // As we widen the narrow bound of a type variable, we may end up with
21
+ // As we widen the lower bound of a type variable, we may end up with
21
22
  // many subtypes. For performance reasons, we need to cap this at some
22
23
  // point. This constant determines the cap.
23
- const maxSubtypeCountForTypeVarNarrowBound = 64;
24
- // This debugging switch enables logging of the TypeVarContext before and
24
+ const maxSubtypeCountForTypeVarLowerBound = 64;
25
+ // This debugging switch enables logging of the constraints before and
25
26
  // after it is updated by the constraint solver.
26
- const logTypeVarContextUpdates = false;
27
+ const logConstraintsUpdates = false;
27
28
  // Assigns the source type to the dest type var in the type var context. If an existing
28
29
  // type is already associated with that type var name, it attempts to either widen or
29
30
  // narrow the type (depending on the value of the isContravariant parameter). The goal is
30
31
  // to produce the narrowest type that meets all of the requirements. If the type var context
31
32
  // has been "locked", it simply validates that the srcType is compatible (with no attempt
32
33
  // to widen or narrow).
33
- function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext, flags = 0 /* AssignTypeFlags.Default */, recursionCount = 0) {
34
- if (logTypeVarContextUpdates) {
34
+ function assignTypeVar(evaluator, destType, srcType, diag, constraints, flags = 0 /* AssignTypeFlags.Default */, recursionCount = 0) {
35
+ let isAssignable;
36
+ if (logConstraintsUpdates) {
35
37
  const indent = ' '.repeat(recursionCount * 2);
36
38
  console.log(`${indent}`);
37
- console.log(`${indent}assignTypeToTypeVar called with`);
39
+ console.log(`${indent}assignTypeVar called with`);
38
40
  console.log(`${indent}destType: ${evaluator.printType(destType)}`);
39
41
  console.log(`${indent}srcType: ${evaluator.printType(srcType)}`);
40
42
  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);
43
+ if (constraints) {
44
+ logConstraints(evaluator, constraints, indent);
45
+ }
44
46
  }
45
- let isTypeVarInScope = true;
46
- const isInvariant = (flags & 1 /* AssignTypeFlags.EnforceInvariance */) !== 0;
47
- const isContravariant = (flags & 2 /* AssignTypeFlags.ReverseTypeVarMatching */) !== 0 && !isInvariant;
48
47
  // If the TypeVar doesn't have a scope ID, then it's being used
49
48
  // outside of a valid TypeVar scope. This will be reported as a
50
49
  // separate error. Just ignore this case to avoid redundant errors.
51
50
  if (!destType.priv.scopeId) {
52
51
  return true;
53
52
  }
53
+ if (types_1.TypeVarType.isBound(destType) && !types_1.TypeVarType.isUnification(destType)) {
54
+ return assignBoundTypeVar(evaluator, destType, srcType, diag, flags);
55
+ }
54
56
  // Handle type[T] as a dest and a special form as a source.
55
57
  if (types_1.TypeBase.isInstantiable(destType) &&
56
58
  (0, types_1.isInstantiableClass)(srcType) &&
57
59
  evaluator.isSpecialFormClass(srcType, flags)) {
58
60
  return false;
59
61
  }
60
- // Verify that we are solving for the scope associated with this
61
- // type variable.
62
- if (!typeVarContext.hasSolveForScope(destType.priv.scopeId)) {
63
- // Handle Any as a source.
64
- if ((0, types_1.isAnyOrUnknown)(srcType) || ((0, types_1.isClass)(srcType) && types_1.ClassType.derivesFromAnyOrUnknown(srcType))) {
65
- return true;
66
- }
67
- // Handle a type[Any] as a source.
68
- if ((0, types_1.isClassInstance)(srcType) && types_1.ClassType.isBuiltIn(srcType, 'type')) {
69
- if (!srcType.priv.typeArguments ||
70
- srcType.priv.typeArguments.length < 1 ||
71
- (0, types_1.isAnyOrUnknown)(srcType.priv.typeArguments[0])) {
72
- if (types_1.TypeBase.isInstantiable(destType)) {
73
- return true;
74
- }
62
+ // An TypeVar can always be assigned to itself, but we won't record this in the constraints.
63
+ if ((0, types_1.isTypeSame)(destType, srcType)) {
64
+ return true;
65
+ }
66
+ if ((0, types_1.isParamSpec)(destType)) {
67
+ // Handle ParamSpecs specially.
68
+ isAssignable = assignParamSpec(evaluator, destType, srcType, diag, constraints, recursionCount);
69
+ }
70
+ else {
71
+ if ((0, types_1.isTypeVarTuple)(destType) && !destType.priv.isInUnion) {
72
+ const tupleClassType = evaluator.getTupleClassType();
73
+ if (!(0, types_1.isUnpacked)(srcType) && tupleClassType) {
74
+ // Package up the type into a tuple.
75
+ srcType = (0, typeUtils_1.convertToInstance)((0, typeUtils_1.specializeTupleClass)(tupleClassType, [{ type: srcType, isUnbounded: false }],
76
+ /* isTypeArgExplicit */ true,
77
+ /* isUnpackedTuple */ true));
75
78
  }
76
79
  }
77
- // Is this the equivalent of an "Unknown" for a ParamSpec?
78
- if (destType.shared.isParamSpec &&
79
- (0, types_1.isFunction)(srcType) &&
80
- types_1.FunctionType.isParamSpecValue(srcType) &&
81
- types_1.FunctionType.isGradualCallableForm(srcType)) {
82
- return true;
80
+ // If we're assigning an unpacked TypeVarTuple to a regular TypeVar,
81
+ // we need to treat it as a union of the unpacked TypeVarTuple.
82
+ if ((0, types_1.isTypeVarTuple)(srcType) &&
83
+ srcType.priv.isUnpacked &&
84
+ !srcType.priv.isInUnion &&
85
+ !(0, types_1.isTypeVarTuple)(destType)) {
86
+ srcType = types_1.TypeVarType.cloneForUnpacked(srcType, /* isInUnion */ true);
83
87
  }
84
- // Never or NoReturn is always assignable to all type variables unless
85
- // we're enforcing invariance.
86
- if ((0, types_1.isNever)(srcType) && !isInvariant) {
87
- return true;
88
+ // Handle the constrained case. This case needs to be handled specially
89
+ // because type narrowing isn't used in this case. For example, if the
90
+ // source type is "Literal[1]" and the constraint list includes the type
91
+ // "float", the resulting type is float.
92
+ if (types_1.TypeVarType.hasConstraints(destType)) {
93
+ isAssignable = assignConstrainedTypeVar(evaluator, destType, srcType, diag, constraints, flags, recursionCount);
88
94
  }
89
- // If we're in "ignore type var scope" mode, don't generate
90
- // an error in this path.
91
- if ((flags & 1024 /* AssignTypeFlags.IgnoreTypeVarScope */) !== 0) {
92
- return true;
95
+ else {
96
+ isAssignable = assignUnconstrainedTypeVar(evaluator, destType, srcType, diag, constraints, flags, recursionCount);
93
97
  }
94
- isTypeVarInScope = false;
95
- // Emit an error unless this is a synthesized type variable used
96
- // for pseudo-generic classes.
97
- if (!destType.shared.isSynthesized || destType.shared.isSynthesizedSelf) {
98
- diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(srcType, destType)));
99
- return false;
98
+ }
99
+ if (logConstraintsUpdates) {
100
+ const indent = ' '.repeat(recursionCount * 2);
101
+ console.log(`${indent}`);
102
+ if (constraints) {
103
+ logConstraints(evaluator, constraints, indent);
100
104
  }
101
105
  }
102
- // An in-scope placeholder TypeVar can always be assigned to itself,
103
- // but we won't record this in the typeVarContext.
104
- if ((0, types_1.isTypeSame)(destType, srcType) && destType.priv.isInScopePlaceholder) {
106
+ return isAssignable;
107
+ }
108
+ exports.assignTypeVar = assignTypeVar;
109
+ // Returns a solution for the type variables tracked by the constraint tracker.
110
+ function solveConstraints(evaluator, constraints, options) {
111
+ const solutionSets = [];
112
+ constraints.doForEachConstraintSet((constraintSet) => {
113
+ const solutionSet = solveConstraintSet(evaluator, constraintSet, options);
114
+ solutionSets.push(solutionSet);
115
+ });
116
+ return new constraintSolution_1.ConstraintSolution(solutionSets);
117
+ }
118
+ exports.solveConstraints = solveConstraints;
119
+ function solveConstraintSet(evaluator, constraintSet, options) {
120
+ const solutionSet = new constraintSolution_1.ConstraintSolutionSet(constraintSet.getScopeIds());
121
+ constraintSet.doForEachTypeVar((entry) => {
122
+ const value = getTypeVarType(evaluator, constraintSet, entry.typeVar, options === null || options === void 0 ? void 0 : options.useLowerBoundOnly);
123
+ if (value) {
124
+ solutionSet.setType(entry.typeVar, value);
125
+ }
126
+ });
127
+ return solutionSet;
128
+ }
129
+ exports.solveConstraintSet = solveConstraintSet;
130
+ // Updates the lower and upper bounds for a type variable. It also calculates the
131
+ // lowerBoundNoLiterals, which is a variant of the lower bound that has
132
+ // literals stripped. By default, the constraint solver always uses the "no literals"
133
+ // type in its solutions unless the version with literals is required to satisfy
134
+ // the upper bound.
135
+ function updateTypeVarType(evaluator, constraints, destType, lowerBound, upperBound, forceRetainLiterals = false) {
136
+ let lowerBoundNoLiterals;
137
+ if (lowerBound && !forceRetainLiterals) {
138
+ const strippedLiteral = (0, types_1.isTypeVarTuple)(destType)
139
+ ? stripLiteralValueForUnpackedTuple(evaluator, lowerBound)
140
+ : evaluator.stripLiteralValue(lowerBound);
141
+ // Strip the literals from the lower bound and see if it is still
142
+ // narrower than the upper bound.
143
+ if (strippedLiteral !== lowerBound) {
144
+ if (!upperBound || evaluator.assignType(upperBound, strippedLiteral)) {
145
+ lowerBoundNoLiterals = strippedLiteral;
146
+ }
147
+ }
148
+ }
149
+ constraints.setBounds(destType, lowerBound, lowerBoundNoLiterals, upperBound);
150
+ }
151
+ exports.updateTypeVarType = updateTypeVarType;
152
+ // In cases where the expected type is a specialized base class of the
153
+ // source type, we need to determine which type arguments in the derived
154
+ // class will make it compatible with the specialized base class. This method
155
+ // performs this reverse mapping of type arguments and populates the type var
156
+ // map for the target type. If the type is not assignable to the expected type,
157
+ // it returns false.
158
+ function addConstraintsForExpectedType(evaluator, type, expectedType, constraints, liveTypeVarScopes, usageOffset = undefined) {
159
+ if ((0, types_1.isAny)(expectedType)) {
160
+ type.shared.typeParams.forEach((typeParam) => {
161
+ updateTypeVarType(evaluator, constraints, typeParam, expectedType, expectedType);
162
+ });
105
163
  return true;
106
164
  }
107
- if ((flags & 8 /* AssignTypeFlags.SkipSolveTypeVars */) !== 0) {
108
- return evaluator.assignType(evaluator.makeTopLevelTypeVarsConcrete(destType), evaluator.makeTopLevelTypeVarsConcrete(srcType), diag,
109
- /* destTypeVarContext */ undefined,
110
- /* srcTypeVarContext */ undefined, flags, recursionCount);
165
+ if ((0, types_1.isTypeVar)(expectedType) && types_1.TypeVarType.isSelf(expectedType) && expectedType.shared.boundType) {
166
+ expectedType = expectedType.shared.boundType;
167
+ }
168
+ if (!(0, types_1.isClass)(expectedType)) {
169
+ return false;
111
170
  }
112
- if (destType.shared.isParamSpec) {
113
- return assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContext, recursionCount);
171
+ // If the expected type is generic (but not specialized), we can't proceed.
172
+ const expectedTypeArgs = expectedType.priv.typeArgs;
173
+ if (!expectedTypeArgs) {
174
+ return evaluator.assignType(type, expectedType,
175
+ /* diag */ undefined, constraints,
176
+ /* srcConstraints */ undefined, 2048 /* AssignTypeFlags.PopulatingExpectedType */);
114
177
  }
115
- if (destType.shared.isVariadic && !destType.priv.isVariadicInUnion) {
116
- if (!(0, types_1.isUnpacked)(srcType)) {
117
- const tupleClassType = evaluator.getTupleClassType();
118
- if (tupleClassType && (0, types_1.isInstantiableClass)(tupleClassType)) {
119
- // Package up the type into a tuple.
120
- srcType = (0, typeUtils_1.convertToInstance)((0, typeUtils_1.specializeTupleClass)(tupleClassType, [{ type: srcType, isUnbounded: false }],
121
- /* isTypeArgumentExplicit */ true,
122
- /* isUnpackedTuple */ true));
178
+ evaluator.inferVarianceForClass(type);
179
+ // If the expected type is the same as the target type (commonly the case),
180
+ // we can use a faster method.
181
+ if (types_1.ClassType.isSameGenericClass(expectedType, type)) {
182
+ const solution = (0, typeUtils_1.buildSolutionFromSpecializedClass)(expectedType);
183
+ const typeParams = types_1.ClassType.getTypeParams(expectedType);
184
+ typeParams.forEach((typeParam) => {
185
+ let typeArgValue = solution.getMainSolutionSet().getType(typeParam);
186
+ if (typeArgValue && liveTypeVarScopes) {
187
+ typeArgValue = (0, typeUtils_1.transformExpectedType)(typeArgValue, liveTypeVarScopes, usageOffset);
123
188
  }
124
- else {
125
- srcType = types_1.UnknownType.create();
189
+ if (typeArgValue) {
190
+ const variance = types_1.TypeVarType.getVariance(typeParam);
191
+ updateTypeVarType(evaluator, constraints, typeParam, variance === 3 /* Variance.Covariant */ ? undefined : typeArgValue, variance === 4 /* Variance.Contravariant */ ? undefined : typeArgValue);
126
192
  }
193
+ });
194
+ return true;
195
+ }
196
+ // Create a generic version of the expected type.
197
+ const expectedTypeScopeId = (0, typeUtils_1.getTypeVarScopeId)(expectedType);
198
+ const synthExpectedTypeArgs = types_1.ClassType.getTypeParams(expectedType).map((typeParam, index) => {
199
+ const typeVar = types_1.TypeVarType.createInstance(`__dest${index}`, (0, types_1.isParamSpec)(typeParam) ? types_1.TypeVarKind.ParamSpec : types_1.TypeVarKind.TypeVar);
200
+ typeVar.shared.isSynthesized = true;
201
+ // Use invariance here so we set the lower and upper bound on the TypeVar.
202
+ typeVar.shared.declaredVariance = 2 /* Variance.Invariant */;
203
+ typeVar.priv.scopeId = expectedTypeScopeId;
204
+ return typeVar;
205
+ });
206
+ const genericExpectedType = types_1.ClassType.specialize(expectedType, synthExpectedTypeArgs);
207
+ // For each type param in the target type, create a placeholder type variable.
208
+ const typeArgs = types_1.ClassType.getTypeParams(type).map((typeParam, index) => {
209
+ const typeVar = types_1.TypeVarType.createInstance(`__source${index}`, (0, types_1.isParamSpec)(typeParam) ? types_1.TypeVarKind.ParamSpec : types_1.TypeVarKind.TypeVar);
210
+ typeVar.shared.isSynthesized = true;
211
+ typeVar.shared.synthesizedIndex = index;
212
+ typeVar.shared.isExemptFromBoundCheck = true;
213
+ return types_1.TypeVarType.cloneAsUnificationVar(typeVar);
214
+ });
215
+ const specializedType = types_1.ClassType.specialize(type, typeArgs);
216
+ const syntheticConstraints = new constraintTracker_1.ConstraintTracker();
217
+ if (evaluator.assignType(genericExpectedType, specializedType,
218
+ /* diag */ undefined, syntheticConstraints,
219
+ /* srcConstraints */ undefined, 2048 /* AssignTypeFlags.PopulatingExpectedType */)) {
220
+ let isResultValid = true;
221
+ synthExpectedTypeArgs.forEach((typeVar, index) => {
222
+ let synthTypeVar = getTypeVarType(evaluator, syntheticConstraints.getMainConstraintSet(), typeVar);
223
+ const otherSubtypes = [];
224
+ // If the resulting type is a union, try to find a matching type var and move
225
+ // the remaining subtypes to the "otherSubtypes" array.
226
+ if (synthTypeVar) {
227
+ if ((0, types_1.isParamSpec)(typeVar) && (0, types_1.isFunction)(synthTypeVar)) {
228
+ synthTypeVar = (0, typeUtils_1.simplifyFunctionToParamSpec)(synthTypeVar);
229
+ }
230
+ if ((0, types_1.isUnion)(synthTypeVar)) {
231
+ let foundSynthTypeVar;
232
+ (0, typeUtils_1.sortTypes)(synthTypeVar.priv.subtypes).forEach((subtype) => {
233
+ if ((0, types_1.isTypeVar)(subtype) &&
234
+ subtype.shared.isSynthesized &&
235
+ subtype.shared.synthesizedIndex !== undefined &&
236
+ !foundSynthTypeVar) {
237
+ foundSynthTypeVar = subtype;
238
+ }
239
+ else {
240
+ otherSubtypes.push(subtype);
241
+ }
242
+ });
243
+ if (foundSynthTypeVar) {
244
+ synthTypeVar = foundSynthTypeVar;
245
+ }
246
+ }
247
+ }
248
+ // Is this one of the synthesized type vars we allocated above? If so,
249
+ // the type arg that corresponds to this type var maps back to the target type.
250
+ if (synthTypeVar &&
251
+ (0, types_1.isTypeVar)(synthTypeVar) &&
252
+ synthTypeVar.shared.isSynthesized &&
253
+ synthTypeVar.shared.synthesizedIndex !== undefined) {
254
+ const targetTypeVar = types_1.ClassType.getTypeParams(specializedType)[synthTypeVar.shared.synthesizedIndex];
255
+ if (index < expectedTypeArgs.length) {
256
+ let typeArgValue = (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(expectedTypeArgs[index]);
257
+ if (otherSubtypes.length > 0) {
258
+ typeArgValue = (0, types_1.combineTypes)([typeArgValue, ...otherSubtypes]);
259
+ }
260
+ if (liveTypeVarScopes) {
261
+ typeArgValue = (0, typeUtils_1.transformExpectedType)(typeArgValue, liveTypeVarScopes, usageOffset);
262
+ }
263
+ if (typeArgValue) {
264
+ const variance = types_1.TypeVarType.getVariance(typeVar);
265
+ // If this type variable already has a type, don't overwrite it. This can
266
+ // happen if a single type variable in the derived class is used multiple times
267
+ // in the specialized base class type (e.g. Mapping[T, T]).
268
+ if (constraints.getMainConstraintSet().getTypeVar(targetTypeVar)) {
269
+ isResultValid = false;
270
+ typeArgValue = types_1.UnknownType.create();
271
+ }
272
+ updateTypeVarType(evaluator, constraints, targetTypeVar, variance === 3 /* Variance.Covariant */ ? undefined : typeArgValue, variance === 4 /* Variance.Contravariant */ ? undefined : typeArgValue);
273
+ }
274
+ else {
275
+ isResultValid = false;
276
+ }
277
+ }
278
+ }
279
+ });
280
+ return isResultValid;
281
+ }
282
+ return false;
283
+ }
284
+ exports.addConstraintsForExpectedType = addConstraintsForExpectedType;
285
+ // If the constraint tracker contains any type variables whose types depend on
286
+ // unification vars used for bidirectional type inference, replace those
287
+ // with the solved type associated with those unification vars.
288
+ function applyUnificationVars(evaluator, constraints) {
289
+ constraints.doForEachConstraintSet((constraintSet) => {
290
+ if (!constraintSet.hasUnificationVars()) {
291
+ return;
127
292
  }
293
+ constraintSet.getTypeVars().forEach((entry) => {
294
+ if (!types_1.TypeVarType.isUnification(entry.typeVar)) {
295
+ const newLowerBound = entry.lowerBound
296
+ ? applyUnificationVarsToType(evaluator, entry.lowerBound, constraintSet)
297
+ : undefined;
298
+ const newLowerBoundNoLiterals = entry.lowerBoundNoLiterals
299
+ ? applyUnificationVarsToType(evaluator, entry.lowerBoundNoLiterals, constraintSet)
300
+ : undefined;
301
+ const newUpperBound = entry.upperBound
302
+ ? applyUnificationVarsToType(evaluator, entry.upperBound, constraintSet)
303
+ : undefined;
304
+ constraintSet.setBounds(entry.typeVar, newLowerBound, newLowerBoundNoLiterals, newUpperBound);
305
+ }
306
+ });
307
+ });
308
+ }
309
+ exports.applyUnificationVars = applyUnificationVars;
310
+ function getTypeVarType(evaluator, constraintSet, typeVar, useLowerBoundOnly) {
311
+ var _a, _b;
312
+ const entry = constraintSet.getTypeVar(typeVar);
313
+ if (!entry) {
314
+ return undefined;
128
315
  }
129
- // If we're assigning an unpacked TypeVarTuple to a regular TypeVar,
130
- // we need to treat it as a union of the unpacked TypeVarTuple.
131
- if ((0, types_1.isTypeVar)(srcType) &&
132
- srcType.shared.isVariadic &&
133
- srcType.priv.isVariadicUnpacked &&
134
- !srcType.priv.isVariadicInUnion &&
135
- !destType.shared.isVariadic) {
136
- srcType = types_1.TypeVarType.cloneForUnpacked(srcType, /* isInUnion */ true);
316
+ if ((0, types_1.isParamSpec)(typeVar)) {
317
+ if (!entry.lowerBound) {
318
+ return undefined;
319
+ }
320
+ if ((0, types_1.isFunction)(entry.lowerBound)) {
321
+ return entry.lowerBound;
322
+ }
323
+ if ((0, types_1.isAnyOrUnknown)(entry.lowerBound)) {
324
+ return types_1.ParamSpecType.getUnknown();
325
+ }
326
+ }
327
+ if (useLowerBoundOnly) {
328
+ return entry.lowerBound;
329
+ }
330
+ // Prefer the lower bound with no literals. It will be undefined
331
+ // if the literal type couldn't be widened due to constraints imposed
332
+ // by the upper bound.
333
+ return (_b = (_a = entry.lowerBoundNoLiterals) !== null && _a !== void 0 ? _a : entry.lowerBound) !== null && _b !== void 0 ? _b : entry.upperBound;
334
+ }
335
+ // Handles an assignment to a TypeVar that is "bound" rather than "free".
336
+ // In general, such assignments are not allowed, but there are some special
337
+ // cases to be handled.
338
+ function assignBoundTypeVar(evaluator, destType, srcType, diag, flags) {
339
+ // Handle Any as a source.
340
+ if ((0, types_1.isAnyOrUnknown)(srcType) || ((0, types_1.isClass)(srcType) && types_1.ClassType.derivesFromAnyOrUnknown(srcType))) {
341
+ return true;
342
+ }
343
+ // Is this the equivalent of an "Unknown" for a ParamSpec?
344
+ if ((0, types_1.isParamSpec)(destType) &&
345
+ (0, types_1.isFunction)(srcType) &&
346
+ types_1.FunctionType.isParamSpecValue(srcType) &&
347
+ types_1.FunctionType.isGradualCallableForm(srcType)) {
348
+ return true;
137
349
  }
138
- // Handle the constrained case. This case needs to be handled specially
139
- // because type narrowing isn't used in this case. For example, if the
140
- // source type is "Literal[1]" and the constraint list includes the type
141
- // "float", the resulting type is float.
142
- if (destType.shared.constraints.length > 0) {
143
- return assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, typeVarContext, flags, isTypeVarInScope, recursionCount);
350
+ // Never is always assignable in a covariant context.
351
+ const isCovariant = (flags & (1 /* AssignTypeFlags.EnforceInvariance */ | 2 /* AssignTypeFlags.ReverseTypeVarMatching */)) === 0;
352
+ if ((0, types_1.isNever)(srcType) && isCovariant) {
353
+ return true;
354
+ }
355
+ // Handle a type[Any] as a source.
356
+ if ((0, types_1.isClassInstance)(srcType) && types_1.ClassType.isBuiltIn(srcType, 'type')) {
357
+ if (!srcType.priv.typeArgs || srcType.priv.typeArgs.length < 1 || (0, types_1.isAnyOrUnknown)(srcType.priv.typeArgs[0])) {
358
+ if (types_1.TypeBase.isInstantiable(destType)) {
359
+ return true;
360
+ }
361
+ }
362
+ }
363
+ // Emit an error unless this is a synthesized type variable used
364
+ // for pseudo-generic classes.
365
+ if (!destType.shared.isSynthesized || types_1.TypeVarType.isSelf(destType)) {
366
+ diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(srcType, destType)));
144
367
  }
368
+ return false;
369
+ }
370
+ // Handles assignments to a TypeVarTuple or a TypeVar that does not have
371
+ // value constraints (but may have an upper bound).
372
+ function assignUnconstrainedTypeVar(evaluator, destType, srcType, diag, constraints, flags, recursionCount) {
373
+ const isInvariant = (flags & 1 /* AssignTypeFlags.EnforceInvariance */) !== 0;
374
+ const isContravariant = (flags & 2 /* AssignTypeFlags.ReverseTypeVarMatching */) !== 0 && !isInvariant;
145
375
  // Handle the unconstrained (but possibly bound) case.
146
- const curEntry = typeVarContext.getPrimarySignature().getTypeVar(destType);
147
- let curWideTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.wideBound;
148
- if (!curWideTypeBound && !destType.shared.isSynthesizedSelf) {
149
- curWideTypeBound = destType.shared.boundType;
150
- }
151
- let curNarrowTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.narrowBound;
152
- let newNarrowTypeBound = curNarrowTypeBound;
153
- let newWideTypeBound = curWideTypeBound;
376
+ const curEntry = constraints === null || constraints === void 0 ? void 0 : constraints.getMainConstraintSet().getTypeVar(destType);
377
+ let curUpperBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.upperBound;
378
+ if (!curUpperBound && !types_1.TypeVarType.isSelf(destType)) {
379
+ curUpperBound = destType.shared.boundType;
380
+ }
381
+ let curLowerBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.lowerBound;
382
+ let newLowerBound = curLowerBound;
383
+ let newUpperTypeBound = curUpperBound;
154
384
  const diagAddendum = diag ? new diagnostic_1.DiagnosticAddendum() : undefined;
155
385
  let adjSrcType = srcType;
156
386
  // If the source is a class that is missing type arguments, fill
157
387
  // in missing type arguments with Unknown.
158
- if ((flags & 8192 /* AssignTypeFlags.AllowUnspecifiedTypeArguments */) === 0) {
388
+ if ((flags & 8192 /* AssignTypeFlags.AllowUnspecifiedTypeArgs */) === 0) {
159
389
  if ((0, types_1.isClass)(adjSrcType) && adjSrcType.priv.includeSubclasses) {
160
390
  adjSrcType = (0, typeUtils_1.specializeWithDefaultTypeArgs)(adjSrcType);
161
391
  }
@@ -187,51 +417,51 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
187
417
  return true;
188
418
  }
189
419
  // If we're populating the expected type, constrain either the
190
- // narrow type bound, wide type bound or both. Don't overwrite
420
+ // lower type bound, upper type bound or both. Don't overwrite
191
421
  // an existing entry.
192
422
  if (!curEntry) {
193
423
  if (isInvariant) {
194
- newNarrowTypeBound = adjSrcType;
195
- newWideTypeBound = adjSrcType;
424
+ newLowerBound = adjSrcType;
425
+ newUpperTypeBound = adjSrcType;
196
426
  }
197
427
  else if (isContravariant) {
198
- newNarrowTypeBound = adjSrcType;
428
+ newLowerBound = adjSrcType;
199
429
  }
200
430
  else {
201
- newWideTypeBound = adjSrcType;
431
+ newUpperTypeBound = adjSrcType;
202
432
  }
203
433
  }
204
434
  }
205
435
  else if (isContravariant) {
206
- // Update the wide type bound.
207
- if (!curWideTypeBound || (0, types_1.isTypeSame)(destType, curWideTypeBound)) {
208
- newWideTypeBound = adjSrcType;
209
- }
210
- else if (!(0, types_1.isTypeSame)(curWideTypeBound, adjSrcType, {}, recursionCount)) {
211
- if (evaluator.assignType(curWideTypeBound, evaluator.makeTopLevelTypeVarsConcrete(adjSrcType), diagAddendum,
212
- /* destTypeVarContext */ undefined,
213
- /* srcTypeVarContext */ undefined, flags & 1024 /* AssignTypeFlags.IgnoreTypeVarScope */, recursionCount)) {
214
- // The srcType is narrower than the current wideTypeBound, so replace it.
215
- newWideTypeBound = adjSrcType;
216
- }
217
- else if (!evaluator.assignType(adjSrcType, curWideTypeBound, diagAddendum,
218
- /* destTypeVarContext */ undefined,
219
- /* srcTypeVarContext */ undefined, flags & 1024 /* AssignTypeFlags.IgnoreTypeVarScope */, recursionCount)) {
436
+ // Update the upper bound.
437
+ if (!curUpperBound || (0, types_1.isTypeSame)(destType, curUpperBound)) {
438
+ newUpperTypeBound = adjSrcType;
439
+ }
440
+ else if (!(0, types_1.isTypeSame)(curUpperBound, adjSrcType, {}, recursionCount)) {
441
+ if (evaluator.assignType(curUpperBound, evaluator.makeTopLevelTypeVarsConcrete(adjSrcType), diagAddendum,
442
+ /* destConstraints */ undefined,
443
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
444
+ // The srcType is narrower than the current upper bound, so replace it.
445
+ newUpperTypeBound = adjSrcType;
446
+ }
447
+ else if (!evaluator.assignType(adjSrcType, curUpperBound, diagAddendum,
448
+ /* destConstraints */ undefined,
449
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
220
450
  if (diag && diagAddendum) {
221
- diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(curWideTypeBound, adjSrcType)));
451
+ diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(curUpperBound, adjSrcType)));
222
452
  diag.addAddendum(diagAddendum);
223
453
  }
224
454
  return false;
225
455
  }
226
456
  }
227
- // Make sure we haven't narrowed it beyond the current narrow bound.
228
- if (curNarrowTypeBound) {
229
- if (!evaluator.assignType(newWideTypeBound, curNarrowTypeBound,
457
+ // Make sure we haven't narrowed it beyond the current lower bound.
458
+ if (curLowerBound) {
459
+ if (!evaluator.assignType(newUpperTypeBound, curLowerBound,
230
460
  /* diag */ undefined,
231
- /* destTypeVarContext */ undefined,
232
- /* srcTypeVarContext */ undefined, flags & 1024 /* AssignTypeFlags.IgnoreTypeVarScope */, recursionCount)) {
461
+ /* destConstraints */ undefined,
462
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
233
463
  if (diag && diagAddendum) {
234
- diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(curNarrowTypeBound, newWideTypeBound)));
464
+ diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(curLowerBound, newUpperTypeBound)));
235
465
  diag.addAddendum(diagAddendum);
236
466
  }
237
467
  return false;
@@ -239,152 +469,150 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
239
469
  }
240
470
  }
241
471
  else {
242
- if (!curNarrowTypeBound || (0, types_1.isTypeSame)(destType, curNarrowTypeBound)) {
243
- // There was previously no narrow bound. We've now established one.
244
- newNarrowTypeBound = adjSrcType;
472
+ if (!curLowerBound || (0, types_1.isTypeSame)(destType, curLowerBound)) {
473
+ // There was previously no lower bound. We've now established one.
474
+ newLowerBound = adjSrcType;
245
475
  }
246
- else if ((0, types_1.isTypeSame)(curNarrowTypeBound, adjSrcType, {}, recursionCount)) {
247
- // If this is an invariant context and there is currently no wide type bound
248
- // established, use the "no literals" version of the narrow type bounds rather
476
+ else if ((0, types_1.isTypeSame)(curLowerBound, adjSrcType, {}, recursionCount)) {
477
+ // If this is an invariant context and there is currently no upper bound
478
+ // established, use the "no literals" version of the lower bound rather
249
479
  // than a version that has literals.
250
- if (!newWideTypeBound && isInvariant && (curEntry === null || curEntry === void 0 ? void 0 : curEntry.narrowBoundNoLiterals)) {
251
- newNarrowTypeBound = curEntry.narrowBoundNoLiterals;
480
+ if (!newUpperTypeBound && isInvariant && (curEntry === null || curEntry === void 0 ? void 0 : curEntry.lowerBoundNoLiterals)) {
481
+ newLowerBound = curEntry.lowerBoundNoLiterals;
252
482
  }
253
483
  }
254
484
  else {
255
- if ((0, types_1.isAnyOrUnknown)(adjSrcType) && (curEntry === null || curEntry === void 0 ? void 0 : curEntry.tupleTypes)) {
256
- // Handle the tuple case specially. If Any or Unknown is assigned
257
- // during the construction of a tuple, the resulting tuple type must
258
- // be tuple[Any, ...], which is compatible with any tuple.
259
- newNarrowTypeBound = adjSrcType;
260
- }
261
- else if (evaluator.assignType(curNarrowTypeBound, adjSrcType, diagAddendum, typeVarContext,
262
- /* srcTypeVarContext */ undefined, flags, recursionCount)) {
485
+ if (evaluator.assignType(curLowerBound, adjSrcType, diagAddendum, constraints,
486
+ /* srcConstraints */ undefined, flags, recursionCount)) {
263
487
  // No need to widen. Stick with the existing type unless it's unknown
264
488
  // or partly unknown, in which case we'll replace it with a known type
265
- // as long as it doesn't violate the current narrow bound.
266
- if ((0, typeUtils_1.isPartlyUnknown)(curNarrowTypeBound) &&
489
+ // as long as it doesn't violate the current lower bound.
490
+ if ((0, typeUtils_1.isPartlyUnknown)(curLowerBound) &&
267
491
  !(0, types_1.isUnknown)(adjSrcType) &&
268
- evaluator.assignType(adjSrcType, curNarrowTypeBound,
269
- /* diag */ undefined, typeVarContext,
270
- /* srcTypeVarContext */ undefined, flags & 1024 /* AssignTypeFlags.IgnoreTypeVarScope */, recursionCount)) {
271
- newNarrowTypeBound = adjSrcType;
492
+ evaluator.assignType(adjSrcType, curLowerBound,
493
+ /* diag */ undefined, constraints,
494
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
495
+ newLowerBound = adjSrcType;
272
496
  }
273
497
  else {
274
- newNarrowTypeBound = (0, typeUtils_1.applySolvedTypeVars)(curNarrowTypeBound, typeVarContext);
498
+ newLowerBound = curLowerBound;
499
+ if (constraints) {
500
+ newLowerBound = evaluator.solveAndApplyConstraints(newLowerBound, constraints);
501
+ }
275
502
  }
276
503
  }
277
- else if ((0, types_1.isTypeVar)(curNarrowTypeBound) &&
504
+ else if ((0, types_1.isTypeVar)(curLowerBound) &&
278
505
  !(0, types_1.isTypeVar)(adjSrcType) &&
279
- evaluator.assignType(evaluator.makeTopLevelTypeVarsConcrete(curNarrowTypeBound), adjSrcType, diagAddendum, typeVarContext,
280
- /* srcTypeVarContext */ undefined, flags, recursionCount)) {
281
- // If the existing narrow type bound was a TypeVar that is not
506
+ evaluator.assignType(evaluator.makeTopLevelTypeVarsConcrete(curLowerBound), adjSrcType, diagAddendum, constraints,
507
+ /* srcConstraints */ undefined, flags, recursionCount)) {
508
+ // If the existing lower bound was a TypeVar that is not
282
509
  // part of the current context we can replace it with the new
283
510
  // source type.
284
- newNarrowTypeBound = adjSrcType;
511
+ newLowerBound = adjSrcType;
285
512
  }
286
513
  else {
287
514
  // We need to widen the type.
288
- if (typeVarContext.isLocked()) {
289
- diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(adjSrcType, curNarrowTypeBound)));
515
+ if (constraints === null || constraints === void 0 ? void 0 : constraints.isLocked()) {
516
+ diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(adjSrcType, curLowerBound)));
290
517
  return false;
291
518
  }
292
- if (evaluator.assignType(adjSrcType, curNarrowTypeBound,
293
- /* diag */ undefined, typeVarContext,
294
- /* srcTypeVarContext */ undefined, flags & 1024 /* AssignTypeFlags.IgnoreTypeVarScope */, recursionCount)) {
295
- newNarrowTypeBound = adjSrcType;
519
+ if (evaluator.assignType(adjSrcType, curLowerBound,
520
+ /* diag */ undefined, constraints,
521
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
522
+ newLowerBound = adjSrcType;
296
523
  }
297
- else if ((0, types_1.isVariadicTypeVar)(destType)) {
298
- const widenedType = widenTypeForVariadicTypeVar(evaluator, curNarrowTypeBound, adjSrcType);
524
+ else if ((0, types_1.isTypeVarTuple)(destType)) {
525
+ const widenedType = widenTypeForTypeVarTuple(evaluator, curLowerBound, adjSrcType);
299
526
  if (!widenedType) {
300
- diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(curNarrowTypeBound, adjSrcType)));
527
+ diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(curLowerBound, adjSrcType)));
301
528
  return false;
302
529
  }
303
- newNarrowTypeBound = widenedType;
530
+ newLowerBound = widenedType;
304
531
  }
305
532
  else {
306
533
  const objectType = evaluator.getObjectType();
307
- // If this is an invariant context and there is currently no wide type bound
308
- // established, use the "no literals" version of the narrow type bounds rather
534
+ // If this is an invariant context and there is currently no upper bound
535
+ // established, use the "no literals" version of the lower bound rather
309
536
  // than a version that has literals.
310
- if (!newWideTypeBound && isInvariant && (curEntry === null || curEntry === void 0 ? void 0 : curEntry.narrowBoundNoLiterals)) {
311
- curNarrowTypeBound = curEntry.narrowBoundNoLiterals;
537
+ if (!newUpperTypeBound && isInvariant && (curEntry === null || curEntry === void 0 ? void 0 : curEntry.lowerBoundNoLiterals)) {
538
+ curLowerBound = curEntry.lowerBoundNoLiterals;
539
+ }
540
+ let curSolvedLowerBound = curLowerBound;
541
+ if (constraints) {
542
+ curSolvedLowerBound = evaluator.solveAndApplyConstraints(curLowerBound, constraints);
312
543
  }
313
- const curSolvedNarrowTypeBound = (0, typeUtils_1.applySolvedTypeVars)(curNarrowTypeBound, typeVarContext);
314
- // In some extreme edge cases, the narrow type bound can become
544
+ // In some extreme edge cases, the lower bound can become
315
545
  // a union with so many subtypes that performance grinds to a
316
546
  // halt. We'll detect this case and widen the resulting type
317
547
  // to an 'object' instead of making the union even bigger. This
318
548
  // is still a valid solution to the TypeVar.
319
- if ((0, types_1.isUnion)(curSolvedNarrowTypeBound) &&
320
- curSolvedNarrowTypeBound.priv.subtypes.length > typeEvaluatorTypes_1.maxSubtypesForInferredType &&
321
- destType.shared.boundType !== undefined &&
549
+ if ((0, types_1.isUnion)(curSolvedLowerBound) &&
550
+ curSolvedLowerBound.priv.subtypes.length > typeEvaluatorTypes_1.maxSubtypesForInferredType &&
551
+ types_1.TypeVarType.hasBound(destType) &&
322
552
  (0, types_1.isClassInstance)(objectType)) {
323
- newNarrowTypeBound = (0, types_1.combineTypes)([curSolvedNarrowTypeBound, objectType], {
324
- maxSubtypeCount: maxSubtypeCountForTypeVarNarrowBound,
553
+ newLowerBound = (0, types_1.combineTypes)([curSolvedLowerBound, objectType], {
554
+ maxSubtypeCount: maxSubtypeCountForTypeVarLowerBound,
325
555
  });
326
556
  }
327
557
  else {
328
- newNarrowTypeBound = (0, types_1.combineTypes)([curSolvedNarrowTypeBound, adjSrcType], {
329
- maxSubtypeCount: maxSubtypeCountForTypeVarNarrowBound,
558
+ newLowerBound = (0, types_1.combineTypes)([curSolvedLowerBound, adjSrcType], {
559
+ maxSubtypeCount: maxSubtypeCountForTypeVarLowerBound,
330
560
  });
331
561
  }
332
562
  }
333
563
  }
334
564
  }
335
- // If this is an invariant context, make sure the narrow type bound
565
+ // If this is an invariant context, make sure the lower bound
336
566
  // isn't too wide.
337
- if (isInvariant && newNarrowTypeBound) {
338
- if (!evaluator.assignType(adjSrcType, newNarrowTypeBound, diag === null || diag === void 0 ? void 0 : diag.createAddendum(),
339
- /* destTypeVarContext */ undefined,
340
- /* srcTypeVarContext */ undefined, 1024 /* AssignTypeFlags.IgnoreTypeVarScope */, recursionCount)) {
567
+ if (isInvariant && newLowerBound) {
568
+ if (!evaluator.assignType(adjSrcType, newLowerBound, diag === null || diag === void 0 ? void 0 : diag.createAddendum(),
569
+ /* destConstraints */ undefined,
570
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
341
571
  if (diag && diagAddendum) {
342
- diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(newNarrowTypeBound, adjSrcType)));
572
+ diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(newLowerBound, adjSrcType)));
343
573
  }
344
574
  return false;
345
575
  }
346
576
  }
347
- // Make sure we don't exceed the wide type bound.
348
- if (curWideTypeBound && newNarrowTypeBound) {
349
- if (!(0, types_1.isTypeSame)(curWideTypeBound, newNarrowTypeBound, {}, recursionCount)) {
350
- let adjWideTypeBound = evaluator.makeTopLevelTypeVarsConcrete(curWideTypeBound,
577
+ // Make sure we don't exceed the upper bound.
578
+ if (curUpperBound && newLowerBound) {
579
+ if (!(0, types_1.isTypeSame)(curUpperBound, newLowerBound, {}, recursionCount)) {
580
+ let adjUpperBound = evaluator.makeTopLevelTypeVarsConcrete(curUpperBound,
351
581
  /* makeParamSpecsConcrete */ true);
352
- // Convert any remaining (non-top-level) TypeVars in the wide type
353
- // bound to in-scope placeholders.
354
- adjWideTypeBound = (0, typeUtils_1.transformExpectedType)(adjWideTypeBound,
582
+ // Convert any remaining (non-top-level) TypeVars in the upper
583
+ // bound to unification vars.
584
+ adjUpperBound = (0, typeUtils_1.transformExpectedType)(adjUpperBound,
355
585
  /* liveTypeVarScopes */ [],
356
586
  /* usageOffset */ undefined);
357
- if (!evaluator.assignType(adjWideTypeBound, newNarrowTypeBound, diag === null || diag === void 0 ? void 0 : diag.createAddendum(),
358
- /* destTypeVarContext */ undefined,
359
- /* srcTypeVarContext */ undefined, 1024 /* AssignTypeFlags.IgnoreTypeVarScope */, recursionCount)) {
587
+ if (!evaluator.assignType(adjUpperBound, newLowerBound, diag === null || diag === void 0 ? void 0 : diag.createAddendum(),
588
+ /* destConstraints */ undefined,
589
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
360
590
  if (diag && diagAddendum) {
361
- diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(newNarrowTypeBound, adjWideTypeBound)));
591
+ diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(newLowerBound, adjUpperBound)));
362
592
  }
363
593
  return false;
364
594
  }
365
595
  }
366
596
  }
367
597
  }
368
- if (!newWideTypeBound && isInvariant) {
369
- newWideTypeBound = newNarrowTypeBound;
598
+ if (!newUpperTypeBound && isInvariant) {
599
+ newUpperTypeBound = newLowerBound;
370
600
  }
371
601
  // If there's a bound type, make sure the source is assignable to it.
372
602
  if (destType.shared.boundType) {
373
- const updatedType = (newNarrowTypeBound || newWideTypeBound);
603
+ const updatedType = (newLowerBound || newUpperTypeBound);
374
604
  // If the dest is a Type[T] but the source is not a valid Type,
375
605
  // skip the assignType check and the diagnostic addendum, which will
376
606
  // be confusing and inaccurate.
377
- if (types_1.TypeBase.isInstantiable(destType) && !types_1.TypeBase.isInstantiable(srcType)) {
607
+ if (types_1.TypeBase.isInstantiable(destType) && !(0, typeUtils_1.isEffectivelyInstantiable)(srcType)) {
378
608
  return false;
379
609
  }
380
610
  // In general, bound types cannot be generic, but the "Self" type is an
381
- // exception. In this case, we need to use the original TypeVarContext
611
+ // exception. In this case, we need to use the original constraints
382
612
  // to solve for the generic type variable(s) in the bound type.
383
- const effectiveTypeVarContext = destType.shared.isSynthesizedSelf
384
- ? typeVarContext
385
- : new typeVarContext_1.TypeVarContext(destType.priv.scopeId);
386
- if (!evaluator.assignType(destType.shared.boundType, evaluator.makeTopLevelTypeVarsConcrete(updatedType), diag === null || diag === void 0 ? void 0 : diag.createAddendum(), effectiveTypeVarContext,
387
- /* srcTypeVarContext */ undefined, flags & 1024 /* AssignTypeFlags.IgnoreTypeVarScope */, recursionCount)) {
613
+ const effectiveConstraints = types_1.TypeVarType.isSelf(destType) ? constraints : undefined;
614
+ if (!evaluator.assignType(destType.shared.boundType, evaluator.makeTopLevelTypeVarsConcrete(updatedType), diag === null || diag === void 0 ? void 0 : diag.createAddendum(), effectiveConstraints,
615
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
388
616
  // Avoid adding a message that will confuse users if the TypeVar was
389
617
  // synthesized for internal purposes.
390
618
  if (!destType.shared.isSynthesized) {
@@ -397,61 +625,24 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
397
625
  return false;
398
626
  }
399
627
  }
400
- // Update the tuple types based on the new type bounds. We need to
401
- // switch to an unbounded tuple type since the length of the resulting
402
- // tuple is indeterminate.
403
- let newTupleTypes = curEntry === null || curEntry === void 0 ? void 0 : curEntry.tupleTypes;
404
- if (newTupleTypes) {
405
- const updatedType = newNarrowTypeBound !== null && newNarrowTypeBound !== void 0 ? newNarrowTypeBound : newWideTypeBound;
406
- if (updatedType) {
407
- newTupleTypes = [{ type: updatedType, isUnbounded: true }];
408
- }
409
- }
410
- if (!typeVarContext.isLocked() && isTypeVarInScope) {
411
- updateTypeVarType(evaluator, typeVarContext, destType, newNarrowTypeBound, newWideTypeBound, newTupleTypes, (flags & (2048 /* AssignTypeFlags.PopulatingExpectedType */ | 256 /* AssignTypeFlags.RetainLiteralsForTypeVar */)) !== 0);
412
- }
413
- if (logTypeVarContextUpdates) {
414
- const indent = ' '.repeat(recursionCount * 2);
415
- console.log(`${indent}`);
416
- console.log(`${indent}post-call context #${typeVarContext.getId()}: `);
417
- logTypeVarContext(evaluator, typeVarContext, indent);
628
+ if (constraints && !constraints.isLocked()) {
629
+ updateTypeVarType(evaluator, constraints, destType, newLowerBound, newUpperTypeBound, (flags & (2048 /* AssignTypeFlags.PopulatingExpectedType */ | 256 /* AssignTypeFlags.RetainLiteralsForTypeVar */)) !== 0);
418
630
  }
419
631
  return true;
420
632
  }
421
- exports.assignTypeToTypeVar = assignTypeToTypeVar;
422
- // Updates the narrow and wide type bounds for a type variable. It also calculates the
423
- // narrowTypeBoundNoLiterals, which is a variant of the narrow type bound that has
424
- // literals stripped. By default, the constraint solver always uses the "no literals"
425
- // type in its solutions unless the version with literals is required to satisfy
426
- // the wide type bound.
427
- function updateTypeVarType(evaluator, typeVarContext, destType, narrowTypeBound, wideTypeBound, tupleTypes = undefined, forceRetainLiterals = false) {
428
- let narrowTypeBoundNoLiterals;
429
- if (narrowTypeBound && !forceRetainLiterals) {
430
- const strippedLiteral = (0, types_1.isVariadicTypeVar)(destType)
431
- ? stripLiteralValueForUnpackedTuple(evaluator, narrowTypeBound)
432
- : evaluator.stripLiteralValue(narrowTypeBound);
433
- // Strip the literals from the narrow type bound and see if it is still
434
- // narrower than the wide bound.
435
- if (strippedLiteral !== narrowTypeBound) {
436
- if (!wideTypeBound || evaluator.assignType(wideTypeBound, strippedLiteral)) {
437
- narrowTypeBoundNoLiterals = strippedLiteral;
438
- }
439
- }
440
- }
441
- typeVarContext.setTypeVarType(destType, narrowTypeBound, narrowTypeBoundNoLiterals, wideTypeBound, tupleTypes);
442
- }
443
- exports.updateTypeVarType = updateTypeVarType;
444
- function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, typeVarContext, flags, isTypeVarInScope, recursionCount) {
633
+ // Handles assignments to a TypeVar with value constraints.
634
+ function assignConstrainedTypeVar(evaluator, destType, srcType, diag, constraints, flags, recursionCount) {
445
635
  let constrainedType;
446
636
  const concreteSrcType = evaluator.makeTopLevelTypeVarsConcrete(srcType);
447
- const curEntry = typeVarContext.getPrimarySignature().getTypeVar(destType);
448
- const curWideTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.wideBound;
449
- const curNarrowTypeBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.narrowBound;
637
+ const curEntry = constraints === null || constraints === void 0 ? void 0 : constraints.getMainConstraintSet().getTypeVar(destType);
638
+ const curUpperBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.upperBound;
639
+ const curLowerBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.lowerBound;
450
640
  let forceRetainLiterals = false;
451
641
  if ((0, types_1.isTypeVar)(srcType)) {
452
642
  if (evaluator.assignType(destType, concreteSrcType,
453
- /* diag */ undefined, new typeVarContext_1.TypeVarContext(destType.priv.scopeId),
454
- /* srcTypeVarContext */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
643
+ /* diag */ undefined,
644
+ /* destConstraints */ undefined,
645
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
455
646
  constrainedType = srcType;
456
647
  // If the source and dest are both instantiables (type[T]), then
457
648
  // we need to convert to an instance (T).
@@ -479,15 +670,15 @@ function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, type
479
670
  : constraint;
480
671
  if (evaluator.assignType(adjustedConstraint, srcSubtype,
481
672
  /* diag */ undefined,
482
- /* destTypeVarContext */ undefined,
483
- /* srcTypeVarContext */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
673
+ /* destConstraints */ undefined,
674
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
484
675
  if (!constrainedSubtype ||
485
676
  evaluator.assignType(types_1.TypeBase.isInstantiable(destType)
486
677
  ? (0, typeUtils_1.convertToInstantiable)(constrainedSubtype)
487
678
  : constrainedSubtype, adjustedConstraint,
488
679
  /* diag */ undefined,
489
- /* destTypeVarContext */ undefined,
490
- /* srcTypeVarContext */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
680
+ /* destConstraints */ undefined,
681
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
491
682
  constrainedSubtype = (0, typeUtils_1.addConditionToType)(constraint, (0, typeUtils_1.getTypeCondition)(srcSubtype));
492
683
  constraintIndexUsed = i;
493
684
  }
@@ -524,8 +715,8 @@ function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, type
524
715
  : constraint;
525
716
  return evaluator.assignType(adjustedConstraint, concreteSrcType,
526
717
  /* diag */ undefined,
527
- /* destTypeVarContext */ undefined,
528
- /* srcTypeVarContext */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount);
718
+ /* destConstraints */ undefined,
719
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount);
529
720
  });
530
721
  }
531
722
  }
@@ -542,26 +733,26 @@ function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, type
542
733
  else if ((0, typeUtils_1.isLiteralTypeOrUnion)(constrainedType)) {
543
734
  forceRetainLiterals = true;
544
735
  }
545
- if (curNarrowTypeBound && !(0, types_1.isAnyOrUnknown)(curNarrowTypeBound)) {
546
- if (!evaluator.assignType(curNarrowTypeBound, constrainedType,
736
+ if (curLowerBound && !(0, types_1.isAnyOrUnknown)(curLowerBound)) {
737
+ if (!evaluator.assignType(curLowerBound, constrainedType,
547
738
  /* diag */ undefined,
548
- /* destTypeVarContext */ undefined,
549
- /* srcTypeVarContext */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
739
+ /* destConstraints */ undefined,
740
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
550
741
  // Handle the case where one of the constrained types is a wider
551
742
  // version of another constrained type that was previously assigned
552
743
  // to the type variable.
553
- if (evaluator.assignType(constrainedType, curNarrowTypeBound,
744
+ if (evaluator.assignType(constrainedType, curLowerBound,
554
745
  /* diag */ undefined,
555
- /* destTypeVarContext */ undefined,
556
- /* srcTypeVarContext */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
557
- if (!typeVarContext.isLocked() && isTypeVarInScope) {
558
- updateTypeVarType(evaluator, typeVarContext, destType, constrainedType, curWideTypeBound);
746
+ /* destConstraints */ undefined,
747
+ /* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
748
+ if (constraints && !constraints.isLocked()) {
749
+ updateTypeVarType(evaluator, constraints, destType, constrainedType, curUpperBound);
559
750
  }
560
751
  }
561
752
  else {
562
753
  diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.LocAddendum.typeConstrainedTypeVar().format({
563
754
  type: evaluator.printType(constrainedType),
564
- name: evaluator.printType(curNarrowTypeBound),
755
+ name: evaluator.printType(curLowerBound),
565
756
  }));
566
757
  return false;
567
758
  }
@@ -569,22 +760,32 @@ function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, type
569
760
  }
570
761
  else {
571
762
  // Assign the type to the type var.
572
- if (!typeVarContext.isLocked() && isTypeVarInScope) {
573
- updateTypeVarType(evaluator, typeVarContext, destType, constrainedType, curWideTypeBound,
574
- /* tupleTypes */ undefined, forceRetainLiterals);
763
+ if (constraints && !constraints.isLocked()) {
764
+ updateTypeVarType(evaluator, constraints, destType, constrainedType, curUpperBound, forceRetainLiterals);
575
765
  }
576
766
  }
577
767
  return true;
578
768
  }
579
- function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContext, recursionCount = 0) {
769
+ // Handles assignments to a ParamSpec.
770
+ function assignParamSpec(evaluator, destType, srcType, diag, constraints, recursionCount = 0) {
771
+ // If there is no constraint tracker, there's nothing to do because
772
+ // param specs have no upper bounds or constraints.
773
+ if (!constraints) {
774
+ return true;
775
+ }
580
776
  let isAssignable = true;
581
- const adjSrcType = (0, types_1.isFunction)(srcType) ? (0, typeUtils_1.convertParamSpecValueToType)(srcType) : srcType;
582
- typeVarContext.doForEachSignature((signatureContext) => {
583
- if ((0, types_1.isTypeVar)(adjSrcType) && adjSrcType.shared.isParamSpec) {
584
- const existingType = signatureContext.getParamSpecType(destType);
777
+ let adjSrcType = (0, types_1.isParamSpec)(srcType) ? srcType : (0, typeUtils_1.convertTypeToParamSpecValue)(srcType);
778
+ if ((0, types_1.isFunction)(adjSrcType)) {
779
+ adjSrcType = (0, typeUtils_1.simplifyFunctionToParamSpec)(adjSrcType);
780
+ }
781
+ constraints.doForEachConstraintSet((constraintSet) => {
782
+ var _a, _b;
783
+ if ((0, types_1.isParamSpec)(adjSrcType)) {
784
+ const existingType = (_a = constraintSet.getTypeVar(destType)) === null || _a === void 0 ? void 0 : _a.lowerBound;
585
785
  if (existingType) {
586
- const existingTypeParamSpec = types_1.FunctionType.getParamSpecFromArgsKwargs(existingType);
587
- const existingTypeWithoutArgsKwargs = types_1.FunctionType.cloneRemoveParamSpecArgsKwargs(existingType);
786
+ const paramSpecValue = (0, typeUtils_1.convertTypeToParamSpecValue)(existingType);
787
+ const existingTypeParamSpec = types_1.FunctionType.getParamSpecFromArgsKwargs(paramSpecValue);
788
+ const existingTypeWithoutArgsKwargs = types_1.FunctionType.cloneRemoveParamSpecArgsKwargs(paramSpecValue);
588
789
  if (existingTypeWithoutArgsKwargs.shared.parameters.length === 0 && existingTypeParamSpec) {
589
790
  // If there's an existing entry that matches, that's fine.
590
791
  if ((0, types_1.isTypeSame)(existingTypeParamSpec, adjSrcType, {}, recursionCount)) {
@@ -593,8 +794,8 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
593
794
  }
594
795
  }
595
796
  else {
596
- if (!typeVarContext.isLocked() && typeVarContext.hasSolveForScope(destType.priv.scopeId)) {
597
- signatureContext.setTypeVarType(destType, (0, typeUtils_1.convertTypeToParamSpecValue)(adjSrcType));
797
+ if (!constraints.isLocked()) {
798
+ constraintSet.setBounds(destType, adjSrcType);
598
799
  }
599
800
  return;
600
801
  }
@@ -602,19 +803,19 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
602
803
  else if ((0, types_1.isFunction)(adjSrcType)) {
603
804
  const newFunction = adjSrcType;
604
805
  let updateContextWithNewFunction = false;
605
- const existingType = signatureContext.getParamSpecType(destType);
806
+ const existingType = (_b = constraintSet.getTypeVar(destType)) === null || _b === void 0 ? void 0 : _b.lowerBound;
606
807
  if (existingType) {
607
808
  // Convert the remaining portion of the signature to a function
608
809
  // for comparison purposes.
609
- const existingFunction = (0, typeUtils_1.convertParamSpecValueToType)(existingType);
810
+ const existingFunction = (0, typeUtils_1.simplifyFunctionToParamSpec)((0, typeUtils_1.convertTypeToParamSpecValue)(existingType));
610
811
  const isNewNarrower = evaluator.assignType(existingFunction, newFunction,
611
812
  /* diag */ undefined,
612
- /* destTypeVarContext */ undefined,
613
- /* srcTypeVarContext */ undefined, 64 /* AssignTypeFlags.SkipReturnTypeCheck */, recursionCount);
813
+ /* destConstraints */ undefined,
814
+ /* srcConstraints */ undefined, 64 /* AssignTypeFlags.SkipReturnTypeCheck */, recursionCount);
614
815
  const isNewWider = evaluator.assignType(newFunction, existingFunction,
615
816
  /* diag */ undefined,
616
- /* destTypeVarContext */ undefined,
617
- /* srcTypeVarContext */ undefined, 64 /* AssignTypeFlags.SkipReturnTypeCheck */, recursionCount);
817
+ /* destConstraints */ undefined,
818
+ /* srcConstraints */ undefined, 64 /* AssignTypeFlags.SkipReturnTypeCheck */, recursionCount);
618
819
  // Should we widen the type?
619
820
  if (isNewNarrower && isNewWider) {
620
821
  // The new type is both a supertype and a subtype of the existing type.
@@ -642,8 +843,8 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
642
843
  updateContextWithNewFunction = true;
643
844
  }
644
845
  if (updateContextWithNewFunction) {
645
- if (!typeVarContext.isLocked() && typeVarContext.hasSolveForScope(destType.priv.scopeId)) {
646
- signatureContext.setTypeVarType(destType, newFunction);
846
+ if (!constraints.isLocked()) {
847
+ constraintSet.setBounds(destType, newFunction);
647
848
  }
648
849
  return;
649
850
  }
@@ -657,173 +858,30 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
657
858
  }));
658
859
  isAssignable = false;
659
860
  });
660
- if (logTypeVarContextUpdates) {
661
- const indent = ' '.repeat(recursionCount * 2);
662
- console.log(`${indent}`);
663
- console.log(`${indent}post-call typeVarContext: `);
664
- logTypeVarContext(evaluator, typeVarContext, indent);
665
- }
666
861
  return isAssignable;
667
862
  }
668
- // In cases where the expected type is a specialized base class of the
669
- // source type, we need to determine which type arguments in the derived
670
- // class will make it compatible with the specialized base class. This method
671
- // performs this reverse mapping of type arguments and populates the type var
672
- // map for the target type. If the type is not assignable to the expected type,
673
- // it returns false.
674
- function addConstraintsForExpectedType(evaluator, type, expectedType, typeVarContext, liveTypeVarScopes, usageOffset = undefined) {
675
- if ((0, types_1.isAny)(expectedType)) {
676
- type.shared.typeParameters.forEach((typeParam) => {
677
- updateTypeVarType(evaluator, typeVarContext, typeParam, expectedType, expectedType);
678
- });
679
- return true;
680
- }
681
- if ((0, types_1.isTypeVar)(expectedType) && expectedType.shared.isSynthesizedSelf && expectedType.shared.boundType) {
682
- expectedType = expectedType.shared.boundType;
683
- }
684
- if (!(0, types_1.isClass)(expectedType)) {
685
- return false;
686
- }
687
- // If the expected type is generic (but not specialized), we can't proceed.
688
- const expectedTypeArgs = expectedType.priv.typeArguments;
689
- if (!expectedTypeArgs) {
690
- return evaluator.assignType(type, expectedType,
691
- /* diag */ undefined, typeVarContext,
692
- /* srcTypeVarContext */ undefined, 2048 /* AssignTypeFlags.PopulatingExpectedType */);
863
+ class UnificationVarTransformer extends typeUtils_1.TypeVarTransformer {
864
+ constructor(_evaluator, _constraintSet) {
865
+ super();
866
+ this._evaluator = _evaluator;
867
+ this._constraintSet = _constraintSet;
693
868
  }
694
- evaluator.inferTypeParameterVarianceForClass(type);
695
- // If the expected type is the same as the target type (commonly the case),
696
- // we can use a faster method.
697
- if (types_1.ClassType.isSameGenericClass(expectedType, type)) {
698
- const sameClassTypeVarContext = (0, typeUtils_1.buildTypeVarContextFromSpecializedClass)(expectedType);
699
- sameClassTypeVarContext
700
- .getPrimarySignature()
701
- .getTypeVars()
702
- .forEach((entry) => {
703
- let typeArgValue = sameClassTypeVarContext.getPrimarySignature().getTypeVarType(entry.typeVar);
704
- if (typeArgValue && liveTypeVarScopes) {
705
- typeArgValue = (0, typeUtils_1.transformExpectedType)(typeArgValue, liveTypeVarScopes, usageOffset);
706
- }
707
- if (typeArgValue) {
708
- const variance = types_1.TypeVarType.getVariance(entry.typeVar);
709
- updateTypeVarType(evaluator, typeVarContext, entry.typeVar, variance === 3 /* Variance.Covariant */ ? undefined : typeArgValue, variance === 4 /* Variance.Contravariant */ ? undefined : typeArgValue);
710
- if (entry.tupleTypes) {
711
- typeVarContext.setTupleTypeVar(entry.typeVar, entry.tupleTypes.map((tupleEntry) => {
712
- let tupleType = tupleEntry.type;
713
- if (liveTypeVarScopes) {
714
- tupleType = (0, typeUtils_1.transformExpectedType)(tupleEntry.type, liveTypeVarScopes, usageOffset);
715
- }
716
- return {
717
- type: tupleType,
718
- isUnbounded: tupleEntry.isUnbounded,
719
- isOptional: tupleEntry.isOptional,
720
- };
721
- }));
722
- }
723
- }
724
- });
725
- return true;
726
- }
727
- // Create a generic version of the expected type.
728
- const expectedTypeScopeId = (0, typeUtils_1.getTypeVarScopeId)(expectedType);
729
- const synthExpectedTypeArgs = types_1.ClassType.getTypeParameters(expectedType).map((typeParam, index) => {
730
- const typeVar = types_1.TypeVarType.createInstance(`__dest${index}`);
731
- typeVar.shared.isSynthesized = true;
732
- if (typeParam.shared.isParamSpec) {
733
- typeVar.shared.isParamSpec = true;
734
- }
735
- // Use invariance here so we set the narrow and wide values on the TypeVar.
736
- typeVar.shared.declaredVariance = 2 /* Variance.Invariant */;
737
- typeVar.priv.scopeId = expectedTypeScopeId;
738
- return typeVar;
739
- });
740
- const genericExpectedType = types_1.ClassType.cloneForSpecialization(expectedType, synthExpectedTypeArgs,
741
- /* isTypeArgumentExplicit */ true);
742
- // For each type param in the target type, create a placeholder type variable.
743
- const typeArgs = types_1.ClassType.getTypeParameters(type).map((typeParam, index) => {
744
- const typeVar = types_1.TypeVarType.createInstance(`__source${index}`);
745
- typeVar.shared.isSynthesized = true;
746
- typeVar.shared.synthesizedIndex = index;
747
- typeVar.shared.isExemptFromBoundCheck = true;
748
- if (typeParam.shared.isParamSpec) {
749
- typeVar.shared.isParamSpec = true;
869
+ transformTypeVar(typeVar) {
870
+ var _a;
871
+ if (types_1.TypeVarType.isUnification(typeVar)) {
872
+ return (_a = getTypeVarType(this._evaluator, this._constraintSet, typeVar)) !== null && _a !== void 0 ? _a : typeVar;
750
873
  }
751
- return types_1.TypeVarType.cloneAsInScopePlaceholder(typeVar);
752
- });
753
- const specializedType = types_1.ClassType.cloneForSpecialization(type, typeArgs, /* isTypeArgumentExplicit */ true);
754
- const syntheticTypeVarContext = new typeVarContext_1.TypeVarContext(expectedTypeScopeId);
755
- if (evaluator.assignType(genericExpectedType, specializedType,
756
- /* diag */ undefined, syntheticTypeVarContext,
757
- /* srcTypeVarContext */ undefined, 2048 /* AssignTypeFlags.PopulatingExpectedType */)) {
758
- let isResultValid = true;
759
- synthExpectedTypeArgs.forEach((typeVar, index) => {
760
- let synthTypeVar = syntheticTypeVarContext.getPrimarySignature().getTypeVarType(typeVar);
761
- const otherSubtypes = [];
762
- // If the resulting type is a union, try to find a matching type var and move
763
- // the remaining subtypes to the "otherSubtypes" array.
764
- if (synthTypeVar) {
765
- if (typeVar.shared.isParamSpec && (0, types_1.isFunction)(synthTypeVar)) {
766
- synthTypeVar = (0, typeUtils_1.convertParamSpecValueToType)(synthTypeVar);
767
- }
768
- if ((0, types_1.isUnion)(synthTypeVar)) {
769
- let foundSynthTypeVar;
770
- (0, typeUtils_1.sortTypes)(synthTypeVar.priv.subtypes).forEach((subtype) => {
771
- if ((0, types_1.isTypeVar)(subtype) &&
772
- subtype.shared.isSynthesized &&
773
- subtype.shared.synthesizedIndex !== undefined &&
774
- !foundSynthTypeVar) {
775
- foundSynthTypeVar = subtype;
776
- }
777
- else {
778
- otherSubtypes.push(subtype);
779
- }
780
- });
781
- if (foundSynthTypeVar) {
782
- synthTypeVar = foundSynthTypeVar;
783
- }
784
- }
785
- }
786
- // Is this one of the synthesized type vars we allocated above? If so,
787
- // the type arg that corresponds to this type var maps back to the target type.
788
- if (synthTypeVar &&
789
- (0, types_1.isTypeVar)(synthTypeVar) &&
790
- synthTypeVar.shared.isSynthesized &&
791
- synthTypeVar.shared.synthesizedIndex !== undefined) {
792
- const targetTypeVar = types_1.ClassType.getTypeParameters(specializedType)[synthTypeVar.shared.synthesizedIndex];
793
- if (index < expectedTypeArgs.length) {
794
- let typeArgValue = (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(expectedTypeArgs[index]);
795
- if (otherSubtypes.length > 0) {
796
- typeArgValue = (0, types_1.combineTypes)([typeArgValue, ...otherSubtypes]);
797
- }
798
- if (liveTypeVarScopes) {
799
- typeArgValue = (0, typeUtils_1.transformExpectedType)(typeArgValue, liveTypeVarScopes, usageOffset);
800
- }
801
- if (typeArgValue) {
802
- const variance = types_1.TypeVarType.getVariance(typeVar);
803
- // If this type variable already has a type, don't overwrite it. This can
804
- // happen if a single type variable in the derived class is used multiple times
805
- // in the specialized base class type (e.g. Mapping[T, T]).
806
- if (typeVarContext.getPrimarySignature().getTypeVarType(targetTypeVar)) {
807
- isResultValid = false;
808
- typeArgValue = types_1.UnknownType.create();
809
- }
810
- updateTypeVarType(evaluator, typeVarContext, targetTypeVar, variance === 3 /* Variance.Covariant */ ? undefined : typeArgValue, variance === 4 /* Variance.Contravariant */ ? undefined : typeArgValue);
811
- }
812
- else {
813
- isResultValid = false;
814
- }
815
- }
816
- }
817
- });
818
- return isResultValid;
874
+ return undefined;
819
875
  }
820
- return false;
821
876
  }
822
- exports.addConstraintsForExpectedType = addConstraintsForExpectedType;
877
+ function applyUnificationVarsToType(evaluator, type, constraintSet) {
878
+ const transformer = new UnificationVarTransformer(evaluator, constraintSet);
879
+ return transformer.apply(type, 0);
880
+ }
823
881
  // For normal TypeVars, the constraint solver can widen a type by combining
824
882
  // two otherwise incompatible types into a union. For TypeVarTuples, we need
825
883
  // to do the equivalent operation for unpacked tuples.
826
- function widenTypeForVariadicTypeVar(evaluator, type1, type2) {
884
+ function widenTypeForTypeVarTuple(evaluator, type1, type2) {
827
885
  // The typing spec indicates that the type should always be "exactly
828
886
  // the same type" if a TypeVarTuple is used in multiple locations.
829
887
  // This is problematic for a number of reasons, but in the interest
@@ -833,9 +891,9 @@ function widenTypeForVariadicTypeVar(evaluator, type1, type2) {
833
891
  return undefined;
834
892
  }
835
893
  // If the two unpacked tuples are not the same length, we can't combine them.
836
- if (!type1.priv.tupleTypeArguments ||
837
- !type2.priv.tupleTypeArguments ||
838
- type1.priv.tupleTypeArguments.length !== type2.priv.tupleTypeArguments.length) {
894
+ if (!type1.priv.tupleTypeArgs ||
895
+ !type2.priv.tupleTypeArgs ||
896
+ type1.priv.tupleTypeArgs.length !== type2.priv.tupleTypeArgs.length) {
839
897
  return undefined;
840
898
  }
841
899
  const strippedType1 = stripLiteralValueForUnpackedTuple(evaluator, type1);
@@ -848,11 +906,11 @@ function widenTypeForVariadicTypeVar(evaluator, type1, type2) {
848
906
  // If the provided type is an unpacked tuple, this function strips the
849
907
  // literals from types of the corresponding elements.
850
908
  function stripLiteralValueForUnpackedTuple(evaluator, type) {
851
- if (!(0, types_1.isUnpackedClass)(type) || !type.priv.tupleTypeArguments) {
909
+ if (!(0, types_1.isUnpackedClass)(type) || !type.priv.tupleTypeArgs) {
852
910
  return type;
853
911
  }
854
912
  let strippedLiteral = false;
855
- const tupleTypeArgs = type.priv.tupleTypeArguments.map((arg) => {
913
+ const tupleTypeArgs = type.priv.tupleTypeArgs.map((arg) => {
856
914
  const strippedType = evaluator.stripLiteralValue(arg.type);
857
915
  if (strippedType !== arg.type) {
858
916
  strippedLiteral = true;
@@ -866,44 +924,44 @@ function stripLiteralValueForUnpackedTuple(evaluator, type) {
866
924
  if (!strippedLiteral) {
867
925
  return type;
868
926
  }
869
- return (0, typeUtils_1.specializeTupleClass)(type, tupleTypeArgs, /* isTypeArgumentExplicit */ true, /* isUnpackedTuple */ true);
927
+ return (0, typeUtils_1.specializeTupleClass)(type, tupleTypeArgs, /* isTypeArgExplicit */ true, /* isUnpackedTuple */ true);
870
928
  }
871
929
  // This function is used for debugging only. It dumps the current contents of
872
- // the TypeVarContext to the console.
873
- function logTypeVarContext(evaluator, typeVarContext, indent) {
874
- const signatureContextCount = typeVarContext.getSignatureContexts().length;
875
- if (signatureContextCount === 0) {
930
+ // the constraints to the console.
931
+ function logConstraints(evaluator, constraints, indent) {
932
+ const constraintSetCount = constraints.getConstraintSets().length;
933
+ if (constraintSetCount === 0) {
876
934
  console.log(`${indent} no signatures`);
877
935
  }
878
- else if (signatureContextCount === 1) {
879
- logTypeVarSignatureContext(evaluator, typeVarContext.getSignatureContexts()[0], `${indent} `);
936
+ else if (constraintSetCount === 1) {
937
+ logTypeVarConstraintSet(evaluator, constraints.getConstraintSets()[0], `${indent} `);
880
938
  }
881
939
  else {
882
- typeVarContext.doForEachSignatureContext((context, signatureIndex) => {
883
- console.log(`${indent} signature ${signatureIndex}`);
884
- logTypeVarSignatureContext(evaluator, context, `${indent} `);
940
+ constraints.doForEachConstraintSet((set, index) => {
941
+ console.log(`${indent} signature ${index}`);
942
+ logTypeVarConstraintSet(evaluator, set, `${indent} `);
885
943
  });
886
944
  }
887
945
  }
888
- function logTypeVarSignatureContext(evaluator, context, indent) {
946
+ function logTypeVarConstraintSet(evaluator, context, indent) {
889
947
  let loggedConstraint = false;
890
948
  context.getTypeVars().forEach((entry) => {
891
949
  var _a;
892
950
  const typeVarName = `${indent}${entry.typeVar.shared.name}`;
893
- const narrowBound = (_a = entry.narrowBoundNoLiterals) !== null && _a !== void 0 ? _a : entry.narrowBound;
894
- const wideBound = entry.wideBound;
895
- // Log the narrow and wide bounds.
896
- if (narrowBound && wideBound && (0, types_1.isTypeSame)(narrowBound, wideBound)) {
897
- console.log(`${typeVarName} = ${evaluator.printType(narrowBound)}`);
951
+ const lowerBound = (_a = entry.lowerBoundNoLiterals) !== null && _a !== void 0 ? _a : entry.lowerBound;
952
+ const upperBound = entry.upperBound;
953
+ // Log the lower and upper bounds.
954
+ if (lowerBound && upperBound && (0, types_1.isTypeSame)(lowerBound, upperBound)) {
955
+ console.log(`${typeVarName} = ${evaluator.printType(lowerBound)}`);
898
956
  loggedConstraint = true;
899
957
  }
900
958
  else {
901
- if (narrowBound) {
902
- console.log(`${typeVarName} ≤ ${evaluator.printType(narrowBound)}`);
959
+ if (lowerBound) {
960
+ console.log(`${typeVarName} ≤ ${evaluator.printType(lowerBound)}`);
903
961
  loggedConstraint = true;
904
962
  }
905
- if (wideBound) {
906
- console.log(`${typeVarName} ≥ ${evaluator.printType(wideBound)}`);
963
+ if (upperBound) {
964
+ console.log(`${typeVarName} ≥ ${evaluator.printType(upperBound)}`);
907
965
  loggedConstraint = true;
908
966
  }
909
967
  }