@zzzen/pyright-internal 1.2.0-dev.20250309 → 1.2.0-dev.20250323
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/analyzerFileInfo.d.ts +1 -0
- package/dist/analyzer/analyzerFileInfo.js.map +1 -1
- package/dist/analyzer/binder.js +21 -13
- package/dist/analyzer/binder.js.map +1 -1
- package/dist/analyzer/checker.d.ts +3 -0
- package/dist/analyzer/checker.js +58 -9
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/codeFlowTypes.d.ts +2 -2
- package/dist/analyzer/codeFlowTypes.js +9 -0
- package/dist/analyzer/codeFlowTypes.js.map +1 -1
- package/dist/analyzer/constructorTransform.js +1 -1
- package/dist/analyzer/constructorTransform.js.map +1 -1
- package/dist/analyzer/constructors.js +7 -1
- package/dist/analyzer/constructors.js.map +1 -1
- package/dist/analyzer/declaration.d.ts +1 -1
- package/dist/analyzer/declaration.js.map +1 -1
- package/dist/analyzer/importResolver.d.ts +2 -0
- package/dist/analyzer/importResolver.js +29 -6
- package/dist/analyzer/importResolver.js.map +1 -1
- package/dist/analyzer/importResult.d.ts +1 -0
- package/dist/analyzer/operations.js +10 -2
- package/dist/analyzer/operations.js.map +1 -1
- package/dist/analyzer/parameterUtils.d.ts +15 -0
- package/dist/analyzer/parameterUtils.js +59 -1
- package/dist/analyzer/parameterUtils.js.map +1 -1
- package/dist/analyzer/parseTreeUtils.d.ts +2 -0
- package/dist/analyzer/parseTreeUtils.js +19 -0
- package/dist/analyzer/parseTreeUtils.js.map +1 -1
- package/dist/analyzer/program.js +17 -4
- package/dist/analyzer/program.js.map +1 -1
- package/dist/analyzer/programTypes.d.ts +2 -2
- package/dist/analyzer/programTypes.js.map +1 -1
- package/dist/analyzer/service.d.ts +3 -3
- package/dist/analyzer/service.js +16 -6
- package/dist/analyzer/service.js.map +1 -1
- package/dist/analyzer/sourceFile.d.ts +2 -1
- package/dist/analyzer/sourceFile.js +3 -1
- package/dist/analyzer/sourceFile.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +236 -245
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +3 -1
- package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
- package/dist/analyzer/typeUtils.js +8 -7
- 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/types.d.ts +6 -5
- package/dist/analyzer/types.js +15 -23
- package/dist/analyzer/types.js.map +1 -1
- package/dist/common/cancellationUtils.d.ts +3 -0
- package/dist/common/cancellationUtils.js +8 -1
- package/dist/common/cancellationUtils.js.map +1 -1
- package/dist/common/languageServerInterface.d.ts +0 -2
- package/dist/common/languageServerInterface.js.map +1 -1
- package/dist/common/serviceKeys.d.ts +2 -0
- package/dist/common/serviceKeys.js +1 -0
- package/dist/common/serviceKeys.js.map +1 -1
- package/dist/common/serviceProviderExtensions.d.ts +2 -0
- package/dist/common/serviceProviderExtensions.js +9 -2
- package/dist/common/serviceProviderExtensions.js.map +1 -1
- package/dist/languageServerBase.d.ts +7 -3
- package/dist/languageServerBase.js +126 -5
- package/dist/languageServerBase.js.map +1 -1
- package/dist/languageService/tooltipUtils.js +2 -2
- package/dist/languageService/tooltipUtils.js.map +1 -1
- package/dist/localization/package.nls.cs.json +1 -1
- package/dist/localization/package.nls.de.json +1 -1
- package/dist/localization/package.nls.es.json +1 -1
- package/dist/localization/package.nls.fr.json +1 -1
- package/dist/localization/package.nls.it.json +1 -1
- package/dist/localization/package.nls.ja.json +1 -1
- package/dist/localization/package.nls.ko.json +1 -1
- package/dist/localization/package.nls.pl.json +1 -1
- package/dist/localization/package.nls.pt-br.json +1 -1
- package/dist/localization/package.nls.ru.json +1 -1
- package/dist/localization/package.nls.tr.json +1 -1
- package/dist/localization/package.nls.zh-cn.json +1 -1
- package/dist/localization/package.nls.zh-tw.json +1 -1
- package/dist/pyright.js +9 -3
- package/dist/pyright.js.map +1 -1
- package/dist/readonlyAugmentedFileSystem.js +4 -0
- package/dist/readonlyAugmentedFileSystem.js.map +1 -1
- package/dist/server.js +1 -2
- package/dist/server.js.map +1 -1
- package/dist/tests/checker.test.js +11 -0
- package/dist/tests/checker.test.js.map +1 -1
- package/dist/tests/fourslash/import.pytyped.privateSymbols.fourslash.js +18 -0
- package/dist/tests/fourslash/import.pytyped.privateSymbols.fourslash.js.map +1 -1
- package/dist/tests/languageServer.test.js +97 -57
- package/dist/tests/languageServer.test.js.map +1 -1
- package/dist/tests/lsp/customLsp.d.ts +8 -1
- package/dist/tests/lsp/customLsp.js +1 -0
- package/dist/tests/lsp/customLsp.js.map +1 -1
- package/dist/tests/lsp/languageServer.js +12 -0
- package/dist/tests/lsp/languageServer.js.map +1 -1
- package/dist/tests/lsp/languageServerTestUtils.d.ts +7 -3
- package/dist/tests/lsp/languageServerTestUtils.js +90 -6
- package/dist/tests/lsp/languageServerTestUtils.js.map +1 -1
- package/dist/tests/sourceFile.test.js +5 -4
- package/dist/tests/sourceFile.test.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +6 -2
- package/dist/tests/typeEvaluator1.test.js.map +1 -1
- package/dist/tests/typeEvaluator4.test.js +1 -1
- package/dist/tests/typeEvaluator5.test.js +1 -1
- package/dist/tests/typeEvaluator6.test.js +1 -1
- package/dist/types.d.ts +6 -2
- package/package.json +1 -1
@@ -142,6 +142,10 @@ const maxCallSiteReturnTypeCacheSize = 8;
|
|
142
142
|
// when inferring the type? We need to cut it off at some point
|
143
143
|
// to avoid excessive computation.
|
144
144
|
const maxEntriesToUseForInference = 64;
|
145
|
+
// How many times should attempt to infer a return type of a
|
146
|
+
// function before giving up and assuming that it won't converge
|
147
|
+
// due to recursion?
|
148
|
+
const maxReturnTypeInferenceAttempts = 8;
|
145
149
|
// How many assignments to an unannotated variable should be used
|
146
150
|
// when inferring its type? We need to cut it off at some point
|
147
151
|
// to avoid excessive computation.
|
@@ -194,7 +198,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
194
198
|
let deferredClassCompletions = [];
|
195
199
|
let cancellationToken;
|
196
200
|
let printExpressionSpaceCount = 0;
|
197
|
-
let
|
201
|
+
let incompleteGenCount = 0;
|
198
202
|
const returnTypeInferenceContextStack = [];
|
199
203
|
let returnTypeInferenceTypeCache;
|
200
204
|
const signatureTrackerStack = [];
|
@@ -255,7 +259,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
255
259
|
if (!cacheEntry) {
|
256
260
|
return false;
|
257
261
|
}
|
258
|
-
return
|
262
|
+
return !cacheEntry.typeResult.isIncomplete || cacheEntry.incompleteGenCount === incompleteGenCount;
|
259
263
|
}
|
260
264
|
function readTypeCache(node, flags) {
|
261
265
|
const cacheEntry = readTypeCacheEntry(node);
|
@@ -290,22 +294,22 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
290
294
|
? returnTypeInferenceTypeCache
|
291
295
|
: typeCache;
|
292
296
|
if (!typeResult.isIncomplete) {
|
293
|
-
|
297
|
+
incompleteGenCount++;
|
294
298
|
}
|
295
299
|
else {
|
296
300
|
const oldValue = typeCacheToUse.get(node.id);
|
297
301
|
if (oldValue !== undefined && !(0, types_1.isTypeSame)(typeResult.type, oldValue.typeResult.type)) {
|
298
|
-
|
302
|
+
incompleteGenCount++;
|
299
303
|
}
|
300
304
|
}
|
301
|
-
typeCacheToUse.set(node.id, { typeResult, flags,
|
305
|
+
typeCacheToUse.set(node.id, { typeResult, flags, incompleteGenCount });
|
302
306
|
// If the entry is located within a part of the parse tree that is currently being
|
303
307
|
// "speculatively" evaluated, track it so we delete the cached entry when we leave
|
304
308
|
// this speculative context.
|
305
309
|
if (isSpeculativeModeInUse(node)) {
|
306
310
|
speculativeTypeTracker.trackEntry(typeCacheToUse, node.id);
|
307
311
|
if (allowSpeculativeCaching) {
|
308
|
-
speculativeTypeTracker.addSpeculativeType(node, typeResult,
|
312
|
+
speculativeTypeTracker.addSpeculativeType(node, typeResult, incompleteGenCount, inferenceContext?.expectedType);
|
309
313
|
}
|
310
314
|
}
|
311
315
|
}
|
@@ -531,23 +535,23 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
531
535
|
function getTypeOfExpression(node, flags = 0 /* EvalFlags.None */, inferenceContext) {
|
532
536
|
// Is this type already cached?
|
533
537
|
const cacheEntry = readTypeCacheEntry(node);
|
534
|
-
if (cacheEntry
|
535
|
-
(!cacheEntry.typeResult.isIncomplete || cacheEntry.
|
536
|
-
|
537
|
-
|
538
|
+
if (cacheEntry) {
|
539
|
+
if (!cacheEntry.typeResult.isIncomplete || cacheEntry.incompleteGenCount === incompleteGenCount) {
|
540
|
+
if (printExpressionTypes) {
|
541
|
+
console.log(`${getPrintExpressionTypesSpaces()}${ParseTreeUtils.printExpression(node)} (${getLineNum(node)}): Cached ${printType(cacheEntry.typeResult.type)} ${cacheEntry.typeResult.typeErrors ? ' Errors' : ''}`);
|
542
|
+
}
|
543
|
+
return cacheEntry.typeResult;
|
538
544
|
}
|
539
|
-
return cacheEntry.typeResult;
|
540
545
|
}
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
if (
|
545
|
-
|
546
|
-
cacheEntry.incompleteGenerationCount === incompleteGenerationCount)) {
|
546
|
+
// Is it cached in the speculative type cache?
|
547
|
+
const specCacheEntry = speculativeTypeTracker.getSpeculativeType(node, inferenceContext?.expectedType);
|
548
|
+
if (specCacheEntry) {
|
549
|
+
if (!specCacheEntry.typeResult.isIncomplete ||
|
550
|
+
specCacheEntry.incompleteGenerationCount === incompleteGenCount) {
|
547
551
|
if (printExpressionTypes) {
|
548
|
-
console.log(`${getPrintExpressionTypesSpaces()}${ParseTreeUtils.printExpression(node)} (${getLineNum(node)}): Speculative ${printType(
|
552
|
+
console.log(`${getPrintExpressionTypesSpaces()}${ParseTreeUtils.printExpression(node)} (${getLineNum(node)}): Speculative ${printType(specCacheEntry.typeResult.type)}`);
|
549
553
|
}
|
550
|
-
return
|
554
|
+
return specCacheEntry.typeResult;
|
551
555
|
}
|
552
556
|
}
|
553
557
|
if (printExpressionTypes) {
|
@@ -2355,7 +2359,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
2355
2359
|
}
|
2356
2360
|
else {
|
2357
2361
|
// Constrain the resulting type to match the declared type.
|
2358
|
-
destType = narrowTypeBasedOnAssignment(
|
2362
|
+
destType = narrowTypeBasedOnAssignment(declaredType, typeResult).type;
|
2359
2363
|
}
|
2360
2364
|
}
|
2361
2365
|
else {
|
@@ -2950,7 +2954,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
2950
2954
|
// is a enum because the annotated type in an enum doesn't reflect
|
2951
2955
|
// the type of the symbol.
|
2952
2956
|
if (!(0, types_1.isClassInstance)(typeResult.type) || !types_1.ClassType.isEnumClass(typeResult.type)) {
|
2953
|
-
typeResult = narrowTypeBasedOnAssignment(
|
2957
|
+
typeResult = narrowTypeBasedOnAssignment(annotationType, typeResult);
|
2954
2958
|
}
|
2955
2959
|
}
|
2956
2960
|
}
|
@@ -3958,8 +3962,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
3958
3962
|
if (isModuleGetAttrSupported) {
|
3959
3963
|
const getAttrTypeResult = getEffectiveTypeOfSymbolForUsage(getAttrSymbol);
|
3960
3964
|
if ((0, types_1.isFunction)(getAttrTypeResult.type)) {
|
3961
|
-
|
3962
|
-
|
3965
|
+
const returnTypeResult = getEffectiveReturnTypeResult(getAttrTypeResult.type);
|
3966
|
+
type = returnTypeResult.type;
|
3967
|
+
if (getAttrTypeResult.isIncomplete || returnTypeResult.isIncomplete) {
|
3963
3968
|
isIncomplete = true;
|
3964
3969
|
}
|
3965
3970
|
}
|
@@ -4310,7 +4315,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
4310
4315
|
// descriptor-based accesses.
|
4311
4316
|
narrowedTypeForSet = isDescriptorApplied
|
4312
4317
|
? usage.setType.type
|
4313
|
-
: narrowTypeBasedOnAssignment(
|
4318
|
+
: narrowTypeBasedOnAssignment(type, usage.setType).type;
|
4314
4319
|
}
|
4315
4320
|
// Verify that the assigned type is compatible.
|
4316
4321
|
if (!assignType(type, usage.setType.type, diag?.createAddendum())) {
|
@@ -6399,7 +6404,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6399
6404
|
// list will grow to include union expansions.
|
6400
6405
|
function validateOverloadsWithExpandedTypes(errorNode, expandedArgTypes, argParamMatches, constraints, skipUnknownArgCheck, inferenceContext) {
|
6401
6406
|
const returnTypes = [];
|
6402
|
-
|
6407
|
+
let matchedOverloads = [];
|
6403
6408
|
let isTypeIncomplete = false;
|
6404
6409
|
let overloadsUsedForCall = [];
|
6405
6410
|
let isDefinitiveMatchFound = false;
|
@@ -6447,10 +6452,12 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6447
6452
|
argResults: callResult.argResults ?? [],
|
6448
6453
|
};
|
6449
6454
|
matchedOverloads.push(matchedOverloadInfo);
|
6450
|
-
if (callResult.anyOrUnknownArg) {
|
6455
|
+
if (callResult.anyOrUnknownArg || matchResults.unpackedArgOfUnknownLength) {
|
6451
6456
|
possibleMatchResults.push(matchedOverloadInfo);
|
6452
|
-
if (
|
6453
|
-
|
6457
|
+
if (callResult.anyOrUnknownArg) {
|
6458
|
+
if ((0, typeUtils_1.isIncompleteUnknown)(callResult.anyOrUnknownArg)) {
|
6459
|
+
possibleMatchInvolvesIncompleteUnknown = true;
|
6460
|
+
}
|
6454
6461
|
}
|
6455
6462
|
}
|
6456
6463
|
else {
|
@@ -6466,11 +6473,13 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6466
6473
|
// Unknown, but include the "possible types" to allow for completion
|
6467
6474
|
// suggestions.
|
6468
6475
|
if (!isDefinitiveMatchFound && possibleMatchResults.length > 0) {
|
6476
|
+
possibleMatchResults = filterOverloadMatchesForUnpackedArgs(possibleMatchResults);
|
6469
6477
|
possibleMatchResults = filterOverloadMatchesForAnyArgs(possibleMatchResults);
|
6470
6478
|
// Did the filtering produce a single result? If so, we're done.
|
6471
6479
|
if (possibleMatchResults.length === 1) {
|
6472
6480
|
overloadsUsedForCall = [possibleMatchResults[0].overload];
|
6473
6481
|
returnTypes.push(possibleMatchResults[0].returnType);
|
6482
|
+
matchedOverloads = [possibleMatchResults[0]];
|
6474
6483
|
}
|
6475
6484
|
else {
|
6476
6485
|
// Eliminate any return types that are subsumed by other return types.
|
@@ -6551,21 +6560,26 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6551
6560
|
overloadsUsedForCall,
|
6552
6561
|
};
|
6553
6562
|
}
|
6554
|
-
//
|
6563
|
+
// Determines whether one or more overloads can be eliminated because they
|
6564
|
+
// rely on an unpacked argument of unknown length when there is at least
|
6565
|
+
// one overload that doesn't because it maps to an *args parameter.
|
6566
|
+
function filterOverloadMatchesForUnpackedArgs(matches) {
|
6567
|
+
if (matches.length < 2) {
|
6568
|
+
return matches;
|
6569
|
+
}
|
6570
|
+
// Is there at least one overload that relies on unpacked args for a match?
|
6571
|
+
const unpackedArgsOverloads = matches.filter((match) => match.matchResults.unpackedArgMapsToVariadic);
|
6572
|
+
if (unpackedArgsOverloads.length === matches.length || unpackedArgsOverloads.length === 0) {
|
6573
|
+
return matches;
|
6574
|
+
}
|
6575
|
+
return unpackedArgsOverloads;
|
6576
|
+
}
|
6577
|
+
// Determines whether multiple incompatible overloads match
|
6555
6578
|
// due to an Any or Unknown argument type.
|
6556
6579
|
function filterOverloadMatchesForAnyArgs(matches) {
|
6557
6580
|
if (matches.length < 2) {
|
6558
6581
|
return matches;
|
6559
6582
|
}
|
6560
|
-
// If the relevance of some matches differs, filter out the ones that
|
6561
|
-
// are lower relevance. This favors *args parameters in cases where
|
6562
|
-
// a *args argument is used.
|
6563
|
-
if (matches[0].matchResults.relevance !== matches[matches.length - 1].matchResults.relevance) {
|
6564
|
-
matches = matches.filter((m) => m.matchResults.relevance === matches[0].matchResults.relevance);
|
6565
|
-
if (matches.length < 2) {
|
6566
|
-
return matches;
|
6567
|
-
}
|
6568
|
-
}
|
6569
6583
|
// If all of the return types match, select the first one.
|
6570
6584
|
if ((0, typeUtils_1.areTypesSame)(matches.map((match) => match.returnType), { treatAnySameAsUnknown: true })) {
|
6571
6585
|
return [matches[0]];
|
@@ -6599,7 +6613,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6599
6613
|
}
|
6600
6614
|
function getBestOverloadForArgs(errorNode, typeResult, argList) {
|
6601
6615
|
let overloadIndex = 0;
|
6602
|
-
|
6616
|
+
const matches = [];
|
6603
6617
|
const speculativeNode = getSpeculativeNodeForCall(errorNode);
|
6604
6618
|
useSignatureTracker(errorNode, () => {
|
6605
6619
|
// Create a list of potential overload matches based on arguments.
|
@@ -6613,7 +6627,6 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6613
6627
|
});
|
6614
6628
|
});
|
6615
6629
|
});
|
6616
|
-
matches = sortOverloadsByBestMatch(matches);
|
6617
6630
|
let winningOverloadIndex;
|
6618
6631
|
matches.forEach((match, matchIndex) => {
|
6619
6632
|
if (winningOverloadIndex === undefined) {
|
@@ -6628,17 +6641,8 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6628
6641
|
});
|
6629
6642
|
return winningOverloadIndex === undefined ? undefined : matches[winningOverloadIndex].overload;
|
6630
6643
|
}
|
6631
|
-
// Sorts the list of overloads based first on "relevance" and second on order.
|
6632
|
-
function sortOverloadsByBestMatch(matches) {
|
6633
|
-
return matches.sort((a, b) => {
|
6634
|
-
if (a.relevance !== b.relevance) {
|
6635
|
-
return b.relevance - a.relevance;
|
6636
|
-
}
|
6637
|
-
return a.overloadIndex - b.overloadIndex;
|
6638
|
-
});
|
6639
|
-
}
|
6640
6644
|
function validateOverloadedArgTypes(errorNode, argList, typeResult, constraints, skipUnknownArgCheck, inferenceContext) {
|
6641
|
-
|
6645
|
+
const filteredMatchResults = [];
|
6642
6646
|
let contextFreeArgTypes;
|
6643
6647
|
let isTypeIncomplete = !!typeResult.isIncomplete;
|
6644
6648
|
const type = typeResult.type;
|
@@ -6661,7 +6665,6 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6661
6665
|
overloadIndex++;
|
6662
6666
|
});
|
6663
6667
|
});
|
6664
|
-
filteredMatchResults = sortOverloadsByBestMatch(filteredMatchResults);
|
6665
6668
|
// If there are no possible arg/param matches among the overloads,
|
6666
6669
|
// emit an error that includes the argument types.
|
6667
6670
|
if (filteredMatchResults.length === 0) {
|
@@ -6904,11 +6907,12 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6904
6907
|
case 3 /* TypeCategory.Never */:
|
6905
6908
|
case 1 /* TypeCategory.Unknown */:
|
6906
6909
|
case 2 /* TypeCategory.Any */: {
|
6907
|
-
//
|
6908
|
-
//
|
6909
|
-
|
6910
|
-
|
6911
|
-
|
6910
|
+
// Create a dummy callable that accepts all arguments and validate
|
6911
|
+
// that the argument expressions are valid.
|
6912
|
+
const dummyFunctionType = types_1.FunctionType.createInstance('', '', '', 0 /* FunctionTypeFlags.None */);
|
6913
|
+
types_1.FunctionType.addDefaultParams(dummyFunctionType);
|
6914
|
+
const dummyCallResult = validateCallForFunction(errorNode, argList, dummyFunctionType, isCallTypeIncomplete, constraints, skipUnknownArgCheck, inferenceContext);
|
6915
|
+
return { ...dummyCallResult, returnType: expandedCallType };
|
6912
6916
|
}
|
6913
6917
|
case 4 /* TypeCategory.Function */: {
|
6914
6918
|
return validateCallForFunction(errorNode, argList, expandedCallType, isCallTypeIncomplete, constraints, skipUnknownArgCheck, inferenceContext);
|
@@ -6919,6 +6923,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6919
6923
|
case 6 /* TypeCategory.Class */: {
|
6920
6924
|
if ((0, typeUtils_1.isNoneInstance)(expandedCallType)) {
|
6921
6925
|
addDiagnostic(diagnosticRules_1.DiagnosticRule.reportOptionalCall, localize_1.LocMessage.noneNotCallable(), errorNode);
|
6926
|
+
touchArgTypes();
|
6922
6927
|
return { argumentErrors: true };
|
6923
6928
|
}
|
6924
6929
|
if (types_1.TypeBase.isInstantiable(expandedCallType)) {
|
@@ -6935,6 +6940,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6935
6940
|
}
|
6936
6941
|
case 7 /* TypeCategory.Module */: {
|
6937
6942
|
addDiagnostic(diagnosticRules_1.DiagnosticRule.reportCallIssue, localize_1.LocMessage.moduleNotCallable(), errorNode);
|
6943
|
+
touchArgTypes();
|
6938
6944
|
return { argumentErrors: true };
|
6939
6945
|
}
|
6940
6946
|
}
|
@@ -7397,25 +7403,15 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7397
7403
|
const paramDetails = (0, parameterUtils_1.getParamListDetails)(overload, { disallowExtraKwargsForTd: true });
|
7398
7404
|
const paramSpec = types_1.FunctionType.getParamSpecFromArgsKwargs(overload);
|
7399
7405
|
let argIndex = 0;
|
7400
|
-
let
|
7406
|
+
let unpackedArgOfUnknownLength = false;
|
7407
|
+
let unpackedArgMapsToVariadic = false;
|
7401
7408
|
let reportedArgError = false;
|
7402
7409
|
let isTypeIncomplete = !!typeResult.isIncomplete;
|
7403
7410
|
let isTypeVarTupleFullyMatched = false;
|
7404
7411
|
// Expand any unpacked tuples in the arg list.
|
7405
7412
|
argList = expandArgList(argList);
|
7406
|
-
//
|
7407
|
-
const
|
7408
|
-
paramDetails.params.forEach((paramInfo) => {
|
7409
|
-
(0, debug_1.assert)(paramInfo !== undefined, 'paramInfo is undefined for param name map');
|
7410
|
-
const param = paramInfo.param;
|
7411
|
-
if (param.name && param.category === 0 /* ParamCategory.Simple */ && paramInfo.kind !== parameterUtils_1.ParamKind.Positional) {
|
7412
|
-
let argsNeeded = paramMap.get(param.name)?.argsNeeded ?? 0;
|
7413
|
-
if (param.category === 0 /* ParamCategory.Simple */ && !paramInfo.defaultType) {
|
7414
|
-
argsNeeded += 1;
|
7415
|
-
}
|
7416
|
-
paramMap.set(param.name, { argsNeeded, argsReceived: 0 });
|
7417
|
-
}
|
7418
|
-
});
|
7413
|
+
// Construct an object that racks which parameters have been assigned arguments.
|
7414
|
+
const paramTracker = new parameterUtils_1.ParamAssignmentTracker(paramDetails.params);
|
7419
7415
|
let positionalOnlyLimitIndex = paramDetails.positionOnlyParamCount;
|
7420
7416
|
let positionParamLimitIndex = paramDetails.firstKeywordOnlyIndex ?? paramDetails.params.length;
|
7421
7417
|
const varArgListParamIndex = paramDetails.argsIndex;
|
@@ -7534,6 +7530,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7534
7530
|
argType.priv.tupleTypeArgs.length > 0) {
|
7535
7531
|
tooManyPositionals = true;
|
7536
7532
|
}
|
7533
|
+
else {
|
7534
|
+
unpackedArgOfUnknownLength = true;
|
7535
|
+
}
|
7537
7536
|
}
|
7538
7537
|
else {
|
7539
7538
|
tooManyPositionals = true;
|
@@ -7563,6 +7562,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7563
7562
|
let isArgCompatibleWithVariadic = false;
|
7564
7563
|
const argTypeResult = getTypeOfArg(argList[argIndex], /* inferenceContext */ undefined);
|
7565
7564
|
let listElementType;
|
7565
|
+
let enforceIterable = false;
|
7566
7566
|
let advanceToNextArg = false;
|
7567
7567
|
// Handle the case where *args is being passed to a function defined
|
7568
7568
|
// with a ParamSpec and a Concatenate operator. PEP 612 indicates that
|
@@ -7622,8 +7622,12 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7622
7622
|
listElementType = getTypeOfIterator({ type: argType, isIncomplete: argTypeResult.isIncomplete },
|
7623
7623
|
/* isAsync */ false, errorNode,
|
7624
7624
|
/* emitNotIterableError */ false)?.type;
|
7625
|
+
if (!listElementType) {
|
7626
|
+
enforceIterable = true;
|
7627
|
+
}
|
7628
|
+
unpackedArgOfUnknownLength = true;
|
7625
7629
|
if (paramInfo.param.category === 1 /* ParamCategory.ArgsList */) {
|
7626
|
-
|
7630
|
+
unpackedArgMapsToVariadic = true;
|
7627
7631
|
}
|
7628
7632
|
if (isParamVariadic && listElementType) {
|
7629
7633
|
isArgCompatibleWithVariadic = true;
|
@@ -7636,7 +7640,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7636
7640
|
argCategory: 0 /* ArgCategory.Simple */,
|
7637
7641
|
typeResult: { type: listElementType, isIncomplete: argTypeResult.isIncomplete },
|
7638
7642
|
}
|
7639
|
-
: { ...argList[argIndex] };
|
7643
|
+
: { ...argList[argIndex], enforceIterable };
|
7640
7644
|
if (argTypeResult.isIncomplete) {
|
7641
7645
|
isTypeIncomplete = true;
|
7642
7646
|
}
|
@@ -7667,10 +7671,8 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7667
7671
|
}
|
7668
7672
|
trySetActive(argList[argIndex], paramDetails.params[paramIndex].param);
|
7669
7673
|
// Note that the parameter has received an argument.
|
7670
|
-
if (paramName &&
|
7671
|
-
|
7672
|
-
paramMap.has(paramName)) {
|
7673
|
-
paramMap.get(paramName).argsReceived++;
|
7674
|
+
if (paramName && paramDetails.params[paramIndex].param.category === 0 /* ParamCategory.Simple */) {
|
7675
|
+
paramTracker.markArgReceived(paramInfo);
|
7674
7676
|
}
|
7675
7677
|
if (advanceToNextArg || paramDetails.params[paramIndex].param.category === 1 /* ParamCategory.ArgsList */) {
|
7676
7678
|
argIndex++;
|
@@ -7739,9 +7741,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7739
7741
|
});
|
7740
7742
|
trySetActive(argList[argIndex], paramInfo.param);
|
7741
7743
|
// Note that the parameter has received an argument.
|
7742
|
-
|
7743
|
-
paramMap.get(paramName).argsReceived++;
|
7744
|
-
}
|
7744
|
+
paramTracker.markArgReceived(paramInfo);
|
7745
7745
|
argIndex++;
|
7746
7746
|
paramIndex++;
|
7747
7747
|
}
|
@@ -7815,7 +7815,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7815
7815
|
const tdEntries = (0, typedDicts_1.getTypedDictMembersForClass)(evaluatorInterface, argType);
|
7816
7816
|
const diag = new diagnostic_1.DiagnosticAddendum();
|
7817
7817
|
tdEntries.knownItems.forEach((entry, name) => {
|
7818
|
-
const paramEntry =
|
7818
|
+
const paramEntry = paramTracker.lookupName(name);
|
7819
7819
|
if (paramEntry) {
|
7820
7820
|
if (paramEntry.argsReceived > 0) {
|
7821
7821
|
diag.addMessage(localize_1.LocMessage.paramAlreadyAssigned().format({ name }));
|
@@ -7852,10 +7852,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7852
7852
|
paramName: name,
|
7853
7853
|
});
|
7854
7854
|
// Remember that this parameter has already received a value.
|
7855
|
-
|
7856
|
-
argsNeeded: 1,
|
7857
|
-
argsReceived: 1,
|
7858
|
-
});
|
7855
|
+
paramTracker.addKeywordParam(name, paramDetails.params[paramDetails.kwargsIndex]);
|
7859
7856
|
}
|
7860
7857
|
else {
|
7861
7858
|
// If the function doesn't have a **kwargs parameter, we need to emit an error.
|
@@ -7941,6 +7938,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7941
7938
|
unpackedDictArgType = types_1.UnknownType.create();
|
7942
7939
|
}
|
7943
7940
|
}
|
7941
|
+
unpackedArgOfUnknownLength = true;
|
7944
7942
|
if (paramDetails.kwargsIndex !== undefined && unpackedDictArgType) {
|
7945
7943
|
const paramType = paramDetails.params[paramDetails.kwargsIndex].type;
|
7946
7944
|
validateArgTypeParams.push({
|
@@ -7952,6 +7950,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7952
7950
|
errorNode: argList[argIndex].valueExpression || errorNode,
|
7953
7951
|
paramName: paramDetails.params[paramDetails.kwargsIndex].param.name,
|
7954
7952
|
});
|
7953
|
+
unpackedArgMapsToVariadic = true;
|
7955
7954
|
}
|
7956
7955
|
if (!isValidMappingType) {
|
7957
7956
|
if (!canSkipDiagnosticForNode(errorNode) && !isTypeIncomplete) {
|
@@ -7972,7 +7971,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7972
7971
|
const paramName = argList[argIndex].name;
|
7973
7972
|
if (paramName) {
|
7974
7973
|
const paramNameValue = paramName.d.value;
|
7975
|
-
const paramEntry =
|
7974
|
+
const paramEntry = paramTracker.lookupName(paramNameValue);
|
7976
7975
|
if (paramEntry) {
|
7977
7976
|
if (paramEntry.argsReceived > 0) {
|
7978
7977
|
if (!canSkipDiagnosticForNode(errorNode) && !isTypeIncomplete) {
|
@@ -8017,12 +8016,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8017
8016
|
errorNode: argList[argIndex].valueExpression ?? errorNode,
|
8018
8017
|
paramName: paramNameValue,
|
8019
8018
|
});
|
8020
|
-
// Remember that this parameter has already received a value.
|
8021
|
-
paramMap.set(paramNameValue, {
|
8022
|
-
argsNeeded: 1,
|
8023
|
-
argsReceived: 1,
|
8024
|
-
});
|
8025
8019
|
(0, debug_1.assert)(paramDetails.params[paramDetails.kwargsIndex], 'paramDetails.kwargsIndex params entry is undefined');
|
8020
|
+
// Remember that this parameter has already received a value.
|
8021
|
+
paramTracker.addKeywordParam(paramNameValue, paramDetails.params[paramDetails.kwargsIndex]);
|
8026
8022
|
}
|
8027
8023
|
trySetActive(argList[argIndex], paramDetails.params[paramDetails.kwargsIndex].param);
|
8028
8024
|
}
|
@@ -8083,8 +8079,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8083
8079
|
if (paramIndex >= paramDetails.firstPositionOrKeywordIndex &&
|
8084
8080
|
param.category === 0 /* ParamCategory.Simple */ &&
|
8085
8081
|
param.name &&
|
8086
|
-
|
8087
|
-
paramMap.get(param.name).argsReceived === 0) {
|
8082
|
+
paramTracker.lookupDetails(paramInfo).argsReceived === 0) {
|
8088
8083
|
const paramType = paramDetails.params[paramIndex].type;
|
8089
8084
|
if (!unpackedDictKeyNames || unpackedDictKeyNames.includes(param.name)) {
|
8090
8085
|
validateArgTypeParams.push({
|
@@ -8100,7 +8095,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8100
8095
|
paramName: param.name,
|
8101
8096
|
isParamNameSynthesized: types_1.FunctionParam.isNameSynthesized(param),
|
8102
8097
|
});
|
8103
|
-
|
8098
|
+
paramTracker.markArgReceived(paramDetails.params[paramIndex]);
|
8104
8099
|
}
|
8105
8100
|
}
|
8106
8101
|
});
|
@@ -8110,10 +8105,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8110
8105
|
// (i.e. an arg starting with a "**"), we will assume that all parameters
|
8111
8106
|
// are matched.
|
8112
8107
|
if (!unpackedDictArgType && !types_1.FunctionType.isDefaultParamCheckDisabled(overload)) {
|
8113
|
-
const unassignedParams =
|
8114
|
-
const entry = paramMap.get(name);
|
8115
|
-
return !entry || entry.argsReceived < entry.argsNeeded;
|
8116
|
-
});
|
8108
|
+
const unassignedParams = paramTracker.getUnassignedParams();
|
8117
8109
|
if (unassignedParams.length > 0) {
|
8118
8110
|
if (!canSkipDiagnosticForNode(errorNode)) {
|
8119
8111
|
const missingParamNames = unassignedParams.map((p) => `"${p}"`).join(', ');
|
@@ -8133,8 +8125,8 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8133
8125
|
paramDetails.params.forEach((paramInfo) => {
|
8134
8126
|
const param = paramInfo.param;
|
8135
8127
|
if (param.category === 0 /* ParamCategory.Simple */ && param.name) {
|
8136
|
-
const entry =
|
8137
|
-
if (entry
|
8128
|
+
const entry = paramTracker.lookupDetails(paramInfo);
|
8129
|
+
if (entry.argsNeeded === 0 && entry.argsReceived === 0) {
|
8138
8130
|
const defaultArgType = paramInfo.defaultType;
|
8139
8131
|
if (defaultArgType &&
|
8140
8132
|
!(0, typeUtils_1.isEllipsisType)(defaultArgType) &&
|
@@ -8225,13 +8217,6 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8225
8217
|
}
|
8226
8218
|
}
|
8227
8219
|
}
|
8228
|
-
let relevance = 0;
|
8229
|
-
if (matchedUnpackedListOfUnknownLength) {
|
8230
|
-
// Increase the relevance if we made assumptions about the length
|
8231
|
-
// of an unpacked argument. This will favor overloads that
|
8232
|
-
// associate this case with a *args parameter.
|
8233
|
-
relevance++;
|
8234
|
-
}
|
8235
8220
|
// Special-case the builtin isinstance and issubclass functions.
|
8236
8221
|
if (types_1.FunctionType.isBuiltIn(overload, ['isinstance', 'issubclass']) && validateArgTypeParams.length === 2) {
|
8237
8222
|
validateArgTypeParams[1].isinstanceParam = true;
|
@@ -8245,7 +8230,8 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8245
8230
|
paramSpecTarget,
|
8246
8231
|
paramSpecArgList,
|
8247
8232
|
activeParam,
|
8248
|
-
|
8233
|
+
unpackedArgOfUnknownLength,
|
8234
|
+
unpackedArgMapsToVariadic,
|
8249
8235
|
argumentMatchScore: 0,
|
8250
8236
|
};
|
8251
8237
|
}
|
@@ -8500,9 +8486,13 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8500
8486
|
}
|
8501
8487
|
}
|
8502
8488
|
// Calculate the return type.
|
8503
|
-
|
8489
|
+
const returnTypeResult = getEffectiveReturnTypeResult(type, {
|
8504
8490
|
callSiteInfo: { args: matchResults.argParams, errorNode },
|
8505
8491
|
});
|
8492
|
+
let returnType = returnTypeResult.type;
|
8493
|
+
if (returnTypeResult.isIncomplete) {
|
8494
|
+
isTypeIncomplete = true;
|
8495
|
+
}
|
8506
8496
|
if (condition.length > 0) {
|
8507
8497
|
returnType = types_1.TypeBase.cloneForCondition(returnType, condition);
|
8508
8498
|
}
|
@@ -8776,13 +8766,18 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8776
8766
|
: 16 /* EvalFlags.NoFinal */ | 2 /* EvalFlags.NoSpecialize */;
|
8777
8767
|
const exprTypeResult = getTypeOfExpression(argParam.argument.valueExpression, flags, (0, typeUtils_1.makeInferenceContext)(expectedType, !!typeResult?.isIncomplete));
|
8778
8768
|
argType = exprTypeResult.type;
|
8769
|
+
// If the argument is unpacked and we are supposed to enforce
|
8770
|
+
// that it's an iterator, do so now.
|
8771
|
+
if (argParam.argument.argCategory === 1 /* ArgCategory.UnpackedList */ && argParam.argument.enforceIterable) {
|
8772
|
+
const iteratorType = getTypeOfIterator(exprTypeResult,
|
8773
|
+
/* isAsync */ false, argParam.argument.valueExpression);
|
8774
|
+
// Try to prevent cascading errors if it was not iterable.
|
8775
|
+
argType = iteratorType?.type ?? types_1.UnknownType.create();
|
8776
|
+
}
|
8779
8777
|
if (exprTypeResult.isIncomplete) {
|
8780
8778
|
isTypeIncomplete = true;
|
8781
8779
|
}
|
8782
|
-
if (
|
8783
|
-
isCompatible = false;
|
8784
|
-
}
|
8785
|
-
else if (expectedType && (0, typeUtils_1.requiresSpecialization)(expectedType)) {
|
8780
|
+
if (expectedType && (0, typeUtils_1.requiresSpecialization)(expectedType)) {
|
8786
8781
|
// Assign the argument type back to the expected type to assign
|
8787
8782
|
// values to any unification variables.
|
8788
8783
|
const clonedConstraints = constraints.clone();
|
@@ -10413,7 +10408,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
10413
10408
|
: undefined, () => {
|
10414
10409
|
const returnTypeResult = getTypeOfExpression(node.d.expr,
|
10415
10410
|
/* flags */ undefined, (0, typeUtils_1.makeInferenceContext)(expectedReturnType));
|
10416
|
-
functionType.
|
10411
|
+
functionType.shared.inferredReturnType = {
|
10417
10412
|
type: returnTypeResult.type,
|
10418
10413
|
};
|
10419
10414
|
if (returnTypeResult.isIncomplete) {
|
@@ -13559,7 +13554,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
13559
13554
|
awaitableFunctionType.shared.declaredReturnType = createAwaitableReturnType(node, functionType.shared.declaredReturnType, types_1.FunctionType.isGenerator(functionType));
|
13560
13555
|
}
|
13561
13556
|
else {
|
13562
|
-
awaitableFunctionType.
|
13557
|
+
awaitableFunctionType.shared.inferredReturnType = {
|
13563
13558
|
type: createAwaitableReturnType(node, getInferredReturnType(functionType), types_1.FunctionType.isGenerator(functionType)),
|
13564
13559
|
};
|
13565
13560
|
}
|
@@ -15737,11 +15732,11 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
15737
15732
|
if (declaration.intrinsicType === 'int') {
|
15738
15733
|
return { type: intType };
|
15739
15734
|
}
|
15740
|
-
if (declaration.intrinsicType === '
|
15741
|
-
const
|
15742
|
-
if ((0, types_1.isInstantiableClass)(
|
15735
|
+
if (declaration.intrinsicType === 'MutableSequence[str]') {
|
15736
|
+
const sequenceType = getBuiltInType(declaration.node, 'MutableSequence');
|
15737
|
+
if ((0, types_1.isInstantiableClass)(sequenceType)) {
|
15743
15738
|
return {
|
15744
|
-
type: types_1.ClassType.cloneAsInstance(types_1.ClassType.specialize(
|
15739
|
+
type: types_1.ClassType.cloneAsInstance(types_1.ClassType.specialize(sequenceType, [strType])),
|
15745
15740
|
};
|
15746
15741
|
}
|
15747
15742
|
}
|
@@ -16014,18 +16009,30 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
16014
16009
|
}
|
16015
16010
|
if (loaderActions.implicitImports) {
|
16016
16011
|
loaderActions.implicitImports.forEach((implicitImport, name) => {
|
16012
|
+
const existingLoaderField = moduleType.priv.loaderFields.get(name);
|
16017
16013
|
// Recursively apply loader actions.
|
16018
16014
|
let symbolType;
|
16019
16015
|
if (implicitImport.isUnresolved) {
|
16020
16016
|
symbolType = types_1.UnknownType.create();
|
16021
16017
|
}
|
16022
16018
|
else {
|
16023
|
-
|
16024
|
-
const
|
16019
|
+
let importedModuleType;
|
16020
|
+
const existingType = existingLoaderField?.getSynthesizedType();
|
16021
|
+
if (existingType?.type && (0, types_1.isModule)(existingType.type)) {
|
16022
|
+
importedModuleType = existingType.type;
|
16023
|
+
}
|
16024
|
+
else {
|
16025
|
+
const moduleName = moduleType.priv.moduleName
|
16026
|
+
? moduleType.priv.moduleName + '.' + name
|
16027
|
+
: '';
|
16028
|
+
importedModuleType = types_1.ModuleType.create(moduleName, implicitImport.uri);
|
16029
|
+
}
|
16025
16030
|
symbolType = applyLoaderActionsToModuleType(importedModuleType, implicitImport, importLookup);
|
16026
16031
|
}
|
16027
|
-
|
16028
|
-
|
16032
|
+
if (!existingLoaderField) {
|
16033
|
+
const importedModuleSymbol = symbol_1.Symbol.createWithType(0 /* SymbolFlags.None */, symbolType);
|
16034
|
+
moduleType.priv.loaderFields.set(name, importedModuleSymbol);
|
16035
|
+
}
|
16029
16036
|
});
|
16030
16037
|
}
|
16031
16038
|
return moduleType;
|
@@ -16034,15 +16041,28 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
16034
16041
|
// is pointing at a module, and we need to synthesize a
|
16035
16042
|
// module type.
|
16036
16043
|
if (resolvedDecl.type === 8 /* DeclarationType.Alias */) {
|
16037
|
-
|
16038
|
-
//
|
16039
|
-
|
16040
|
-
|
16041
|
-
|
16044
|
+
let moduleType;
|
16045
|
+
// See if this is an import that shares a ModuleType with another
|
16046
|
+
// import statement. If so, used the cached type. This happens when
|
16047
|
+
// multiple import statements start with the same module name, such
|
16048
|
+
// as "import a.b" and "import a.c".
|
16049
|
+
if (resolvedDecl.node.nodeType === 24 /* ParseNodeType.ImportAs */) {
|
16050
|
+
const cachedType = readTypeCache(resolvedDecl.node.d.module, 0 /* EvalFlags.None */);
|
16051
|
+
if (cachedType && (0, types_1.isModule)(cachedType)) {
|
16052
|
+
moduleType = cachedType;
|
16053
|
+
}
|
16042
16054
|
}
|
16043
|
-
|
16044
|
-
|
16055
|
+
if (!moduleType) {
|
16056
|
+
// Build a module type that corresponds to the declaration and
|
16057
|
+
// its associated loader actions.
|
16058
|
+
moduleType = types_1.ModuleType.create(resolvedDecl.moduleName, resolvedDecl.uri);
|
16059
|
+
if (resolvedDecl.node.nodeType === 24 /* ParseNodeType.ImportAs */) {
|
16060
|
+
writeTypeCache(resolvedDecl.node.d.module, { type: moduleType }, 0 /* EvalFlags.None */);
|
16061
|
+
}
|
16045
16062
|
}
|
16063
|
+
return applyLoaderActionsToModuleType(moduleType, resolvedDecl.symbolName && resolvedDecl.submoduleFallback
|
16064
|
+
? resolvedDecl.submoduleFallback
|
16065
|
+
: resolvedDecl, importLookup);
|
16046
16066
|
}
|
16047
16067
|
const declaredType = getTypeForDeclaration(resolvedDecl);
|
16048
16068
|
if (declaredType.type) {
|
@@ -16598,38 +16618,49 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
16598
16618
|
}
|
16599
16619
|
}
|
16600
16620
|
}
|
16621
|
+
function getEffectiveReturnType(type) {
|
16622
|
+
return getEffectiveReturnTypeResult(type).type;
|
16623
|
+
}
|
16624
|
+
function getInferredReturnType(type) {
|
16625
|
+
return getInferredReturnTypeResult(type).type;
|
16626
|
+
}
|
16601
16627
|
// Returns the return type of the function. If the type is explicitly provided in
|
16602
16628
|
// a type annotation, that type is returned. If not, an attempt is made to infer
|
16603
16629
|
// the return type. If a list of args is provided, the inference logic may take
|
16604
16630
|
// into account argument types to infer the return type.
|
16605
|
-
function
|
16631
|
+
function getEffectiveReturnTypeResult(type, options) {
|
16606
16632
|
const specializedReturnType = types_1.FunctionType.getEffectiveReturnType(type, /* includeInferred */ false);
|
16607
16633
|
if (specializedReturnType && !(0, types_1.isUnknown)(specializedReturnType)) {
|
16608
|
-
return specializedReturnType;
|
16634
|
+
return { type: specializedReturnType };
|
16609
16635
|
}
|
16610
|
-
return
|
16636
|
+
return getInferredReturnTypeResult(type, options?.callSiteInfo);
|
16611
16637
|
}
|
16612
|
-
function
|
16638
|
+
function _getInferredReturnTypeResult(type, callSiteInfo) {
|
16613
16639
|
let returnType;
|
16614
16640
|
let isIncomplete = false;
|
16615
16641
|
const analyzeUnannotatedFunctions = true;
|
16616
16642
|
// Don't attempt to infer the return type for a stub file.
|
16617
16643
|
if (types_1.FunctionType.isStubDefinition(type)) {
|
16618
|
-
return types_1.UnknownType.create();
|
16644
|
+
return { type: types_1.UnknownType.create() };
|
16619
16645
|
}
|
16620
16646
|
// Don't infer the return type for a ParamSpec value.
|
16621
16647
|
if (types_1.FunctionType.isParamSpecValue(type)) {
|
16622
|
-
return types_1.UnknownType.create();
|
16648
|
+
return { type: types_1.UnknownType.create() };
|
16623
16649
|
}
|
16624
16650
|
// Don't infer the return type for an overloaded function (unless it's synthesized,
|
16625
16651
|
// which is needed for proper operation of the __get__ method in properties).
|
16626
16652
|
if (types_1.FunctionType.isOverloaded(type) && !types_1.FunctionType.isSynthesizedMethod(type)) {
|
16627
|
-
return types_1.UnknownType.create();
|
16653
|
+
return { type: types_1.UnknownType.create() };
|
16628
16654
|
}
|
16655
|
+
const evalCount = type.shared.inferredReturnType?.evaluationCount ?? 0;
|
16629
16656
|
// If the return type has already been lazily evaluated,
|
16630
16657
|
// don't bother computing it again.
|
16631
|
-
if (type.
|
16632
|
-
returnType = type.
|
16658
|
+
if (type.shared.inferredReturnType && !type.shared.inferredReturnType.isIncomplete) {
|
16659
|
+
returnType = type.shared.inferredReturnType.type;
|
16660
|
+
}
|
16661
|
+
else if (evalCount > maxReturnTypeInferenceAttempts) {
|
16662
|
+
// Detect a case where a return type won't converge because of recursion.
|
16663
|
+
returnType = types_1.UnknownType.create();
|
16633
16664
|
}
|
16634
16665
|
else {
|
16635
16666
|
// Don't bother inferring the return type of __init__ because it's
|
@@ -16676,7 +16707,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
16676
16707
|
}
|
16677
16708
|
returnType = (0, typeUtils_1.makeTypeVarsFree)(returnType, typeVarScopes);
|
16678
16709
|
// Cache the type for next time.
|
16679
|
-
type.
|
16710
|
+
type.shared.inferredReturnType = { type: returnType, isIncomplete, evaluationCount: evalCount + 1 };
|
16680
16711
|
}
|
16681
16712
|
// If the type is partially unknown and the function has one or more unannotated
|
16682
16713
|
// params, try to analyze the function with the provided argument types and
|
@@ -16713,7 +16744,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
16713
16744
|
}
|
16714
16745
|
}
|
16715
16746
|
}
|
16716
|
-
return returnType;
|
16747
|
+
return { type: returnType, isIncomplete };
|
16717
16748
|
}
|
16718
16749
|
function inferReturnTypeForCallSite(type, callSiteInfo) {
|
16719
16750
|
const args = callSiteInfo.args;
|
@@ -18243,8 +18274,10 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
18243
18274
|
}
|
18244
18275
|
// Determines whether the two types are potentially comparable -- i.e.
|
18245
18276
|
// their types overlap in such a way that it makes sense for them to
|
18246
|
-
// be compared with an == or != operator.
|
18247
|
-
|
18277
|
+
// be compared with an == or != operator. The functional also supports
|
18278
|
+
// a special variant that can be used for the "is" and "is not" operator.
|
18279
|
+
// This variant can be less conservative in some cases.
|
18280
|
+
function isTypeComparable(leftType, rightType, assumeIsOperator = false) {
|
18248
18281
|
if ((0, types_1.isAnyOrUnknown)(leftType) || (0, types_1.isAnyOrUnknown)(rightType)) {
|
18249
18282
|
return true;
|
18250
18283
|
}
|
@@ -18284,6 +18317,16 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
18284
18317
|
if (assignType(genericLeftType, genericRightType) || assignType(genericRightType, genericLeftType)) {
|
18285
18318
|
return true;
|
18286
18319
|
}
|
18320
|
+
// Check for the "is None" or "is not None" case.
|
18321
|
+
if (assumeIsOperator && (0, typeUtils_1.isNoneInstance)(rightType)) {
|
18322
|
+
if ((0, typeUtils_1.isNoneInstance)(leftType)) {
|
18323
|
+
return true;
|
18324
|
+
}
|
18325
|
+
// The LHS could be a protocol or 'object', in which case None is
|
18326
|
+
// potentially comparable to it. In other cases, None is not comparable
|
18327
|
+
// because the types are disjoint.
|
18328
|
+
return assignType(leftType, rightType);
|
18329
|
+
}
|
18287
18330
|
// Assume that if the types are disjoint and built-in classes that they
|
18288
18331
|
// will never be comparable.
|
18289
18332
|
if (types_1.ClassType.isBuiltIn(leftType) && types_1.ClassType.isBuiltIn(rightType) && types_1.TypeBase.isInstance(rightType)) {
|
@@ -19197,72 +19240,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
19197
19240
|
}
|
19198
19241
|
return canAssign;
|
19199
19242
|
}
|
19200
|
-
// If the declaredType contains type arguments that are "Any" and
|
19201
|
-
// the corresponding type argument in the assignedType is not "Any",
|
19202
|
-
// replace that type argument in the assigned type. This function assumes
|
19203
|
-
// that the caller has already verified that the assignedType is assignable
|
19204
|
-
// to the declaredType.
|
19205
|
-
function replaceTypeArgsWithAny(node, declaredType, assignedType, recursionCount = 0) {
|
19206
|
-
if (recursionCount > types_1.maxTypeRecursionCount) {
|
19207
|
-
return undefined;
|
19208
|
-
}
|
19209
|
-
recursionCount++;
|
19210
|
-
if (assignedType.shared.typeParams.length > 0 &&
|
19211
|
-
assignedType.priv.typeArgs &&
|
19212
|
-
assignedType.priv.typeArgs.length <= assignedType.shared.typeParams.length &&
|
19213
|
-
!assignedType.priv.tupleTypeArgs) {
|
19214
|
-
const constraints = new constraintTracker_1.ConstraintTracker();
|
19215
|
-
(0, constraintSolver_1.addConstraintsForExpectedType)(evaluatorInterface, types_1.ClassType.specialize(assignedType, /* typeArgs */ undefined), declaredType, constraints, ParseTreeUtils.getTypeVarScopesForNode(node), node.start);
|
19216
|
-
let replacedTypeArg = false;
|
19217
|
-
const solution = (0, constraintSolver_1.solveConstraints)(evaluatorInterface, constraints).getMainSolutionSet();
|
19218
|
-
const newTypeArgs = assignedType.priv.typeArgs.map((typeArg, index) => {
|
19219
|
-
const typeParam = assignedType.shared.typeParams[index];
|
19220
|
-
const expectedTypeArgType = solution.getType(typeParam);
|
19221
|
-
if (expectedTypeArgType) {
|
19222
|
-
if ((0, types_1.isAnyOrUnknown)(expectedTypeArgType) || (0, types_1.isAnyOrUnknown)(typeArg)) {
|
19223
|
-
replacedTypeArg = true;
|
19224
|
-
return expectedTypeArgType;
|
19225
|
-
}
|
19226
|
-
if ((0, types_1.isClassInstance)(expectedTypeArgType) && (0, types_1.isClassInstance)(typeArg)) {
|
19227
|
-
// Recursively replace Any in the type argument.
|
19228
|
-
const recursiveReplacement = replaceTypeArgsWithAny(node, expectedTypeArgType, typeArg, recursionCount);
|
19229
|
-
if (recursiveReplacement) {
|
19230
|
-
replacedTypeArg = true;
|
19231
|
-
return recursiveReplacement;
|
19232
|
-
}
|
19233
|
-
}
|
19234
|
-
else if ((0, typeUtils_1.containsAnyRecursive)(expectedTypeArgType)) {
|
19235
|
-
// If the expected type arg contains an Any, we can replace it with
|
19236
|
-
// a version that doesn't contain Any if the replacement doesn't violate
|
19237
|
-
// the variance of the type parameter.
|
19238
|
-
const variance = types_1.TypeVarType.getVariance(typeParam);
|
19239
|
-
const isSubtype = assignType(expectedTypeArgType, typeArg);
|
19240
|
-
const isSupertype = assignType(typeArg, expectedTypeArgType);
|
19241
|
-
if ((variance === 4 /* Variance.Contravariant */ || isSubtype) &&
|
19242
|
-
(variance === 3 /* Variance.Covariant */ || isSupertype)) {
|
19243
|
-
replacedTypeArg = true;
|
19244
|
-
return expectedTypeArgType;
|
19245
|
-
}
|
19246
|
-
}
|
19247
|
-
}
|
19248
|
-
return typeArg;
|
19249
|
-
});
|
19250
|
-
if (replacedTypeArg) {
|
19251
|
-
return types_1.ClassType.specialize(assignedType, newTypeArgs);
|
19252
|
-
}
|
19253
|
-
}
|
19254
|
-
// If the declared and assigned types are the same generic type but the assigned type
|
19255
|
-
// contains one or more unknowns, use the declared type instead.
|
19256
|
-
if (types_1.ClassType.isSameGenericClass(declaredType, assignedType)) {
|
19257
|
-
if ((0, typeUtils_1.containsAnyRecursive)(assignedType) && !(0, typeUtils_1.containsAnyRecursive)(declaredType)) {
|
19258
|
-
return declaredType;
|
19259
|
-
}
|
19260
|
-
}
|
19261
|
-
return undefined;
|
19262
|
-
}
|
19263
19243
|
// When a value is assigned to a variable with a declared type,
|
19264
19244
|
// we may be able to narrow the type based on the assignment.
|
19265
|
-
function narrowTypeBasedOnAssignment(
|
19245
|
+
function narrowTypeBasedOnAssignment(declaredType, assignedTypeResult) {
|
19266
19246
|
// TODO: The rules for narrowing types on assignment are not defined in
|
19267
19247
|
// the typing spec. Pyright's current logic is currently not even internally
|
19268
19248
|
// consistent and probably not sound from a type theory perspective. It
|
@@ -19278,46 +19258,36 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
19278
19258
|
}
|
19279
19259
|
}
|
19280
19260
|
const narrowedSubtype = (0, typeUtils_1.mapSubtypes)(declaredType, (declaredSubtype) => {
|
19281
|
-
|
19282
|
-
|
19283
|
-
return declaredSubtype;
|
19261
|
+
if (!assignType(declaredSubtype, assignedSubtype)) {
|
19262
|
+
return undefined;
|
19284
19263
|
}
|
19285
|
-
|
19286
|
-
|
19287
|
-
|
19288
|
-
|
19289
|
-
|
19290
|
-
|
19291
|
-
|
19292
|
-
|
19293
|
-
|
19294
|
-
|
19295
|
-
|
19296
|
-
|
19264
|
+
// Retain unknowns for code flow analysis convergence and for
|
19265
|
+
// unknown type reporting in strict mode.
|
19266
|
+
if ((0, types_1.isUnknown)(assignedSubtype)) {
|
19267
|
+
return assignedSubtype;
|
19268
|
+
}
|
19269
|
+
// If the two types are bidirectionally assignable, they are
|
19270
|
+
// either equivalent (in which case it doesn't matter which
|
19271
|
+
// one we choose) or one or both include gradual types (Any, etc.),
|
19272
|
+
// in which case we'll want to stick with the declared subtype.
|
19273
|
+
if (assignType(assignedSubtype, declaredSubtype)) {
|
19274
|
+
// We need to be careful with TypedDict types that have
|
19275
|
+
// narrowed fields. In this case, we want to return the
|
19276
|
+
// assigned type.
|
19277
|
+
if ((0, types_1.isClass)(assignedSubtype) &&
|
19278
|
+
assignedSubtype.priv.typedDictNarrowedEntries &&
|
19279
|
+
(0, types_1.isTypeSame)(assignedSubtype, declaredSubtype, { ignoreTypedDictNarrowEntries: true })) {
|
19297
19280
|
return assignedSubtype;
|
19298
19281
|
}
|
19299
|
-
|
19300
|
-
|
19301
|
-
|
19302
|
-
|
19303
|
-
|
19304
|
-
return declaredSubtype;
|
19305
|
-
}
|
19306
|
-
// If the declared type doesn't contain any `Any` but the assigned
|
19307
|
-
// type does, stick with the declared type. We don't include unknowns
|
19308
|
-
// in the assigned subtype check here so unknowns are preserved so
|
19309
|
-
// reportUnknownVariableType assignment diagnostics are reported.
|
19310
|
-
// TODO - this is an inconsistency because Any and Unknown should
|
19311
|
-
// always be treated the same for purposes of type narrowing. This
|
19312
|
-
// should be revisited once the narrowing-on-assignment behavior
|
19313
|
-
// is properly specified in the typing spec.
|
19314
|
-
if ((0, typeUtils_1.containsAnyRecursive)(assignedSubtype, /* includeUnknown */ false) &&
|
19315
|
-
!(0, typeUtils_1.containsAnyRecursive)(declaredSubtype)) {
|
19316
|
-
return declaredSubtype;
|
19282
|
+
// We also need to be careful with callback protocols.
|
19283
|
+
if ((0, types_1.isClassInstance)(declaredSubtype) && types_1.ClassType.isProtocolClass(declaredSubtype)) {
|
19284
|
+
if ((0, types_1.isFunction)(assignedSubtype) || (0, types_1.isOverloaded)(assignedSubtype)) {
|
19285
|
+
return assignedSubtype;
|
19286
|
+
}
|
19317
19287
|
}
|
19318
|
-
return
|
19288
|
+
return declaredSubtype;
|
19319
19289
|
}
|
19320
|
-
return
|
19290
|
+
return assignedSubtype;
|
19321
19291
|
});
|
19322
19292
|
// If we couldn't assign the assigned subtype any of the declared
|
19323
19293
|
// subtypes, the types are incompatible. Return the unnarrowed form.
|
@@ -19332,12 +19302,12 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
19332
19302
|
// with the declared type. In strict mode, this will retain the "unknown type"
|
19333
19303
|
// diagnostics while still providing reasonable completion suggestions.
|
19334
19304
|
if ((0, typeUtils_1.isIncompleteUnknown)(narrowedType)) {
|
19335
|
-
return { type: narrowedType };
|
19305
|
+
return { type: narrowedType, isIncomplete: assignedTypeResult.isIncomplete };
|
19336
19306
|
}
|
19337
19307
|
else if ((0, types_1.isUnknown)(narrowedType)) {
|
19338
|
-
return { type: (0, types_1.combineTypes)([narrowedType, declaredType]) };
|
19308
|
+
return { type: (0, types_1.combineTypes)([narrowedType, declaredType]), isIncomplete: assignedTypeResult.isIncomplete };
|
19339
19309
|
}
|
19340
|
-
return { type: narrowedType };
|
19310
|
+
return { type: narrowedType, isIncomplete: assignedTypeResult.isIncomplete };
|
19341
19311
|
}
|
19342
19312
|
function validateOverrideMethod(baseMethod, overrideMethod, baseClass, diag, enforceParamNames = true) {
|
19343
19313
|
// If we're overriding a non-method with a method, report it as an error.
|
@@ -19860,6 +19830,11 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
19860
19830
|
if (!baseType) {
|
19861
19831
|
return types_1.FunctionType.clone(functionType, /* stripFirstParam */ true);
|
19862
19832
|
}
|
19833
|
+
// If the first parameter was already stripped, it has already been
|
19834
|
+
// bound. Don't attempt to rebind.
|
19835
|
+
if (functionType.priv.strippedFirstParamType) {
|
19836
|
+
return functionType;
|
19837
|
+
}
|
19863
19838
|
if (types_1.FunctionType.isInstanceMethod(functionType)) {
|
19864
19839
|
// If the baseType is a metaclass, don't specialize the function.
|
19865
19840
|
if ((0, typeUtils_1.isInstantiableMetaclass)(baseType)) {
|
@@ -19917,6 +19892,22 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
19917
19892
|
}
|
19918
19893
|
else {
|
19919
19894
|
const subDiag = diag?.createAddendum();
|
19895
|
+
// Protect against the case where a callback protocol is being
|
19896
|
+
// bound to its own __call__ method but the first parameter
|
19897
|
+
// is annotated with its own callable type. This can lead to
|
19898
|
+
// infinite recursion.
|
19899
|
+
if ((0, types_1.isFunction)(memberTypeFirstParamType) || (0, types_1.isOverloaded)(memberTypeFirstParamType)) {
|
19900
|
+
if ((0, types_1.isClassInstance)(firstParamType) && types_1.ClassType.isProtocolClass(firstParamType)) {
|
19901
|
+
if (subDiag) {
|
19902
|
+
subDiag.addMessage(localize_1.LocMessage.bindTypeMismatch().format({
|
19903
|
+
type: printType(firstParamType),
|
19904
|
+
methodName: memberType.shared.name || '<anonymous>',
|
19905
|
+
paramName: memberTypeFirstParam.name || '__p0',
|
19906
|
+
}));
|
19907
|
+
}
|
19908
|
+
return undefined;
|
19909
|
+
}
|
19910
|
+
}
|
19920
19911
|
if (!assignType(memberTypeFirstParamType, firstParamType, subDiag?.createAddendum(), constraints, 8192 /* AssignTypeFlags.AllowUnspecifiedTypeArgs */, recursionCount)) {
|
19921
19912
|
if (memberTypeFirstParam.name &&
|
19922
19913
|
!types_1.FunctionParam.isNameSynthesized(memberTypeFirstParam) &&
|
@@ -20195,7 +20186,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
20195
20186
|
return codeFlowEngine.printControlFlowGraph(flowNode, reference, callName, logger);
|
20196
20187
|
}
|
20197
20188
|
// Track these apis internal usages when logging is on. otherwise, it should be noop.
|
20198
|
-
const
|
20189
|
+
const getInferredReturnTypeResult = wrapWithLogger(_getInferredReturnTypeResult);
|
20199
20190
|
const evaluatorInterface = {
|
20200
20191
|
runWithCancellationToken,
|
20201
20192
|
getType,
|