mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-27 11:18:42 +03:00
Fixed bug that caused Callable type not to be assignable to generic Type[_T] parameter.
This commit is contained in:
parent
532b3783e7
commit
8b6c825fec
@ -322,33 +322,24 @@ export function canAssignType(destType: Type, srcType: Type, diag: DiagnosticAdd
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srcType.category === TypeCategory.Class) {
|
// Is the src a specialized "Type" object?
|
||||||
if (destType.category === TypeCategory.Object) {
|
if (srcType.category === TypeCategory.Object &&
|
||||||
const destClassType = destType.classType;
|
ClassType.isBuiltIn(srcType.classType, 'Type')) {
|
||||||
if (ClassType.isBuiltIn(destClassType)) {
|
|
||||||
// Is the dest a generic "type" object?
|
|
||||||
const destClassName = ClassType.getClassName(destClassType);
|
|
||||||
if (destClassName === 'type') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (destClassName === 'Type') {
|
const srcTypeArgs = ClassType.getTypeArguments(srcType.classType);
|
||||||
const destTypeArgs = ClassType.getTypeArguments(destClassType);
|
if (srcTypeArgs && srcTypeArgs.length >= 1) {
|
||||||
if (destTypeArgs && destTypeArgs.length >= 1) {
|
if (isAnyOrUnknown(srcTypeArgs[0])) {
|
||||||
return canAssignType(destTypeArgs[0],
|
return true;
|
||||||
ObjectType.create(srcType), diag.createAddendum(), typeVarMap,
|
} else if (srcTypeArgs[0].category === TypeCategory.Object) {
|
||||||
flags, recursionCount + 1);
|
return canAssignType(destType,
|
||||||
}
|
srcTypeArgs[0].classType, diag.createAddendum(), typeVarMap,
|
||||||
}
|
flags, recursionCount + 1);
|
||||||
|
|
||||||
// All classes derive from object.
|
|
||||||
if (destClassName === 'object') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (destType.category === TypeCategory.Class) {
|
if (destType.category === TypeCategory.Class) {
|
||||||
|
if (srcType.category === TypeCategory.Class) {
|
||||||
return _canAssignClass(destType, srcType, diag,
|
return _canAssignClass(destType, srcType, diag,
|
||||||
typeVarMap, flags, recursionCount + 1, false);
|
typeVarMap, flags, recursionCount + 1, false);
|
||||||
}
|
}
|
||||||
@ -357,13 +348,49 @@ export function canAssignType(destType: Type, srcType: Type, diag: DiagnosticAdd
|
|||||||
if (destType.category === TypeCategory.Object) {
|
if (destType.category === TypeCategory.Object) {
|
||||||
const destClassType = destType.classType;
|
const destClassType = destType.classType;
|
||||||
|
|
||||||
|
// Is the dest a generic "type" object?
|
||||||
|
if (ClassType.isBuiltIn(destClassType, 'type')) {
|
||||||
|
if (srcType.category === TypeCategory.Class ||
|
||||||
|
srcType.category === TypeCategory.Function ||
|
||||||
|
srcType.category === TypeCategory.OverloadedFunction) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the dest a specialized "Type" object?
|
||||||
|
if (ClassType.isBuiltIn(destClassType, 'Type')) {
|
||||||
|
const destTypeArgs = ClassType.getTypeArguments(destClassType);
|
||||||
|
if (destTypeArgs && destTypeArgs.length >= 1) {
|
||||||
|
if (isAnyOrUnknown(destTypeArgs[0])) {
|
||||||
|
return true;
|
||||||
|
} else if (destTypeArgs[0].category === TypeCategory.Object) {
|
||||||
|
return canAssignType(destTypeArgs[0].classType,
|
||||||
|
srcType, diag.createAddendum(), typeVarMap,
|
||||||
|
flags, recursionCount + 1);
|
||||||
|
} else if (destTypeArgs[0].category === TypeCategory.TypeVar) {
|
||||||
|
if (srcType.category === TypeCategory.Class) {
|
||||||
|
return canAssignType(destTypeArgs[0],
|
||||||
|
ObjectType.create(srcType), diag.createAddendum(), typeVarMap,
|
||||||
|
flags, recursionCount + 1);
|
||||||
|
} else if (srcType.category === TypeCategory.Function ||
|
||||||
|
srcType.category === TypeCategory.OverloadedFunction) {
|
||||||
|
|
||||||
|
return canAssignType(destTypeArgs[0],
|
||||||
|
srcType, diag.createAddendum(), typeVarMap,
|
||||||
|
flags, recursionCount + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (srcType.category === TypeCategory.Object) {
|
if (srcType.category === TypeCategory.Object) {
|
||||||
const destLiteral = destType.literalValue;
|
const destLiteral = destType.literalValue;
|
||||||
if (destLiteral !== undefined) {
|
if (destLiteral !== undefined) {
|
||||||
const srcLiteral = srcType.literalValue;
|
const srcLiteral = srcType.literalValue;
|
||||||
if (srcLiteral !== destLiteral) {
|
if (srcLiteral !== destLiteral) {
|
||||||
diag.addMessage(`'${ srcLiteral ? printLiteralValue(srcType) : printType(srcType) }' ` +
|
diag.addMessage(`'${ srcLiteral ? printLiteralValue(srcType) : printType(srcType) }' ` +
|
||||||
`cannot be assigned to '${ printLiteralValue(destType) }'`);
|
`cannot be assigned to '${ printLiteralValue(destType) }'`);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -398,6 +425,11 @@ export function canAssignType(destType: Type, srcType: Type, diag: DiagnosticAdd
|
|||||||
if (ClassType.isBuiltIn(destClassType, 'ModuleType')) {
|
if (ClassType.isBuiltIn(destClassType, 'ModuleType')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} else if (srcType.category === TypeCategory.Class) {
|
||||||
|
// All classes are assignable to "object".
|
||||||
|
if (ClassType.isBuiltIn(destType.classType, 'object')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,6 +516,8 @@ export function canAssignType(destType: Type, srcType: Type, diag: DiagnosticAdd
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diag.addMessage(`'${ printType(srcType) }' ` +
|
||||||
|
`cannot be assigned to '${ printType(destType) }'`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
server/src/tests/samples/genericTypes3.py
Normal file
11
server/src/tests/samples/genericTypes3.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# This sample tests the ability for a Callable generic
|
||||||
|
# to be assigned to a Type[_T] parameter.
|
||||||
|
|
||||||
|
from typing import Callable, cast
|
||||||
|
|
||||||
|
FUNC = Callable[[int], int]
|
||||||
|
def foo(i: int) -> int:
|
||||||
|
return 42
|
||||||
|
|
||||||
|
bar = cast(FUNC, foo)
|
||||||
|
|
@ -622,6 +622,12 @@ test('GenericTypes2', () => {
|
|||||||
validateResults(analysisResults, 1);
|
validateResults(analysisResults, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('GenericTypes3', () => {
|
||||||
|
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes3.py']);
|
||||||
|
|
||||||
|
validateResults(analysisResults, 0);
|
||||||
|
});
|
||||||
|
|
||||||
test('TypedDict1', () => {
|
test('TypedDict1', () => {
|
||||||
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typedDict1.py']);
|
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typedDict1.py']);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user