mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-11 07:55:56 +03:00
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:
parent
c345c561a0
commit
7724fce513
@ -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
|
||||
|
14
packages/pyright-internal/src/tests/samples/loop47.py
Normal file
14
packages/pyright-internal/src/tests/samples/loop47.py
Normal 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()
|
@ -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']);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user