Fixed a bug in the code flow engine that results in incorrect type evaluation in certain cases involving codependent variables in a loop. This addresses #7466. (#7945)

This commit is contained in:
Eric Traut 2024-05-17 10:09:18 -07:00 committed by GitHub
parent c345c561a0
commit 7724fce513
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 0 deletions

View File

@ -194,6 +194,26 @@ export function getCodeFlowEngine(
return flowNodeTypeCache;
}
// Determines whether any calls to getTypeFromCodeFlow are pending
// for an expression other than referenceKeyFilter. This is important in cases
// where the type of one expression depends on the type of another
// in a loop. If there are other pending evaluations, we will mark the
// current evaluation as incomplete and return back to the pending
// evaluation.
function isGetTypeFromCodeFlowPending(referenceKeyFilter: string | undefined): boolean {
if (!referenceKeyFilter) {
return false;
}
for (const [key, value] of flowNodeTypeCacheSet.entries()) {
if (key !== referenceKeyFilter && value.pendingNodes.size > 0) {
return true;
}
}
return false;
}
// This function has two primary modes. The first is used to determine
// the narrowed type of a reference expression based on code flow analysis.
// The second (when reference is undefined) is used to determine whether
@ -1063,6 +1083,7 @@ export function getCodeFlowEngine(
if (
sawIncomplete &&
!sawPending &&
!isGetTypeFromCodeFlowPending(referenceKeyWithSymbolId) &&
effectiveType &&
!isIncompleteUnknown(effectiveType) &&
!firstAntecedentTypeIsIncomplete

View File

@ -0,0 +1,14 @@
# This sample tests a case where there are dependencies between
# variables within a loop.
a = None
b = False
for _ in []:
if b > 0:
pass
if a:
reveal_type(a, expected_text="int")
c = int(a or 1)
a = c
c.is_integer()

View File

@ -449,6 +449,12 @@ test('Loop46', () => {
TestUtils.validateResults(analysisResults, 0);
});
test('Loop47', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop47.py']);
TestUtils.validateResults(analysisResults, 0);
});
test('ForLoop1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['forLoop1.py']);