Added special-case handling for type var matching of Optional[T].

This commit is contained in:
Eric Traut 2020-04-07 23:40:27 -07:00
parent 1a0d7027bf
commit 308f906200
3 changed files with 48 additions and 6 deletions

View File

@ -10906,12 +10906,20 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
let foundMatch = false;
// Run through all subtypes in the union. Don't stop at the first
// match we find because we may need to match TypeVars in other
// subtypes.
destType.subtypes.forEach((subtype) => {
if (canAssignType(subtype, srcType, diagAddendum, typeVarMap, flags, recursionCount + 1)) {
foundMatch = true;
}
});
// subtypes. We special-case "None" so we can handle Optional[T]
// without matching the None to the type var.
if (
srcType.category === TypeCategory.None &&
destType.subtypes.some((subtype) => subtype.category === TypeCategory.None)
) {
foundMatch = true;
} else {
destType.subtypes.forEach((subtype) => {
if (canAssignType(subtype, srcType, diagAddendum, typeVarMap, flags, recursionCount + 1)) {
foundMatch = true;
}
});
}
if (!foundMatch) {
diag.addAddendum(diagAddendum);

View File

@ -1066,6 +1066,12 @@ test('GenericTypes20', () => {
validateResults(analysisResults, 0);
});
test('GenericTypes21', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes21.py']);
validateResults(analysisResults, 1);
});
test('Protocol1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['protocol1.py']);

View File

@ -0,0 +1,28 @@
# This sample tests the special-case handling of Optional[T] within
# a function.
from typing import Optional, TypeVar
_T = TypeVar("T")
def foo1(v: Optional[_T]) -> _T:
if v is None:
raise ValueError
return v
def foo2(v: _T) -> _T:
if v is None:
raise ValueError
return v
f: Optional[int]
# This should not generate an error because type var _T
# should be matched to "int" rather than "Optional[int]".
a: int = foo1(f)
# This should generate an error because type var _T
# should be matched to "Optional[int]".
b: int = foo2(f)