@zzzen/pyright-internal 1.2.0-dev.20250316 → 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 +20 -12
- 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/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/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 +1 -3
- package/dist/analyzer/service.js +1 -3
- 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 +156 -200
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +2 -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.js +2 -3
- 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/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 +2 -2
- package/dist/tests/sourceFile.test.js +5 -4
- package/dist/tests/sourceFile.test.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +5 -1
- 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/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.
|
@@ -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) {
|
@@ -6920,6 +6923,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6920
6923
|
case 6 /* TypeCategory.Class */: {
|
6921
6924
|
if ((0, typeUtils_1.isNoneInstance)(expandedCallType)) {
|
6922
6925
|
addDiagnostic(diagnosticRules_1.DiagnosticRule.reportOptionalCall, localize_1.LocMessage.noneNotCallable(), errorNode);
|
6926
|
+
touchArgTypes();
|
6923
6927
|
return { argumentErrors: true };
|
6924
6928
|
}
|
6925
6929
|
if (types_1.TypeBase.isInstantiable(expandedCallType)) {
|
@@ -6936,6 +6940,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
6936
6940
|
}
|
6937
6941
|
case 7 /* TypeCategory.Module */: {
|
6938
6942
|
addDiagnostic(diagnosticRules_1.DiagnosticRule.reportCallIssue, localize_1.LocMessage.moduleNotCallable(), errorNode);
|
6943
|
+
touchArgTypes();
|
6939
6944
|
return { argumentErrors: true };
|
6940
6945
|
}
|
6941
6946
|
}
|
@@ -7398,25 +7403,15 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7398
7403
|
const paramDetails = (0, parameterUtils_1.getParamListDetails)(overload, { disallowExtraKwargsForTd: true });
|
7399
7404
|
const paramSpec = types_1.FunctionType.getParamSpecFromArgsKwargs(overload);
|
7400
7405
|
let argIndex = 0;
|
7401
|
-
let
|
7406
|
+
let unpackedArgOfUnknownLength = false;
|
7407
|
+
let unpackedArgMapsToVariadic = false;
|
7402
7408
|
let reportedArgError = false;
|
7403
7409
|
let isTypeIncomplete = !!typeResult.isIncomplete;
|
7404
7410
|
let isTypeVarTupleFullyMatched = false;
|
7405
7411
|
// Expand any unpacked tuples in the arg list.
|
7406
7412
|
argList = expandArgList(argList);
|
7407
|
-
//
|
7408
|
-
const
|
7409
|
-
paramDetails.params.forEach((paramInfo) => {
|
7410
|
-
(0, debug_1.assert)(paramInfo !== undefined, 'paramInfo is undefined for param name map');
|
7411
|
-
const param = paramInfo.param;
|
7412
|
-
if (param.name && param.category === 0 /* ParamCategory.Simple */ && paramInfo.kind !== parameterUtils_1.ParamKind.Positional) {
|
7413
|
-
let argsNeeded = paramMap.get(param.name)?.argsNeeded ?? 0;
|
7414
|
-
if (param.category === 0 /* ParamCategory.Simple */ && !paramInfo.defaultType) {
|
7415
|
-
argsNeeded += 1;
|
7416
|
-
}
|
7417
|
-
paramMap.set(param.name, { argsNeeded, argsReceived: 0 });
|
7418
|
-
}
|
7419
|
-
});
|
7413
|
+
// Construct an object that racks which parameters have been assigned arguments.
|
7414
|
+
const paramTracker = new parameterUtils_1.ParamAssignmentTracker(paramDetails.params);
|
7420
7415
|
let positionalOnlyLimitIndex = paramDetails.positionOnlyParamCount;
|
7421
7416
|
let positionParamLimitIndex = paramDetails.firstKeywordOnlyIndex ?? paramDetails.params.length;
|
7422
7417
|
const varArgListParamIndex = paramDetails.argsIndex;
|
@@ -7535,6 +7530,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7535
7530
|
argType.priv.tupleTypeArgs.length > 0) {
|
7536
7531
|
tooManyPositionals = true;
|
7537
7532
|
}
|
7533
|
+
else {
|
7534
|
+
unpackedArgOfUnknownLength = true;
|
7535
|
+
}
|
7538
7536
|
}
|
7539
7537
|
else {
|
7540
7538
|
tooManyPositionals = true;
|
@@ -7627,8 +7625,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7627
7625
|
if (!listElementType) {
|
7628
7626
|
enforceIterable = true;
|
7629
7627
|
}
|
7628
|
+
unpackedArgOfUnknownLength = true;
|
7630
7629
|
if (paramInfo.param.category === 1 /* ParamCategory.ArgsList */) {
|
7631
|
-
|
7630
|
+
unpackedArgMapsToVariadic = true;
|
7632
7631
|
}
|
7633
7632
|
if (isParamVariadic && listElementType) {
|
7634
7633
|
isArgCompatibleWithVariadic = true;
|
@@ -7672,10 +7671,8 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7672
7671
|
}
|
7673
7672
|
trySetActive(argList[argIndex], paramDetails.params[paramIndex].param);
|
7674
7673
|
// Note that the parameter has received an argument.
|
7675
|
-
if (paramName &&
|
7676
|
-
|
7677
|
-
paramMap.has(paramName)) {
|
7678
|
-
paramMap.get(paramName).argsReceived++;
|
7674
|
+
if (paramName && paramDetails.params[paramIndex].param.category === 0 /* ParamCategory.Simple */) {
|
7675
|
+
paramTracker.markArgReceived(paramInfo);
|
7679
7676
|
}
|
7680
7677
|
if (advanceToNextArg || paramDetails.params[paramIndex].param.category === 1 /* ParamCategory.ArgsList */) {
|
7681
7678
|
argIndex++;
|
@@ -7744,9 +7741,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7744
7741
|
});
|
7745
7742
|
trySetActive(argList[argIndex], paramInfo.param);
|
7746
7743
|
// Note that the parameter has received an argument.
|
7747
|
-
|
7748
|
-
paramMap.get(paramName).argsReceived++;
|
7749
|
-
}
|
7744
|
+
paramTracker.markArgReceived(paramInfo);
|
7750
7745
|
argIndex++;
|
7751
7746
|
paramIndex++;
|
7752
7747
|
}
|
@@ -7820,7 +7815,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7820
7815
|
const tdEntries = (0, typedDicts_1.getTypedDictMembersForClass)(evaluatorInterface, argType);
|
7821
7816
|
const diag = new diagnostic_1.DiagnosticAddendum();
|
7822
7817
|
tdEntries.knownItems.forEach((entry, name) => {
|
7823
|
-
const paramEntry =
|
7818
|
+
const paramEntry = paramTracker.lookupName(name);
|
7824
7819
|
if (paramEntry) {
|
7825
7820
|
if (paramEntry.argsReceived > 0) {
|
7826
7821
|
diag.addMessage(localize_1.LocMessage.paramAlreadyAssigned().format({ name }));
|
@@ -7857,10 +7852,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7857
7852
|
paramName: name,
|
7858
7853
|
});
|
7859
7854
|
// Remember that this parameter has already received a value.
|
7860
|
-
|
7861
|
-
argsNeeded: 1,
|
7862
|
-
argsReceived: 1,
|
7863
|
-
});
|
7855
|
+
paramTracker.addKeywordParam(name, paramDetails.params[paramDetails.kwargsIndex]);
|
7864
7856
|
}
|
7865
7857
|
else {
|
7866
7858
|
// If the function doesn't have a **kwargs parameter, we need to emit an error.
|
@@ -7946,6 +7938,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7946
7938
|
unpackedDictArgType = types_1.UnknownType.create();
|
7947
7939
|
}
|
7948
7940
|
}
|
7941
|
+
unpackedArgOfUnknownLength = true;
|
7949
7942
|
if (paramDetails.kwargsIndex !== undefined && unpackedDictArgType) {
|
7950
7943
|
const paramType = paramDetails.params[paramDetails.kwargsIndex].type;
|
7951
7944
|
validateArgTypeParams.push({
|
@@ -7957,6 +7950,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7957
7950
|
errorNode: argList[argIndex].valueExpression || errorNode,
|
7958
7951
|
paramName: paramDetails.params[paramDetails.kwargsIndex].param.name,
|
7959
7952
|
});
|
7953
|
+
unpackedArgMapsToVariadic = true;
|
7960
7954
|
}
|
7961
7955
|
if (!isValidMappingType) {
|
7962
7956
|
if (!canSkipDiagnosticForNode(errorNode) && !isTypeIncomplete) {
|
@@ -7977,7 +7971,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
7977
7971
|
const paramName = argList[argIndex].name;
|
7978
7972
|
if (paramName) {
|
7979
7973
|
const paramNameValue = paramName.d.value;
|
7980
|
-
const paramEntry =
|
7974
|
+
const paramEntry = paramTracker.lookupName(paramNameValue);
|
7981
7975
|
if (paramEntry) {
|
7982
7976
|
if (paramEntry.argsReceived > 0) {
|
7983
7977
|
if (!canSkipDiagnosticForNode(errorNode) && !isTypeIncomplete) {
|
@@ -8022,12 +8016,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8022
8016
|
errorNode: argList[argIndex].valueExpression ?? errorNode,
|
8023
8017
|
paramName: paramNameValue,
|
8024
8018
|
});
|
8025
|
-
// Remember that this parameter has already received a value.
|
8026
|
-
paramMap.set(paramNameValue, {
|
8027
|
-
argsNeeded: 1,
|
8028
|
-
argsReceived: 1,
|
8029
|
-
});
|
8030
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]);
|
8031
8022
|
}
|
8032
8023
|
trySetActive(argList[argIndex], paramDetails.params[paramDetails.kwargsIndex].param);
|
8033
8024
|
}
|
@@ -8088,8 +8079,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8088
8079
|
if (paramIndex >= paramDetails.firstPositionOrKeywordIndex &&
|
8089
8080
|
param.category === 0 /* ParamCategory.Simple */ &&
|
8090
8081
|
param.name &&
|
8091
|
-
|
8092
|
-
paramMap.get(param.name).argsReceived === 0) {
|
8082
|
+
paramTracker.lookupDetails(paramInfo).argsReceived === 0) {
|
8093
8083
|
const paramType = paramDetails.params[paramIndex].type;
|
8094
8084
|
if (!unpackedDictKeyNames || unpackedDictKeyNames.includes(param.name)) {
|
8095
8085
|
validateArgTypeParams.push({
|
@@ -8105,7 +8095,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8105
8095
|
paramName: param.name,
|
8106
8096
|
isParamNameSynthesized: types_1.FunctionParam.isNameSynthesized(param),
|
8107
8097
|
});
|
8108
|
-
|
8098
|
+
paramTracker.markArgReceived(paramDetails.params[paramIndex]);
|
8109
8099
|
}
|
8110
8100
|
}
|
8111
8101
|
});
|
@@ -8115,10 +8105,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8115
8105
|
// (i.e. an arg starting with a "**"), we will assume that all parameters
|
8116
8106
|
// are matched.
|
8117
8107
|
if (!unpackedDictArgType && !types_1.FunctionType.isDefaultParamCheckDisabled(overload)) {
|
8118
|
-
const unassignedParams =
|
8119
|
-
const entry = paramMap.get(name);
|
8120
|
-
return !entry || entry.argsReceived < entry.argsNeeded;
|
8121
|
-
});
|
8108
|
+
const unassignedParams = paramTracker.getUnassignedParams();
|
8122
8109
|
if (unassignedParams.length > 0) {
|
8123
8110
|
if (!canSkipDiagnosticForNode(errorNode)) {
|
8124
8111
|
const missingParamNames = unassignedParams.map((p) => `"${p}"`).join(', ');
|
@@ -8138,8 +8125,8 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8138
8125
|
paramDetails.params.forEach((paramInfo) => {
|
8139
8126
|
const param = paramInfo.param;
|
8140
8127
|
if (param.category === 0 /* ParamCategory.Simple */ && param.name) {
|
8141
|
-
const entry =
|
8142
|
-
if (entry
|
8128
|
+
const entry = paramTracker.lookupDetails(paramInfo);
|
8129
|
+
if (entry.argsNeeded === 0 && entry.argsReceived === 0) {
|
8143
8130
|
const defaultArgType = paramInfo.defaultType;
|
8144
8131
|
if (defaultArgType &&
|
8145
8132
|
!(0, typeUtils_1.isEllipsisType)(defaultArgType) &&
|
@@ -8230,13 +8217,6 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8230
8217
|
}
|
8231
8218
|
}
|
8232
8219
|
}
|
8233
|
-
let relevance = 0;
|
8234
|
-
if (matchedUnpackedListOfUnknownLength) {
|
8235
|
-
// Increase the relevance if we made assumptions about the length
|
8236
|
-
// of an unpacked argument. This will favor overloads that
|
8237
|
-
// associate this case with a *args parameter.
|
8238
|
-
relevance++;
|
8239
|
-
}
|
8240
8220
|
// Special-case the builtin isinstance and issubclass functions.
|
8241
8221
|
if (types_1.FunctionType.isBuiltIn(overload, ['isinstance', 'issubclass']) && validateArgTypeParams.length === 2) {
|
8242
8222
|
validateArgTypeParams[1].isinstanceParam = true;
|
@@ -8250,7 +8230,8 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8250
8230
|
paramSpecTarget,
|
8251
8231
|
paramSpecArgList,
|
8252
8232
|
activeParam,
|
8253
|
-
|
8233
|
+
unpackedArgOfUnknownLength,
|
8234
|
+
unpackedArgMapsToVariadic,
|
8254
8235
|
argumentMatchScore: 0,
|
8255
8236
|
};
|
8256
8237
|
}
|
@@ -8505,9 +8486,13 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8505
8486
|
}
|
8506
8487
|
}
|
8507
8488
|
// Calculate the return type.
|
8508
|
-
|
8489
|
+
const returnTypeResult = getEffectiveReturnTypeResult(type, {
|
8509
8490
|
callSiteInfo: { args: matchResults.argParams, errorNode },
|
8510
8491
|
});
|
8492
|
+
let returnType = returnTypeResult.type;
|
8493
|
+
if (returnTypeResult.isIncomplete) {
|
8494
|
+
isTypeIncomplete = true;
|
8495
|
+
}
|
8511
8496
|
if (condition.length > 0) {
|
8512
8497
|
returnType = types_1.TypeBase.cloneForCondition(returnType, condition);
|
8513
8498
|
}
|
@@ -8766,9 +8751,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
8766
8751
|
else {
|
8767
8752
|
skippedBareTypeVarExpectedType = true;
|
8768
8753
|
}
|
8769
|
-
// If the expected type is
|
8754
|
+
// If the expected type is unknown, don't use an expected type. Instead,
|
8770
8755
|
// use default rules for evaluating the expression type.
|
8771
|
-
if (expectedType && (0, types_1.
|
8756
|
+
if (expectedType && (0, types_1.isUnknown)(expectedType)) {
|
8772
8757
|
expectedType = undefined;
|
8773
8758
|
}
|
8774
8759
|
// Was the argument's type precomputed by the caller?
|
@@ -10423,7 +10408,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
10423
10408
|
: undefined, () => {
|
10424
10409
|
const returnTypeResult = getTypeOfExpression(node.d.expr,
|
10425
10410
|
/* flags */ undefined, (0, typeUtils_1.makeInferenceContext)(expectedReturnType));
|
10426
|
-
functionType.
|
10411
|
+
functionType.shared.inferredReturnType = {
|
10427
10412
|
type: returnTypeResult.type,
|
10428
10413
|
};
|
10429
10414
|
if (returnTypeResult.isIncomplete) {
|
@@ -13569,7 +13554,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
13569
13554
|
awaitableFunctionType.shared.declaredReturnType = createAwaitableReturnType(node, functionType.shared.declaredReturnType, types_1.FunctionType.isGenerator(functionType));
|
13570
13555
|
}
|
13571
13556
|
else {
|
13572
|
-
awaitableFunctionType.
|
13557
|
+
awaitableFunctionType.shared.inferredReturnType = {
|
13573
13558
|
type: createAwaitableReturnType(node, getInferredReturnType(functionType), types_1.FunctionType.isGenerator(functionType)),
|
13574
13559
|
};
|
13575
13560
|
}
|
@@ -16633,38 +16618,49 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
16633
16618
|
}
|
16634
16619
|
}
|
16635
16620
|
}
|
16621
|
+
function getEffectiveReturnType(type) {
|
16622
|
+
return getEffectiveReturnTypeResult(type).type;
|
16623
|
+
}
|
16624
|
+
function getInferredReturnType(type) {
|
16625
|
+
return getInferredReturnTypeResult(type).type;
|
16626
|
+
}
|
16636
16627
|
// Returns the return type of the function. If the type is explicitly provided in
|
16637
16628
|
// a type annotation, that type is returned. If not, an attempt is made to infer
|
16638
16629
|
// the return type. If a list of args is provided, the inference logic may take
|
16639
16630
|
// into account argument types to infer the return type.
|
16640
|
-
function
|
16631
|
+
function getEffectiveReturnTypeResult(type, options) {
|
16641
16632
|
const specializedReturnType = types_1.FunctionType.getEffectiveReturnType(type, /* includeInferred */ false);
|
16642
16633
|
if (specializedReturnType && !(0, types_1.isUnknown)(specializedReturnType)) {
|
16643
|
-
return specializedReturnType;
|
16634
|
+
return { type: specializedReturnType };
|
16644
16635
|
}
|
16645
|
-
return
|
16636
|
+
return getInferredReturnTypeResult(type, options?.callSiteInfo);
|
16646
16637
|
}
|
16647
|
-
function
|
16638
|
+
function _getInferredReturnTypeResult(type, callSiteInfo) {
|
16648
16639
|
let returnType;
|
16649
16640
|
let isIncomplete = false;
|
16650
16641
|
const analyzeUnannotatedFunctions = true;
|
16651
16642
|
// Don't attempt to infer the return type for a stub file.
|
16652
16643
|
if (types_1.FunctionType.isStubDefinition(type)) {
|
16653
|
-
return types_1.UnknownType.create();
|
16644
|
+
return { type: types_1.UnknownType.create() };
|
16654
16645
|
}
|
16655
16646
|
// Don't infer the return type for a ParamSpec value.
|
16656
16647
|
if (types_1.FunctionType.isParamSpecValue(type)) {
|
16657
|
-
return types_1.UnknownType.create();
|
16648
|
+
return { type: types_1.UnknownType.create() };
|
16658
16649
|
}
|
16659
16650
|
// Don't infer the return type for an overloaded function (unless it's synthesized,
|
16660
16651
|
// which is needed for proper operation of the __get__ method in properties).
|
16661
16652
|
if (types_1.FunctionType.isOverloaded(type) && !types_1.FunctionType.isSynthesizedMethod(type)) {
|
16662
|
-
return types_1.UnknownType.create();
|
16653
|
+
return { type: types_1.UnknownType.create() };
|
16663
16654
|
}
|
16655
|
+
const evalCount = type.shared.inferredReturnType?.evaluationCount ?? 0;
|
16664
16656
|
// If the return type has already been lazily evaluated,
|
16665
16657
|
// don't bother computing it again.
|
16666
|
-
if (type.
|
16667
|
-
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();
|
16668
16664
|
}
|
16669
16665
|
else {
|
16670
16666
|
// Don't bother inferring the return type of __init__ because it's
|
@@ -16711,7 +16707,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
16711
16707
|
}
|
16712
16708
|
returnType = (0, typeUtils_1.makeTypeVarsFree)(returnType, typeVarScopes);
|
16713
16709
|
// Cache the type for next time.
|
16714
|
-
type.
|
16710
|
+
type.shared.inferredReturnType = { type: returnType, isIncomplete, evaluationCount: evalCount + 1 };
|
16715
16711
|
}
|
16716
16712
|
// If the type is partially unknown and the function has one or more unannotated
|
16717
16713
|
// params, try to analyze the function with the provided argument types and
|
@@ -16748,7 +16744,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
16748
16744
|
}
|
16749
16745
|
}
|
16750
16746
|
}
|
16751
|
-
return returnType;
|
16747
|
+
return { type: returnType, isIncomplete };
|
16752
16748
|
}
|
16753
16749
|
function inferReturnTypeForCallSite(type, callSiteInfo) {
|
16754
16750
|
const args = callSiteInfo.args;
|
@@ -18278,8 +18274,10 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
18278
18274
|
}
|
18279
18275
|
// Determines whether the two types are potentially comparable -- i.e.
|
18280
18276
|
// their types overlap in such a way that it makes sense for them to
|
18281
|
-
// be compared with an == or != operator.
|
18282
|
-
|
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) {
|
18283
18281
|
if ((0, types_1.isAnyOrUnknown)(leftType) || (0, types_1.isAnyOrUnknown)(rightType)) {
|
18284
18282
|
return true;
|
18285
18283
|
}
|
@@ -18319,6 +18317,16 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
18319
18317
|
if (assignType(genericLeftType, genericRightType) || assignType(genericRightType, genericLeftType)) {
|
18320
18318
|
return true;
|
18321
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
|
+
}
|
18322
18330
|
// Assume that if the types are disjoint and built-in classes that they
|
18323
18331
|
// will never be comparable.
|
18324
18332
|
if (types_1.ClassType.isBuiltIn(leftType) && types_1.ClassType.isBuiltIn(rightType) && types_1.TypeBase.isInstance(rightType)) {
|
@@ -19232,72 +19240,9 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
19232
19240
|
}
|
19233
19241
|
return canAssign;
|
19234
19242
|
}
|
19235
|
-
// If the declaredType contains type arguments that are "Any" and
|
19236
|
-
// the corresponding type argument in the assignedType is not "Any",
|
19237
|
-
// replace that type argument in the assigned type. This function assumes
|
19238
|
-
// that the caller has already verified that the assignedType is assignable
|
19239
|
-
// to the declaredType.
|
19240
|
-
function replaceTypeArgsWithAny(node, declaredType, assignedType, recursionCount = 0) {
|
19241
|
-
if (recursionCount > types_1.maxTypeRecursionCount) {
|
19242
|
-
return undefined;
|
19243
|
-
}
|
19244
|
-
recursionCount++;
|
19245
|
-
if (assignedType.shared.typeParams.length > 0 &&
|
19246
|
-
assignedType.priv.typeArgs &&
|
19247
|
-
assignedType.priv.typeArgs.length <= assignedType.shared.typeParams.length &&
|
19248
|
-
!assignedType.priv.tupleTypeArgs) {
|
19249
|
-
const constraints = new constraintTracker_1.ConstraintTracker();
|
19250
|
-
(0, constraintSolver_1.addConstraintsForExpectedType)(evaluatorInterface, types_1.ClassType.specialize(assignedType, /* typeArgs */ undefined), declaredType, constraints, ParseTreeUtils.getTypeVarScopesForNode(node), node.start);
|
19251
|
-
let replacedTypeArg = false;
|
19252
|
-
const solution = (0, constraintSolver_1.solveConstraints)(evaluatorInterface, constraints).getMainSolutionSet();
|
19253
|
-
const newTypeArgs = assignedType.priv.typeArgs.map((typeArg, index) => {
|
19254
|
-
const typeParam = assignedType.shared.typeParams[index];
|
19255
|
-
const expectedTypeArgType = solution.getType(typeParam);
|
19256
|
-
if (expectedTypeArgType) {
|
19257
|
-
if ((0, types_1.isAnyOrUnknown)(expectedTypeArgType) || (0, types_1.isAnyOrUnknown)(typeArg)) {
|
19258
|
-
replacedTypeArg = true;
|
19259
|
-
return expectedTypeArgType;
|
19260
|
-
}
|
19261
|
-
if ((0, types_1.isClassInstance)(expectedTypeArgType) && (0, types_1.isClassInstance)(typeArg)) {
|
19262
|
-
// Recursively replace Any in the type argument.
|
19263
|
-
const recursiveReplacement = replaceTypeArgsWithAny(node, expectedTypeArgType, typeArg, recursionCount);
|
19264
|
-
if (recursiveReplacement) {
|
19265
|
-
replacedTypeArg = true;
|
19266
|
-
return recursiveReplacement;
|
19267
|
-
}
|
19268
|
-
}
|
19269
|
-
else if ((0, typeUtils_1.containsAnyRecursive)(expectedTypeArgType)) {
|
19270
|
-
// If the expected type arg contains an Any, we can replace it with
|
19271
|
-
// a version that doesn't contain Any if the replacement doesn't violate
|
19272
|
-
// the variance of the type parameter.
|
19273
|
-
const variance = types_1.TypeVarType.getVariance(typeParam);
|
19274
|
-
const isSubtype = assignType(expectedTypeArgType, typeArg);
|
19275
|
-
const isSupertype = assignType(typeArg, expectedTypeArgType);
|
19276
|
-
if ((variance === 4 /* Variance.Contravariant */ || isSubtype) &&
|
19277
|
-
(variance === 3 /* Variance.Covariant */ || isSupertype)) {
|
19278
|
-
replacedTypeArg = true;
|
19279
|
-
return expectedTypeArgType;
|
19280
|
-
}
|
19281
|
-
}
|
19282
|
-
}
|
19283
|
-
return typeArg;
|
19284
|
-
});
|
19285
|
-
if (replacedTypeArg) {
|
19286
|
-
return types_1.ClassType.specialize(assignedType, newTypeArgs);
|
19287
|
-
}
|
19288
|
-
}
|
19289
|
-
// If the declared and assigned types are the same generic type but the assigned type
|
19290
|
-
// contains one or more unknowns, use the declared type instead.
|
19291
|
-
if (types_1.ClassType.isSameGenericClass(declaredType, assignedType)) {
|
19292
|
-
if ((0, typeUtils_1.containsAnyRecursive)(assignedType) && !(0, typeUtils_1.containsAnyRecursive)(declaredType)) {
|
19293
|
-
return declaredType;
|
19294
|
-
}
|
19295
|
-
}
|
19296
|
-
return undefined;
|
19297
|
-
}
|
19298
19243
|
// When a value is assigned to a variable with a declared type,
|
19299
19244
|
// we may be able to narrow the type based on the assignment.
|
19300
|
-
function narrowTypeBasedOnAssignment(
|
19245
|
+
function narrowTypeBasedOnAssignment(declaredType, assignedTypeResult) {
|
19301
19246
|
// TODO: The rules for narrowing types on assignment are not defined in
|
19302
19247
|
// the typing spec. Pyright's current logic is currently not even internally
|
19303
19248
|
// consistent and probably not sound from a type theory perspective. It
|
@@ -19313,46 +19258,36 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
19313
19258
|
}
|
19314
19259
|
}
|
19315
19260
|
const narrowedSubtype = (0, typeUtils_1.mapSubtypes)(declaredType, (declaredSubtype) => {
|
19316
|
-
|
19317
|
-
|
19318
|
-
return declaredSubtype;
|
19261
|
+
if (!assignType(declaredSubtype, assignedSubtype)) {
|
19262
|
+
return undefined;
|
19319
19263
|
}
|
19320
|
-
|
19321
|
-
|
19322
|
-
|
19323
|
-
|
19324
|
-
|
19325
|
-
|
19326
|
-
|
19327
|
-
|
19328
|
-
|
19329
|
-
|
19330
|
-
|
19331
|
-
|
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 })) {
|
19332
19280
|
return assignedSubtype;
|
19333
19281
|
}
|
19334
|
-
|
19335
|
-
|
19336
|
-
|
19337
|
-
|
19338
|
-
|
19339
|
-
return declaredSubtype;
|
19340
|
-
}
|
19341
|
-
// If the declared type doesn't contain any `Any` but the assigned
|
19342
|
-
// type does, stick with the declared type. We don't include unknowns
|
19343
|
-
// in the assigned subtype check here so unknowns are preserved so
|
19344
|
-
// reportUnknownVariableType assignment diagnostics are reported.
|
19345
|
-
// TODO - this is an inconsistency because Any and Unknown should
|
19346
|
-
// always be treated the same for purposes of type narrowing. This
|
19347
|
-
// should be revisited once the narrowing-on-assignment behavior
|
19348
|
-
// is properly specified in the typing spec.
|
19349
|
-
if ((0, typeUtils_1.containsAnyRecursive)(assignedSubtype, /* includeUnknown */ false) &&
|
19350
|
-
!(0, typeUtils_1.containsAnyRecursive)(declaredSubtype)) {
|
19351
|
-
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
|
+
}
|
19352
19287
|
}
|
19353
|
-
return
|
19288
|
+
return declaredSubtype;
|
19354
19289
|
}
|
19355
|
-
return
|
19290
|
+
return assignedSubtype;
|
19356
19291
|
});
|
19357
19292
|
// If we couldn't assign the assigned subtype any of the declared
|
19358
19293
|
// subtypes, the types are incompatible. Return the unnarrowed form.
|
@@ -19895,6 +19830,11 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
19895
19830
|
if (!baseType) {
|
19896
19831
|
return types_1.FunctionType.clone(functionType, /* stripFirstParam */ true);
|
19897
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
|
+
}
|
19898
19838
|
if (types_1.FunctionType.isInstanceMethod(functionType)) {
|
19899
19839
|
// If the baseType is a metaclass, don't specialize the function.
|
19900
19840
|
if ((0, typeUtils_1.isInstantiableMetaclass)(baseType)) {
|
@@ -19952,6 +19892,22 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
19952
19892
|
}
|
19953
19893
|
else {
|
19954
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
|
+
}
|
19955
19911
|
if (!assignType(memberTypeFirstParamType, firstParamType, subDiag?.createAddendum(), constraints, 8192 /* AssignTypeFlags.AllowUnspecifiedTypeArgs */, recursionCount)) {
|
19956
19912
|
if (memberTypeFirstParam.name &&
|
19957
19913
|
!types_1.FunctionParam.isNameSynthesized(memberTypeFirstParam) &&
|
@@ -20230,7 +20186,7 @@ function createTypeEvaluator(importLookup, evaluatorOptions, wrapWithLogger) {
|
|
20230
20186
|
return codeFlowEngine.printControlFlowGraph(flowNode, reference, callName, logger);
|
20231
20187
|
}
|
20232
20188
|
// Track these apis internal usages when logging is on. otherwise, it should be noop.
|
20233
|
-
const
|
20189
|
+
const getInferredReturnTypeResult = wrapWithLogger(_getInferredReturnTypeResult);
|
20234
20190
|
const evaluatorInterface = {
|
20235
20191
|
runWithCancellationToken,
|
20236
20192
|
getType,
|