mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-11 07:55:56 +03:00
Improved coalescing of overload return types when the result is ambiguous due to Any
or Unknown
arguments.
This commit is contained in:
parent
1dc84b93b1
commit
c9e43d2594
@ -7751,11 +7751,33 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
|
||||
// Unknown, but include the "possible types" to allow for completion
|
||||
// suggestions.
|
||||
if (!isDefinitiveMatchFound) {
|
||||
if (possibleMatchResults.length > 1) {
|
||||
returnTypes.push(UnknownType.createPossibleType(combineTypes(possibleMatchResults)));
|
||||
} else {
|
||||
returnTypes.push(possibleMatchResults[0]);
|
||||
}
|
||||
// Eliminate any return types that are subsumed by other return types.
|
||||
let dedupedMatchResults: Type[] = [];
|
||||
|
||||
possibleMatchResults.forEach((subtype) => {
|
||||
let isSubtypeSubsumed = false;
|
||||
|
||||
for (let dedupedIndex = 0; dedupedIndex < dedupedMatchResults.length; dedupedIndex++) {
|
||||
if (assignType(dedupedMatchResults[dedupedIndex], subtype)) {
|
||||
isSubtypeSubsumed = true;
|
||||
break;
|
||||
} else if (assignType(subtype, dedupedMatchResults[dedupedIndex])) {
|
||||
dedupedMatchResults[dedupedIndex] = NeverType.createNever();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSubtypeSubsumed) {
|
||||
dedupedMatchResults.push(subtype);
|
||||
}
|
||||
});
|
||||
|
||||
dedupedMatchResults = dedupedMatchResults.filter((t) => !isNever(t));
|
||||
const combinedTypes = combineTypes(dedupedMatchResults);
|
||||
|
||||
returnTypes.push(
|
||||
dedupedMatchResults.length > 1 ? UnknownType.createPossibleType(combinedTypes) : combinedTypes
|
||||
);
|
||||
}
|
||||
|
||||
if (!matchedOverload) {
|
||||
|
@ -2,30 +2,76 @@
|
||||
# matches are found due to an Any or Unknown argument.
|
||||
|
||||
from typing import Any, overload
|
||||
from typing_extensions import LiteralString
|
||||
|
||||
|
||||
@overload
|
||||
def func1(x: int, y: float) -> float:
|
||||
def overload1(x: int, y: float) -> float:
|
||||
...
|
||||
|
||||
@overload
|
||||
def func1(x: str, y: float) -> str:
|
||||
def overload1(x: str, y: float) -> str:
|
||||
...
|
||||
|
||||
def func1(x: str | int, y: float) -> float | str:
|
||||
def overload1(x: str | int, y: float) -> float | str:
|
||||
...
|
||||
|
||||
|
||||
def func1(a: Any):
|
||||
v1 = overload1(1, 3.4)
|
||||
reveal_type(v1, expected_text="float")
|
||||
|
||||
v2 = overload1("", 3.4)
|
||||
reveal_type(v2, expected_text="str")
|
||||
|
||||
v3 = overload1(a, 3.4)
|
||||
reveal_type(v3, expected_text="Unknown")
|
||||
|
||||
v4 = overload1("", a)
|
||||
reveal_type(v4, expected_text="str")
|
||||
|
||||
|
||||
@overload
|
||||
def overload2(x: int) -> Any:
|
||||
...
|
||||
|
||||
@overload
|
||||
def overload2(x: str) -> str:
|
||||
...
|
||||
|
||||
def overload2(x: str | int) -> Any | str:
|
||||
...
|
||||
|
||||
|
||||
def func2(a: Any):
|
||||
v1 = func1(1, 3.4)
|
||||
reveal_type(v1, expected_text="float")
|
||||
v1 = overload2("")
|
||||
reveal_type(v1, expected_text="str")
|
||||
|
||||
v2 = func1("", 3.4)
|
||||
v2 = overload2(3)
|
||||
reveal_type(v2, expected_text="Any")
|
||||
|
||||
v3 = overload2(a)
|
||||
reveal_type(v3, expected_text="Any")
|
||||
|
||||
@overload
|
||||
def overload3(x: LiteralString) -> LiteralString:
|
||||
...
|
||||
|
||||
@overload
|
||||
def overload3(x: str) -> str:
|
||||
...
|
||||
|
||||
def overload3(x: str) -> str:
|
||||
...
|
||||
|
||||
|
||||
def func3(a: Any, b: str):
|
||||
v1 = overload3("")
|
||||
reveal_type(v1, expected_text="LiteralString")
|
||||
|
||||
v2 = overload3(b)
|
||||
reveal_type(v2, expected_text="str")
|
||||
|
||||
v3 = func1(a, 3.4)
|
||||
reveal_type(v3, expected_text="Unknown")
|
||||
|
||||
v4 = func1("", a)
|
||||
reveal_type(v4, expected_text="str")
|
||||
v3 = overload3(a)
|
||||
reveal_type(v3, expected_text="str")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user