Discard TypeEvaluator if cancellation leaves partially-constructed function type in cache (#8118)

This commit is contained in:
Erik De Bonte 2024-06-11 15:02:36 -07:00 committed by GitHub
parent 8e1797cca7
commit 807b160a39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -14330,6 +14330,7 @@ export function createTypeEvaluator(
let functionType = FunctionType.createInstance('', '', '', FunctionTypeFlags.PartiallyEvaluated);
functionType.details.typeVarScopeId = ParseTreeUtils.getScopeIdForNode(node);
try {
// Pre-cache the incomplete function type in case the evaluation of the
// lambda depends on itself.
writeTypeCache(node, { type: functionType, isIncomplete: true }, EvaluatorFlags.None);
@ -14351,7 +14352,10 @@ export function createTypeEvaluator(
// If the parameter category matches and both of the parameters are
// either separators (/ or *) or not separators, copy the type
// from the expected parameter.
if (expectedParam.param.category === param.category && !param.name === !expectedParam.param.name) {
if (
expectedParam.param.category === param.category &&
!param.name === !expectedParam.param.name
) {
paramType = expectedParam.type;
} else {
sawParamMismatch = true;
@ -14458,7 +14462,12 @@ export function createTypeEvaluator(
if (requiresSpecialization(expectedReturnType)) {
const typeVarContext = new TypeVarContext(getTypeVarScopeId(functionType));
if (
assignType(expectedReturnType, returnTypeResult.type, /* diag */ undefined, typeVarContext)
assignType(
expectedReturnType,
returnTypeResult.type,
/* diag */ undefined,
typeVarContext
)
) {
functionType = applySolvedTypeVars(functionType, typeVarContext, {
applyInScopePlaceholders: true,
@ -14470,7 +14479,9 @@ export function createTypeEvaluator(
{
dependentType: inferenceContext?.expectedType,
allowDiagnostics:
!forceSpeculative && !isDiagnosticSuppressedForNode(node) && !inferenceContext?.isTypeIncomplete,
!forceSpeculative &&
!isDiagnosticSuppressedForNode(node) &&
!inferenceContext?.isTypeIncomplete,
}
);
@ -14483,6 +14494,15 @@ export function createTypeEvaluator(
}
return { type: functionType, isIncomplete, typeErrors };
} catch (e) {
if (OperationCanceledException.is(e)) {
// If the work was canceled before the function type was updated, the
// function type in the type cache is in an invalid, partially-constructed state.
e.isTypeCacheInvalid = true;
}
throw e;
}
}
function getTypeOfComprehension(
@ -17868,6 +17888,7 @@ export function createTypeEvaluator(
setSymbolResolutionPartialType(functionSymbol.symbol, functionDecl, functionType);
}
try {
writeTypeCache(node.name, { type: functionType }, /* flags */ undefined);
// Is this an "__init__" method within a pseudo-generic class? If so,
@ -17950,7 +17971,10 @@ export function createTypeEvaluator(
paramTypeNode = param.typeAnnotationComment;
} else if (node.functionAnnotationComment && !node.functionAnnotationComment.isParamListEllipsis) {
const adjustedIndex = index - firstCommentAnnotationIndex;
if (adjustedIndex >= 0 && adjustedIndex < node.functionAnnotationComment.paramTypeAnnotations.length) {
if (
adjustedIndex >= 0 &&
adjustedIndex < node.functionAnnotationComment.paramTypeAnnotations.length
) {
paramTypeNode = node.functionAnnotationComment.paramTypeAnnotations[adjustedIndex];
}
}
@ -18092,7 +18116,12 @@ export function createTypeEvaluator(
let isTypeInferred = false;
if (!paramTypeNode) {
isTypeInferred = true;
const inferredType = inferParameterType(node, functionType.details.flags, index, containingClassType);
const inferredType = inferParameterType(
node,
functionType.details.flags,
index,
containingClassType
);
if (inferredType) {
paramType = inferredType;
}
@ -18246,6 +18275,15 @@ export function createTypeEvaluator(
writeTypeCache(node.name, { type: functionType }, EvaluatorFlags.None);
return functionType;
} catch (e) {
if (OperationCanceledException.is(e)) {
// If the work was canceled before the function type was updated, the
// function type in the type cache is in an invalid, partially-constructed state.
e.isTypeCacheInvalid = true;
}
throw e;
}
}
function markParamAccessed(param: ParameterNode) {