@zzzen/pyright-internal 1.2.0-dev.20240728 → 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.
- package/dist/analyzer/binder.js +7 -4
- package/dist/analyzer/binder.js.map +1 -1
- package/dist/analyzer/checker.d.ts +2 -1
- package/dist/analyzer/checker.js +135 -83
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/codeFlowEngine.js +4 -4
- package/dist/analyzer/codeFlowEngine.js.map +1 -1
- package/dist/analyzer/constraintSolution.d.ts +21 -0
- package/dist/analyzer/constraintSolution.js +71 -0
- package/dist/analyzer/constraintSolution.js.map +1 -0
- package/dist/analyzer/constraintSolver.d.ts +9 -5
- package/dist/analyzer/constraintSolver.js +420 -322
- package/dist/analyzer/constraintSolver.js.map +1 -1
- package/dist/analyzer/constraintTracker.d.ts +44 -0
- package/dist/analyzer/constraintTracker.js +230 -0
- package/dist/analyzer/constraintTracker.js.map +1 -0
- package/dist/analyzer/constructorTransform.js +15 -15
- package/dist/analyzer/constructorTransform.js.map +1 -1
- package/dist/analyzer/constructors.d.ts +1 -1
- package/dist/analyzer/constructors.js +59 -38
- package/dist/analyzer/constructors.js.map +1 -1
- package/dist/analyzer/dataClasses.js +35 -32
- package/dist/analyzer/dataClasses.js.map +1 -1
- package/dist/analyzer/decorators.js +1 -1
- package/dist/analyzer/decorators.js.map +1 -1
- package/dist/analyzer/functionTransform.js +1 -1
- package/dist/analyzer/functionTransform.js.map +1 -1
- package/dist/analyzer/operations.d.ts +1 -2
- package/dist/analyzer/operations.js +95 -72
- package/dist/analyzer/operations.js.map +1 -1
- package/dist/analyzer/packageTypeVerifier.js +8 -4
- package/dist/analyzer/packageTypeVerifier.js.map +1 -1
- package/dist/analyzer/parameterUtils.d.ts +3 -3
- package/dist/analyzer/parameterUtils.js +19 -21
- package/dist/analyzer/parameterUtils.js.map +1 -1
- package/dist/analyzer/patternMatching.js +21 -19
- package/dist/analyzer/patternMatching.js.map +1 -1
- package/dist/analyzer/properties.d.ts +3 -2
- package/dist/analyzer/properties.js +11 -11
- package/dist/analyzer/properties.js.map +1 -1
- package/dist/analyzer/protocols.d.ts +3 -3
- package/dist/analyzer/protocols.js +50 -48
- package/dist/analyzer/protocols.js.map +1 -1
- package/dist/analyzer/tuples.d.ts +2 -2
- package/dist/analyzer/tuples.js +10 -9
- package/dist/analyzer/tuples.js.map +1 -1
- package/dist/analyzer/typeComplexity.js +12 -4
- package/dist/analyzer/typeComplexity.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +806 -778
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +28 -8
- package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
- package/dist/analyzer/typeGuards.js +46 -39
- package/dist/analyzer/typeGuards.js.map +1 -1
- package/dist/analyzer/typePrinter.js +17 -15
- package/dist/analyzer/typePrinter.js.map +1 -1
- package/dist/analyzer/typeUtils.d.ts +32 -30
- package/dist/analyzer/typeUtils.js +331 -563
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/analyzer/typeWalker.js +1 -1
- package/dist/analyzer/typeWalker.js.map +1 -1
- package/dist/analyzer/typedDicts.d.ts +2 -2
- package/dist/analyzer/typedDicts.js +25 -25
- package/dist/analyzer/typedDicts.js.map +1 -1
- package/dist/analyzer/types.d.ts +24 -21
- package/dist/analyzer/types.js +110 -113
- package/dist/analyzer/types.js.map +1 -1
- package/dist/languageServerBase.d.ts +2 -2
- package/dist/languageServerBase.js +5 -2
- package/dist/languageServerBase.js.map +1 -1
- package/dist/languageService/completionProvider.js +2 -2
- package/dist/languageService/completionProvider.js.map +1 -1
- package/dist/tests/checker.test.js +10 -2
- package/dist/tests/checker.test.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +1 -1
- package/dist/tests/typeEvaluator2.test.js +12 -0
- package/dist/tests/typeEvaluator2.test.js.map +1 -1
- package/dist/tests/typeEvaluator3.test.js +4 -0
- package/dist/tests/typeEvaluator3.test.js.map +1 -1
- package/dist/tests/typeEvaluator4.test.js +1 -1
- package/dist/tests/typeEvaluator5.test.js +1 -1
- package/dist/tests/typeEvaluator7.test.js +4 -0
- package/dist/tests/typeEvaluator7.test.js.map +1 -1
- package/dist/tests/typeEvaluator8.test.js +4 -0
- package/dist/tests/typeEvaluator8.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/analyzer/typeVarContext.d.ts +0 -48
- package/dist/analyzer/typeVarContext.js +0 -288
- package/dist/analyzer/typeVarContext.js.map +0 -1
@@ -10,140 +10,372 @@
|
|
10
10
|
*
|
11
11
|
*/
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
13
|
-
exports.addConstraintsForExpectedType = exports.updateTypeVarType = exports.
|
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
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
24
|
const maxSubtypeCountForTypeVarLowerBound = 64;
|
24
|
-
// This debugging switch enables logging of the
|
25
|
+
// This debugging switch enables logging of the constraints before and
|
25
26
|
// after it is updated by the constraint solver.
|
26
|
-
const
|
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
|
34
|
-
|
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}
|
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
|
-
|
42
|
-
|
43
|
+
if (constraints) {
|
44
|
+
logConstraints(evaluator, constraints, indent);
|
45
|
+
}
|
43
46
|
}
|
44
|
-
let isTypeVarInScope = true;
|
45
|
-
const isInvariant = (flags & 1 /* AssignTypeFlags.EnforceInvariance */) !== 0;
|
46
|
-
const isContravariant = (flags & 2 /* AssignTypeFlags.ReverseTypeVarMatching */) !== 0 && !isInvariant;
|
47
47
|
// If the TypeVar doesn't have a scope ID, then it's being used
|
48
48
|
// outside of a valid TypeVar scope. This will be reported as a
|
49
49
|
// separate error. Just ignore this case to avoid redundant errors.
|
50
50
|
if (!destType.priv.scopeId) {
|
51
51
|
return true;
|
52
52
|
}
|
53
|
+
if (types_1.TypeVarType.isBound(destType) && !types_1.TypeVarType.isUnification(destType)) {
|
54
|
+
return assignBoundTypeVar(evaluator, destType, srcType, diag, flags);
|
55
|
+
}
|
53
56
|
// Handle type[T] as a dest and a special form as a source.
|
54
57
|
if (types_1.TypeBase.isInstantiable(destType) &&
|
55
58
|
(0, types_1.isInstantiableClass)(srcType) &&
|
56
59
|
evaluator.isSpecialFormClass(srcType, flags)) {
|
57
60
|
return false;
|
58
61
|
}
|
59
|
-
//
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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));
|
74
78
|
}
|
75
79
|
}
|
76
|
-
//
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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);
|
82
87
|
}
|
83
|
-
//
|
84
|
-
//
|
85
|
-
|
86
|
-
|
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);
|
87
94
|
}
|
88
|
-
|
89
|
-
|
90
|
-
if ((flags & 1024 /* AssignTypeFlags.IgnoreTypeVarScope */) !== 0) {
|
91
|
-
return true;
|
95
|
+
else {
|
96
|
+
isAssignable = assignUnconstrainedTypeVar(evaluator, destType, srcType, diag, constraints, flags, recursionCount);
|
92
97
|
}
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
98
|
+
}
|
99
|
+
if (logConstraintsUpdates) {
|
100
|
+
const indent = ' '.repeat(recursionCount * 2);
|
101
|
+
console.log(`${indent}`);
|
102
|
+
if (constraints) {
|
103
|
+
logConstraints(evaluator, constraints, indent);
|
99
104
|
}
|
100
105
|
}
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
+
});
|
104
163
|
return true;
|
105
164
|
}
|
106
|
-
if ((
|
107
|
-
|
108
|
-
/* destTypeVarContext */ undefined,
|
109
|
-
/* srcTypeVarContext */ undefined, flags, recursionCount);
|
165
|
+
if ((0, types_1.isTypeVar)(expectedType) && types_1.TypeVarType.isSelf(expectedType) && expectedType.shared.boundType) {
|
166
|
+
expectedType = expectedType.shared.boundType;
|
110
167
|
}
|
111
|
-
if ((0, types_1.
|
112
|
-
return
|
168
|
+
if (!(0, types_1.isClass)(expectedType)) {
|
169
|
+
return false;
|
113
170
|
}
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
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 */);
|
177
|
+
}
|
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);
|
122
188
|
}
|
123
|
-
|
124
|
-
|
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);
|
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;
|
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);
|
125
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;
|
315
|
+
}
|
316
|
+
if ((0, types_1.isParamSpec)(typeVar)) {
|
317
|
+
if (!entry.lowerBound) {
|
318
|
+
return undefined;
|
126
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;
|
127
349
|
}
|
128
|
-
//
|
129
|
-
|
130
|
-
if ((0, types_1.
|
131
|
-
|
132
|
-
!srcType.priv.isVariadicInUnion &&
|
133
|
-
!(0, types_1.isTypeVarTuple)(destType)) {
|
134
|
-
srcType = types_1.TypeVarType.cloneForUnpacked(srcType, /* isInUnion */ true);
|
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;
|
135
354
|
}
|
136
|
-
// Handle
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
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
|
+
}
|
142
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)));
|
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;
|
143
375
|
// Handle the unconstrained (but possibly bound) case.
|
144
|
-
const curEntry =
|
376
|
+
const curEntry = constraints === null || constraints === void 0 ? void 0 : constraints.getMainConstraintSet().getTypeVar(destType);
|
145
377
|
let curUpperBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.upperBound;
|
146
|
-
if (!curUpperBound && !
|
378
|
+
if (!curUpperBound && !types_1.TypeVarType.isSelf(destType)) {
|
147
379
|
curUpperBound = destType.shared.boundType;
|
148
380
|
}
|
149
381
|
let curLowerBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.lowerBound;
|
@@ -207,14 +439,14 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
207
439
|
}
|
208
440
|
else if (!(0, types_1.isTypeSame)(curUpperBound, adjSrcType, {}, recursionCount)) {
|
209
441
|
if (evaluator.assignType(curUpperBound, evaluator.makeTopLevelTypeVarsConcrete(adjSrcType), diagAddendum,
|
210
|
-
/*
|
211
|
-
/*
|
442
|
+
/* destConstraints */ undefined,
|
443
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
212
444
|
// The srcType is narrower than the current upper bound, so replace it.
|
213
445
|
newUpperTypeBound = adjSrcType;
|
214
446
|
}
|
215
447
|
else if (!evaluator.assignType(adjSrcType, curUpperBound, diagAddendum,
|
216
|
-
/*
|
217
|
-
/*
|
448
|
+
/* destConstraints */ undefined,
|
449
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
218
450
|
if (diag && diagAddendum) {
|
219
451
|
diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(curUpperBound, adjSrcType)));
|
220
452
|
diag.addAddendum(diagAddendum);
|
@@ -226,8 +458,8 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
226
458
|
if (curLowerBound) {
|
227
459
|
if (!evaluator.assignType(newUpperTypeBound, curLowerBound,
|
228
460
|
/* diag */ undefined,
|
229
|
-
/*
|
230
|
-
/*
|
461
|
+
/* destConstraints */ undefined,
|
462
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
231
463
|
if (diag && diagAddendum) {
|
232
464
|
diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(curLowerBound, newUpperTypeBound)));
|
233
465
|
diag.addAddendum(diagAddendum);
|
@@ -250,26 +482,29 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
250
482
|
}
|
251
483
|
}
|
252
484
|
else {
|
253
|
-
if (evaluator.assignType(curLowerBound, adjSrcType, diagAddendum,
|
254
|
-
/*
|
485
|
+
if (evaluator.assignType(curLowerBound, adjSrcType, diagAddendum, constraints,
|
486
|
+
/* srcConstraints */ undefined, flags, recursionCount)) {
|
255
487
|
// No need to widen. Stick with the existing type unless it's unknown
|
256
488
|
// or partly unknown, in which case we'll replace it with a known type
|
257
489
|
// as long as it doesn't violate the current lower bound.
|
258
490
|
if ((0, typeUtils_1.isPartlyUnknown)(curLowerBound) &&
|
259
491
|
!(0, types_1.isUnknown)(adjSrcType) &&
|
260
492
|
evaluator.assignType(adjSrcType, curLowerBound,
|
261
|
-
/* diag */ undefined,
|
262
|
-
/*
|
493
|
+
/* diag */ undefined, constraints,
|
494
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
263
495
|
newLowerBound = adjSrcType;
|
264
496
|
}
|
265
497
|
else {
|
266
|
-
newLowerBound =
|
498
|
+
newLowerBound = curLowerBound;
|
499
|
+
if (constraints) {
|
500
|
+
newLowerBound = evaluator.solveAndApplyConstraints(newLowerBound, constraints);
|
501
|
+
}
|
267
502
|
}
|
268
503
|
}
|
269
504
|
else if ((0, types_1.isTypeVar)(curLowerBound) &&
|
270
505
|
!(0, types_1.isTypeVar)(adjSrcType) &&
|
271
|
-
evaluator.assignType(evaluator.makeTopLevelTypeVarsConcrete(curLowerBound), adjSrcType, diagAddendum,
|
272
|
-
/*
|
506
|
+
evaluator.assignType(evaluator.makeTopLevelTypeVarsConcrete(curLowerBound), adjSrcType, diagAddendum, constraints,
|
507
|
+
/* srcConstraints */ undefined, flags, recursionCount)) {
|
273
508
|
// If the existing lower bound was a TypeVar that is not
|
274
509
|
// part of the current context we can replace it with the new
|
275
510
|
// source type.
|
@@ -277,13 +512,13 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
277
512
|
}
|
278
513
|
else {
|
279
514
|
// We need to widen the type.
|
280
|
-
if (
|
515
|
+
if (constraints === null || constraints === void 0 ? void 0 : constraints.isLocked()) {
|
281
516
|
diag === null || diag === void 0 ? void 0 : diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(adjSrcType, curLowerBound)));
|
282
517
|
return false;
|
283
518
|
}
|
284
519
|
if (evaluator.assignType(adjSrcType, curLowerBound,
|
285
|
-
/* diag */ undefined,
|
286
|
-
/*
|
520
|
+
/* diag */ undefined, constraints,
|
521
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
287
522
|
newLowerBound = adjSrcType;
|
288
523
|
}
|
289
524
|
else if ((0, types_1.isTypeVarTuple)(destType)) {
|
@@ -302,7 +537,10 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
302
537
|
if (!newUpperTypeBound && isInvariant && (curEntry === null || curEntry === void 0 ? void 0 : curEntry.lowerBoundNoLiterals)) {
|
303
538
|
curLowerBound = curEntry.lowerBoundNoLiterals;
|
304
539
|
}
|
305
|
-
|
540
|
+
let curSolvedLowerBound = curLowerBound;
|
541
|
+
if (constraints) {
|
542
|
+
curSolvedLowerBound = evaluator.solveAndApplyConstraints(curLowerBound, constraints);
|
543
|
+
}
|
306
544
|
// In some extreme edge cases, the lower bound can become
|
307
545
|
// a union with so many subtypes that performance grinds to a
|
308
546
|
// halt. We'll detect this case and widen the resulting type
|
@@ -310,7 +548,7 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
310
548
|
// is still a valid solution to the TypeVar.
|
311
549
|
if ((0, types_1.isUnion)(curSolvedLowerBound) &&
|
312
550
|
curSolvedLowerBound.priv.subtypes.length > typeEvaluatorTypes_1.maxSubtypesForInferredType &&
|
313
|
-
|
551
|
+
types_1.TypeVarType.hasBound(destType) &&
|
314
552
|
(0, types_1.isClassInstance)(objectType)) {
|
315
553
|
newLowerBound = (0, types_1.combineTypes)([curSolvedLowerBound, objectType], {
|
316
554
|
maxSubtypeCount: maxSubtypeCountForTypeVarLowerBound,
|
@@ -328,8 +566,8 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
328
566
|
// isn't too wide.
|
329
567
|
if (isInvariant && newLowerBound) {
|
330
568
|
if (!evaluator.assignType(adjSrcType, newLowerBound, diag === null || diag === void 0 ? void 0 : diag.createAddendum(),
|
331
|
-
/*
|
332
|
-
/*
|
569
|
+
/* destConstraints */ undefined,
|
570
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
333
571
|
if (diag && diagAddendum) {
|
334
572
|
diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(newLowerBound, adjSrcType)));
|
335
573
|
}
|
@@ -342,13 +580,13 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
342
580
|
let adjUpperBound = evaluator.makeTopLevelTypeVarsConcrete(curUpperBound,
|
343
581
|
/* makeParamSpecsConcrete */ true);
|
344
582
|
// Convert any remaining (non-top-level) TypeVars in the upper
|
345
|
-
// bound to
|
583
|
+
// bound to unification vars.
|
346
584
|
adjUpperBound = (0, typeUtils_1.transformExpectedType)(adjUpperBound,
|
347
585
|
/* liveTypeVarScopes */ [],
|
348
586
|
/* usageOffset */ undefined);
|
349
587
|
if (!evaluator.assignType(adjUpperBound, newLowerBound, diag === null || diag === void 0 ? void 0 : diag.createAddendum(),
|
350
|
-
/*
|
351
|
-
/*
|
588
|
+
/* destConstraints */ undefined,
|
589
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
352
590
|
if (diag && diagAddendum) {
|
353
591
|
diag.addMessage(localize_1.LocAddendum.typeAssignmentMismatch().format(evaluator.printSrcDestTypes(newLowerBound, adjUpperBound)));
|
354
592
|
}
|
@@ -366,17 +604,15 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
366
604
|
// If the dest is a Type[T] but the source is not a valid Type,
|
367
605
|
// skip the assignType check and the diagnostic addendum, which will
|
368
606
|
// be confusing and inaccurate.
|
369
|
-
if (types_1.TypeBase.isInstantiable(destType) && !
|
607
|
+
if (types_1.TypeBase.isInstantiable(destType) && !(0, typeUtils_1.isEffectivelyInstantiable)(srcType)) {
|
370
608
|
return false;
|
371
609
|
}
|
372
610
|
// In general, bound types cannot be generic, but the "Self" type is an
|
373
|
-
// exception. In this case, we need to use the original
|
611
|
+
// exception. In this case, we need to use the original constraints
|
374
612
|
// to solve for the generic type variable(s) in the bound type.
|
375
|
-
const
|
376
|
-
|
377
|
-
|
378
|
-
if (!evaluator.assignType(destType.shared.boundType, evaluator.makeTopLevelTypeVarsConcrete(updatedType), diag === null || diag === void 0 ? void 0 : diag.createAddendum(), effectiveTypeVarContext,
|
379
|
-
/* 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)) {
|
380
616
|
// Avoid adding a message that will confuse users if the TypeVar was
|
381
617
|
// synthesized for internal purposes.
|
382
618
|
if (!destType.shared.isSynthesized) {
|
@@ -389,50 +625,24 @@ function assignTypeToTypeVar(evaluator, destType, srcType, diag, typeVarContext,
|
|
389
625
|
return false;
|
390
626
|
}
|
391
627
|
}
|
392
|
-
if (!
|
393
|
-
updateTypeVarType(evaluator,
|
394
|
-
}
|
395
|
-
if (logTypeVarContextUpdates) {
|
396
|
-
const indent = ' '.repeat(recursionCount * 2);
|
397
|
-
console.log(`${indent}`);
|
398
|
-
logTypeVarContext(evaluator, typeVarContext, indent);
|
628
|
+
if (constraints && !constraints.isLocked()) {
|
629
|
+
updateTypeVarType(evaluator, constraints, destType, newLowerBound, newUpperTypeBound, (flags & (2048 /* AssignTypeFlags.PopulatingExpectedType */ | 256 /* AssignTypeFlags.RetainLiteralsForTypeVar */)) !== 0);
|
399
630
|
}
|
400
631
|
return true;
|
401
632
|
}
|
402
|
-
|
403
|
-
|
404
|
-
// lowerBoundNoLiterals, which is a variant of the lower bound that has
|
405
|
-
// literals stripped. By default, the constraint solver always uses the "no literals"
|
406
|
-
// type in its solutions unless the version with literals is required to satisfy
|
407
|
-
// the upper bound.
|
408
|
-
function updateTypeVarType(evaluator, typeVarContext, destType, lowerBound, upperBound, forceRetainLiterals = false) {
|
409
|
-
let lowerBoundNoLiterals;
|
410
|
-
if (lowerBound && !forceRetainLiterals) {
|
411
|
-
const strippedLiteral = (0, types_1.isTypeVarTuple)(destType)
|
412
|
-
? stripLiteralValueForUnpackedTuple(evaluator, lowerBound)
|
413
|
-
: evaluator.stripLiteralValue(lowerBound);
|
414
|
-
// Strip the literals from the lower bound and see if it is still
|
415
|
-
// narrower than the upper bound.
|
416
|
-
if (strippedLiteral !== lowerBound) {
|
417
|
-
if (!upperBound || evaluator.assignType(upperBound, strippedLiteral)) {
|
418
|
-
lowerBoundNoLiterals = strippedLiteral;
|
419
|
-
}
|
420
|
-
}
|
421
|
-
}
|
422
|
-
typeVarContext.setTypeVarType(destType, lowerBound, lowerBoundNoLiterals, upperBound); //, tupleTypes);
|
423
|
-
}
|
424
|
-
exports.updateTypeVarType = updateTypeVarType;
|
425
|
-
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) {
|
426
635
|
let constrainedType;
|
427
636
|
const concreteSrcType = evaluator.makeTopLevelTypeVarsConcrete(srcType);
|
428
|
-
const curEntry =
|
637
|
+
const curEntry = constraints === null || constraints === void 0 ? void 0 : constraints.getMainConstraintSet().getTypeVar(destType);
|
429
638
|
const curUpperBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.upperBound;
|
430
639
|
const curLowerBound = curEntry === null || curEntry === void 0 ? void 0 : curEntry.lowerBound;
|
431
640
|
let forceRetainLiterals = false;
|
432
641
|
if ((0, types_1.isTypeVar)(srcType)) {
|
433
642
|
if (evaluator.assignType(destType, concreteSrcType,
|
434
|
-
/* diag */ undefined,
|
435
|
-
/*
|
643
|
+
/* diag */ undefined,
|
644
|
+
/* destConstraints */ undefined,
|
645
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
436
646
|
constrainedType = srcType;
|
437
647
|
// If the source and dest are both instantiables (type[T]), then
|
438
648
|
// we need to convert to an instance (T).
|
@@ -460,15 +670,15 @@ function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, type
|
|
460
670
|
: constraint;
|
461
671
|
if (evaluator.assignType(adjustedConstraint, srcSubtype,
|
462
672
|
/* diag */ undefined,
|
463
|
-
/*
|
464
|
-
/*
|
673
|
+
/* destConstraints */ undefined,
|
674
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
465
675
|
if (!constrainedSubtype ||
|
466
676
|
evaluator.assignType(types_1.TypeBase.isInstantiable(destType)
|
467
677
|
? (0, typeUtils_1.convertToInstantiable)(constrainedSubtype)
|
468
678
|
: constrainedSubtype, adjustedConstraint,
|
469
679
|
/* diag */ undefined,
|
470
|
-
/*
|
471
|
-
/*
|
680
|
+
/* destConstraints */ undefined,
|
681
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
472
682
|
constrainedSubtype = (0, typeUtils_1.addConditionToType)(constraint, (0, typeUtils_1.getTypeCondition)(srcSubtype));
|
473
683
|
constraintIndexUsed = i;
|
474
684
|
}
|
@@ -505,8 +715,8 @@ function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, type
|
|
505
715
|
: constraint;
|
506
716
|
return evaluator.assignType(adjustedConstraint, concreteSrcType,
|
507
717
|
/* diag */ undefined,
|
508
|
-
/*
|
509
|
-
/*
|
718
|
+
/* destConstraints */ undefined,
|
719
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount);
|
510
720
|
});
|
511
721
|
}
|
512
722
|
}
|
@@ -526,17 +736,17 @@ function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, type
|
|
526
736
|
if (curLowerBound && !(0, types_1.isAnyOrUnknown)(curLowerBound)) {
|
527
737
|
if (!evaluator.assignType(curLowerBound, constrainedType,
|
528
738
|
/* diag */ undefined,
|
529
|
-
/*
|
530
|
-
/*
|
739
|
+
/* destConstraints */ undefined,
|
740
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
531
741
|
// Handle the case where one of the constrained types is a wider
|
532
742
|
// version of another constrained type that was previously assigned
|
533
743
|
// to the type variable.
|
534
744
|
if (evaluator.assignType(constrainedType, curLowerBound,
|
535
745
|
/* diag */ undefined,
|
536
|
-
/*
|
537
|
-
/*
|
538
|
-
if (!
|
539
|
-
updateTypeVarType(evaluator,
|
746
|
+
/* destConstraints */ undefined,
|
747
|
+
/* srcConstraints */ undefined, 0 /* AssignTypeFlags.Default */, recursionCount)) {
|
748
|
+
if (constraints && !constraints.isLocked()) {
|
749
|
+
updateTypeVarType(evaluator, constraints, destType, constrainedType, curUpperBound);
|
540
750
|
}
|
541
751
|
}
|
542
752
|
else {
|
@@ -550,21 +760,32 @@ function assignTypeToConstrainedTypeVar(evaluator, destType, srcType, diag, type
|
|
550
760
|
}
|
551
761
|
else {
|
552
762
|
// Assign the type to the type var.
|
553
|
-
if (!
|
554
|
-
updateTypeVarType(evaluator,
|
763
|
+
if (constraints && !constraints.isLocked()) {
|
764
|
+
updateTypeVarType(evaluator, constraints, destType, constrainedType, curUpperBound, forceRetainLiterals);
|
555
765
|
}
|
556
766
|
}
|
557
767
|
return true;
|
558
768
|
}
|
559
|
-
|
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
|
+
}
|
560
776
|
let isAssignable = true;
|
561
|
-
|
562
|
-
|
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;
|
563
783
|
if ((0, types_1.isParamSpec)(adjSrcType)) {
|
564
|
-
const existingType =
|
784
|
+
const existingType = (_a = constraintSet.getTypeVar(destType)) === null || _a === void 0 ? void 0 : _a.lowerBound;
|
565
785
|
if (existingType) {
|
566
|
-
const
|
567
|
-
const
|
786
|
+
const paramSpecValue = (0, typeUtils_1.convertTypeToParamSpecValue)(existingType);
|
787
|
+
const existingTypeParamSpec = types_1.FunctionType.getParamSpecFromArgsKwargs(paramSpecValue);
|
788
|
+
const existingTypeWithoutArgsKwargs = types_1.FunctionType.cloneRemoveParamSpecArgsKwargs(paramSpecValue);
|
568
789
|
if (existingTypeWithoutArgsKwargs.shared.parameters.length === 0 && existingTypeParamSpec) {
|
569
790
|
// If there's an existing entry that matches, that's fine.
|
570
791
|
if ((0, types_1.isTypeSame)(existingTypeParamSpec, adjSrcType, {}, recursionCount)) {
|
@@ -573,8 +794,8 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
|
|
573
794
|
}
|
574
795
|
}
|
575
796
|
else {
|
576
|
-
if (!
|
577
|
-
|
797
|
+
if (!constraints.isLocked()) {
|
798
|
+
constraintSet.setBounds(destType, adjSrcType);
|
578
799
|
}
|
579
800
|
return;
|
580
801
|
}
|
@@ -582,19 +803,19 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
|
|
582
803
|
else if ((0, types_1.isFunction)(adjSrcType)) {
|
583
804
|
const newFunction = adjSrcType;
|
584
805
|
let updateContextWithNewFunction = false;
|
585
|
-
const existingType =
|
806
|
+
const existingType = (_b = constraintSet.getTypeVar(destType)) === null || _b === void 0 ? void 0 : _b.lowerBound;
|
586
807
|
if (existingType) {
|
587
808
|
// Convert the remaining portion of the signature to a function
|
588
809
|
// for comparison purposes.
|
589
|
-
const existingFunction = (0, typeUtils_1.
|
810
|
+
const existingFunction = (0, typeUtils_1.simplifyFunctionToParamSpec)((0, typeUtils_1.convertTypeToParamSpecValue)(existingType));
|
590
811
|
const isNewNarrower = evaluator.assignType(existingFunction, newFunction,
|
591
812
|
/* diag */ undefined,
|
592
|
-
/*
|
593
|
-
/*
|
813
|
+
/* destConstraints */ undefined,
|
814
|
+
/* srcConstraints */ undefined, 64 /* AssignTypeFlags.SkipReturnTypeCheck */, recursionCount);
|
594
815
|
const isNewWider = evaluator.assignType(newFunction, existingFunction,
|
595
816
|
/* diag */ undefined,
|
596
|
-
/*
|
597
|
-
/*
|
817
|
+
/* destConstraints */ undefined,
|
818
|
+
/* srcConstraints */ undefined, 64 /* AssignTypeFlags.SkipReturnTypeCheck */, recursionCount);
|
598
819
|
// Should we widen the type?
|
599
820
|
if (isNewNarrower && isNewWider) {
|
600
821
|
// The new type is both a supertype and a subtype of the existing type.
|
@@ -622,8 +843,8 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
|
|
622
843
|
updateContextWithNewFunction = true;
|
623
844
|
}
|
624
845
|
if (updateContextWithNewFunction) {
|
625
|
-
if (!
|
626
|
-
|
846
|
+
if (!constraints.isLocked()) {
|
847
|
+
constraintSet.setBounds(destType, newFunction);
|
627
848
|
}
|
628
849
|
return;
|
629
850
|
}
|
@@ -637,149 +858,26 @@ function assignTypeToParamSpec(evaluator, destType, srcType, diag, typeVarContex
|
|
637
858
|
}));
|
638
859
|
isAssignable = false;
|
639
860
|
});
|
640
|
-
if (logTypeVarContextUpdates) {
|
641
|
-
const indent = ' '.repeat(recursionCount * 2);
|
642
|
-
console.log(`${indent}`);
|
643
|
-
console.log(`${indent}post-call typeVarContext: `);
|
644
|
-
logTypeVarContext(evaluator, typeVarContext, indent);
|
645
|
-
}
|
646
861
|
return isAssignable;
|
647
862
|
}
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
// it returns false.
|
654
|
-
function addConstraintsForExpectedType(evaluator, type, expectedType, typeVarContext, liveTypeVarScopes, usageOffset = undefined) {
|
655
|
-
if ((0, types_1.isAny)(expectedType)) {
|
656
|
-
type.shared.typeParams.forEach((typeParam) => {
|
657
|
-
updateTypeVarType(evaluator, typeVarContext, typeParam, expectedType, expectedType);
|
658
|
-
});
|
659
|
-
return true;
|
863
|
+
class UnificationVarTransformer extends typeUtils_1.TypeVarTransformer {
|
864
|
+
constructor(_evaluator, _constraintSet) {
|
865
|
+
super();
|
866
|
+
this._evaluator = _evaluator;
|
867
|
+
this._constraintSet = _constraintSet;
|
660
868
|
}
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
// If the expected type is generic (but not specialized), we can't proceed.
|
668
|
-
const expectedTypeArgs = expectedType.priv.typeArgs;
|
669
|
-
if (!expectedTypeArgs) {
|
670
|
-
return evaluator.assignType(type, expectedType,
|
671
|
-
/* diag */ undefined, typeVarContext,
|
672
|
-
/* srcTypeVarContext */ undefined, 2048 /* AssignTypeFlags.PopulatingExpectedType */);
|
673
|
-
}
|
674
|
-
evaluator.inferVarianceForClass(type);
|
675
|
-
// If the expected type is the same as the target type (commonly the case),
|
676
|
-
// we can use a faster method.
|
677
|
-
if (types_1.ClassType.isSameGenericClass(expectedType, type)) {
|
678
|
-
const sameClassTypeVarContext = (0, typeUtils_1.buildTypeVarContextFromSpecializedClass)(expectedType);
|
679
|
-
sameClassTypeVarContext
|
680
|
-
.getMainSolutionSet()
|
681
|
-
.getTypeVars()
|
682
|
-
.forEach((entry) => {
|
683
|
-
let typeArgValue = sameClassTypeVarContext.getMainSolutionSet().getTypeVarType(entry.typeVar);
|
684
|
-
if (typeArgValue && liveTypeVarScopes) {
|
685
|
-
typeArgValue = (0, typeUtils_1.transformExpectedType)(typeArgValue, liveTypeVarScopes, usageOffset);
|
686
|
-
}
|
687
|
-
if (typeArgValue) {
|
688
|
-
const variance = types_1.TypeVarType.getVariance(entry.typeVar);
|
689
|
-
updateTypeVarType(evaluator, typeVarContext, entry.typeVar, variance === 3 /* Variance.Covariant */ ? undefined : typeArgValue, variance === 4 /* Variance.Contravariant */ ? undefined : typeArgValue);
|
690
|
-
}
|
691
|
-
});
|
692
|
-
return true;
|
693
|
-
}
|
694
|
-
// Create a generic version of the expected type.
|
695
|
-
const expectedTypeScopeId = (0, typeUtils_1.getTypeVarScopeId)(expectedType);
|
696
|
-
const synthExpectedTypeArgs = types_1.ClassType.getTypeParams(expectedType).map((typeParam, index) => {
|
697
|
-
const typeVar = types_1.TypeVarType.createInstance(`__dest${index}`, (0, types_1.isParamSpec)(typeParam) ? types_1.TypeVarKind.ParamSpec : types_1.TypeVarKind.TypeVar);
|
698
|
-
typeVar.shared.isSynthesized = true;
|
699
|
-
// Use invariance here so we set the lower and upper bound on the TypeVar.
|
700
|
-
typeVar.shared.declaredVariance = 2 /* Variance.Invariant */;
|
701
|
-
typeVar.priv.scopeId = expectedTypeScopeId;
|
702
|
-
return typeVar;
|
703
|
-
});
|
704
|
-
const genericExpectedType = types_1.ClassType.specialize(expectedType, synthExpectedTypeArgs);
|
705
|
-
// For each type param in the target type, create a placeholder type variable.
|
706
|
-
const typeArgs = types_1.ClassType.getTypeParams(type).map((typeParam, index) => {
|
707
|
-
const typeVar = types_1.TypeVarType.createInstance(`__source${index}`, (0, types_1.isParamSpec)(typeParam) ? types_1.TypeVarKind.ParamSpec : types_1.TypeVarKind.TypeVar);
|
708
|
-
typeVar.shared.isSynthesized = true;
|
709
|
-
typeVar.shared.synthesizedIndex = index;
|
710
|
-
typeVar.shared.isExemptFromBoundCheck = true;
|
711
|
-
return types_1.TypeVarType.cloneAsInScopePlaceholder(typeVar);
|
712
|
-
});
|
713
|
-
const specializedType = types_1.ClassType.specialize(type, typeArgs);
|
714
|
-
const syntheticTypeVarContext = new typeVarContext_1.TypeVarContext(expectedTypeScopeId);
|
715
|
-
if (evaluator.assignType(genericExpectedType, specializedType,
|
716
|
-
/* diag */ undefined, syntheticTypeVarContext,
|
717
|
-
/* srcTypeVarContext */ undefined, 2048 /* AssignTypeFlags.PopulatingExpectedType */)) {
|
718
|
-
let isResultValid = true;
|
719
|
-
synthExpectedTypeArgs.forEach((typeVar, index) => {
|
720
|
-
let synthTypeVar = syntheticTypeVarContext.getMainSolutionSet().getTypeVarType(typeVar);
|
721
|
-
const otherSubtypes = [];
|
722
|
-
// If the resulting type is a union, try to find a matching type var and move
|
723
|
-
// the remaining subtypes to the "otherSubtypes" array.
|
724
|
-
if (synthTypeVar) {
|
725
|
-
if ((0, types_1.isParamSpec)(typeVar) && (0, types_1.isFunction)(synthTypeVar)) {
|
726
|
-
synthTypeVar = (0, typeUtils_1.convertParamSpecValueToType)(synthTypeVar);
|
727
|
-
}
|
728
|
-
if ((0, types_1.isUnion)(synthTypeVar)) {
|
729
|
-
let foundSynthTypeVar;
|
730
|
-
(0, typeUtils_1.sortTypes)(synthTypeVar.priv.subtypes).forEach((subtype) => {
|
731
|
-
if ((0, types_1.isTypeVar)(subtype) &&
|
732
|
-
subtype.shared.isSynthesized &&
|
733
|
-
subtype.shared.synthesizedIndex !== undefined &&
|
734
|
-
!foundSynthTypeVar) {
|
735
|
-
foundSynthTypeVar = subtype;
|
736
|
-
}
|
737
|
-
else {
|
738
|
-
otherSubtypes.push(subtype);
|
739
|
-
}
|
740
|
-
});
|
741
|
-
if (foundSynthTypeVar) {
|
742
|
-
synthTypeVar = foundSynthTypeVar;
|
743
|
-
}
|
744
|
-
}
|
745
|
-
}
|
746
|
-
// Is this one of the synthesized type vars we allocated above? If so,
|
747
|
-
// the type arg that corresponds to this type var maps back to the target type.
|
748
|
-
if (synthTypeVar &&
|
749
|
-
(0, types_1.isTypeVar)(synthTypeVar) &&
|
750
|
-
synthTypeVar.shared.isSynthesized &&
|
751
|
-
synthTypeVar.shared.synthesizedIndex !== undefined) {
|
752
|
-
const targetTypeVar = types_1.ClassType.getTypeParams(specializedType)[synthTypeVar.shared.synthesizedIndex];
|
753
|
-
if (index < expectedTypeArgs.length) {
|
754
|
-
let typeArgValue = (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(expectedTypeArgs[index]);
|
755
|
-
if (otherSubtypes.length > 0) {
|
756
|
-
typeArgValue = (0, types_1.combineTypes)([typeArgValue, ...otherSubtypes]);
|
757
|
-
}
|
758
|
-
if (liveTypeVarScopes) {
|
759
|
-
typeArgValue = (0, typeUtils_1.transformExpectedType)(typeArgValue, liveTypeVarScopes, usageOffset);
|
760
|
-
}
|
761
|
-
if (typeArgValue) {
|
762
|
-
const variance = types_1.TypeVarType.getVariance(typeVar);
|
763
|
-
// If this type variable already has a type, don't overwrite it. This can
|
764
|
-
// happen if a single type variable in the derived class is used multiple times
|
765
|
-
// in the specialized base class type (e.g. Mapping[T, T]).
|
766
|
-
if (typeVarContext.getMainSolutionSet().getTypeVarType(targetTypeVar)) {
|
767
|
-
isResultValid = false;
|
768
|
-
typeArgValue = types_1.UnknownType.create();
|
769
|
-
}
|
770
|
-
updateTypeVarType(evaluator, typeVarContext, targetTypeVar, variance === 3 /* Variance.Covariant */ ? undefined : typeArgValue, variance === 4 /* Variance.Contravariant */ ? undefined : typeArgValue);
|
771
|
-
}
|
772
|
-
else {
|
773
|
-
isResultValid = false;
|
774
|
-
}
|
775
|
-
}
|
776
|
-
}
|
777
|
-
});
|
778
|
-
return isResultValid;
|
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;
|
873
|
+
}
|
874
|
+
return undefined;
|
779
875
|
}
|
780
|
-
return false;
|
781
876
|
}
|
782
|
-
|
877
|
+
function applyUnificationVarsToType(evaluator, type, constraintSet) {
|
878
|
+
const transformer = new UnificationVarTransformer(evaluator, constraintSet);
|
879
|
+
return transformer.apply(type, 0);
|
880
|
+
}
|
783
881
|
// For normal TypeVars, the constraint solver can widen a type by combining
|
784
882
|
// two otherwise incompatible types into a union. For TypeVarTuples, we need
|
785
883
|
// to do the equivalent operation for unpacked tuples.
|
@@ -829,23 +927,23 @@ function stripLiteralValueForUnpackedTuple(evaluator, type) {
|
|
829
927
|
return (0, typeUtils_1.specializeTupleClass)(type, tupleTypeArgs, /* isTypeArgExplicit */ true, /* isUnpackedTuple */ true);
|
830
928
|
}
|
831
929
|
// This function is used for debugging only. It dumps the current contents of
|
832
|
-
// the
|
833
|
-
function
|
834
|
-
const
|
835
|
-
if (
|
930
|
+
// the constraints to the console.
|
931
|
+
function logConstraints(evaluator, constraints, indent) {
|
932
|
+
const constraintSetCount = constraints.getConstraintSets().length;
|
933
|
+
if (constraintSetCount === 0) {
|
836
934
|
console.log(`${indent} no signatures`);
|
837
935
|
}
|
838
|
-
else if (
|
839
|
-
|
936
|
+
else if (constraintSetCount === 1) {
|
937
|
+
logTypeVarConstraintSet(evaluator, constraints.getConstraintSets()[0], `${indent} `);
|
840
938
|
}
|
841
939
|
else {
|
842
|
-
|
940
|
+
constraints.doForEachConstraintSet((set, index) => {
|
843
941
|
console.log(`${indent} signature ${index}`);
|
844
|
-
|
942
|
+
logTypeVarConstraintSet(evaluator, set, `${indent} `);
|
845
943
|
});
|
846
944
|
}
|
847
945
|
}
|
848
|
-
function
|
946
|
+
function logTypeVarConstraintSet(evaluator, context, indent) {
|
849
947
|
let loggedConstraint = false;
|
850
948
|
context.getTypeVars().forEach((entry) => {
|
851
949
|
var _a;
|