@@ -8887,7 +8887,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
8887
8887
8888
8888
// Create a helper function that evaluates the overload that best
8889
8889
// matches the arg/param lists.
8890
- function evaluateUsingBestMatchingOverload(skipUnknownArgCheck: boolean) {
8890
+ function evaluateUsingBestMatchingOverload(skipUnknownArgCheck: boolean, emitNoOverloadFoundError: boolean ) {
8891
8891
// Find the match with the smallest argument match score. If there
8892
8892
// are more than one with the same score, use the one with the
8893
8893
// largest index. Later overloads tend to be more general.
@@ -8898,6 +8898,27 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
8898
8898
return current.argumentMatchScore < previous.argumentMatchScore ? current : previous;
8899
8899
});
8900
8900
8901
+ // If there is more than one filtered match, report that no match
8902
+ // was possible and emit a diagnostic that provides the most likely.
8903
+ if (emitNoOverloadFoundError) {
8904
+ const functionName = bestMatch.overload.details.name || '<anonymous function>';
8905
+ const diagnostic = addDiagnostic(
8906
+ AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.reportGeneralTypeIssues,
8907
+ DiagnosticRule.reportGeneralTypeIssues,
8908
+ Localizer.Diagnostic.noOverload().format({ name: functionName }),
8909
+ errorNode
8910
+ );
8911
+
8912
+ const overrideDecl = bestMatch.overload.details.declaration;
8913
+ if (diagnostic && overrideDecl) {
8914
+ diagnostic.addRelatedInfo(
8915
+ Localizer.DiagnosticAddendum.overloadIndex().format({ index: bestMatch.overloadIndex + 1 }),
8916
+ overrideDecl.path,
8917
+ overrideDecl.range
8918
+ );
8919
+ }
8920
+ }
8921
+
8901
8922
const effectiveTypeVarContext = typeVarContext ?? new TypeVarContext();
8902
8923
effectiveTypeVarContext.addSolveForScope(getTypeVarScopeIds(bestMatch.overload));
8903
8924
effectiveTypeVarContext.unlock();
@@ -8915,7 +8936,10 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
8915
8936
// use the normal type matching mechanism because it is faster and
8916
8937
// will provide a clearer error message.
8917
8938
if (filteredMatchResults.length === 1) {
8918
- return evaluateUsingBestMatchingOverload(/* skipUnknownArgCheck */ false);
8939
+ return evaluateUsingBestMatchingOverload(
8940
+ /* skipUnknownArgCheck */ false,
8941
+ /* emitNoOverloadFoundError */ false
8942
+ );
8919
8943
}
8920
8944
8921
8945
let expandedArgTypes: (Type | undefined)[][] | undefined = [argList.map((arg) => undefined)];
@@ -8974,7 +8998,10 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
8974
8998
// in speculative mode because it's very expensive, and we're going to
8975
8999
// suppress the diagnostic anyway.
8976
9000
if (!isDiagnosticSuppressedForNode(errorNode) && !isTypeIncomplete) {
8977
- const result = evaluateUsingBestMatchingOverload(/* skipUnknownArgCheck */ true);
9001
+ const result = evaluateUsingBestMatchingOverload(
9002
+ /* skipUnknownArgCheck */ true,
9003
+ /* emitNoOverloadFoundError */ true
9004
+ );
8978
9005
8979
9006
// Replace the result with an unknown type since we don't know
8980
9007
// what overload should have been used.
0 commit comments