Fix too aggressive data-flow clearing of loop-assigned vars
This is effectively a revert of
447c127036, which was an (incorrect) fix
for KT-22379.
The bug was that we've cleared data-flow info for assigned variables
*after* knowledge that loop condition if 'false' was applied (we can
claim that if loop has no jump-outs). Therefore, we broke smartcasts in
the innocent code like that:
var x: Int? = null
while (x == null) {
x = readPotentiallyNullableInt()
}
// x should be non-null here
Commit reverts that "fix" for 1.3.0 and postpones deprecation until 1.4
KT-22379 Open
KT-27084 Fixed
This commit is contained in:
+2
-14
@@ -286,16 +286,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo(),
|
dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo(),
|
||||||
components.languageVersionSettings));
|
components.languageVersionSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFlowInfo conservativeInfoAfterLoop =
|
|
||||||
components.languageVersionSettings.supportsFeature(LanguageFeature.SoundSmartcastFromLoopConditionForLoopAssignedVariables)
|
|
||||||
? loopVisitor.clearDataFlowInfoForAssignedLocalVariables(dataFlowInfo, components.languageVersionSettings)
|
|
||||||
: dataFlowInfo;
|
|
||||||
|
|
||||||
|
|
||||||
return components.dataFlowAnalyzer
|
return components.dataFlowAnalyzer
|
||||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||||
.replaceDataFlowInfo(conservativeInfoAfterLoop);
|
.replaceDataFlowInfo(dataFlowInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean containsJumpOutOfLoop(@NotNull KtExpression expression, ExpressionTypingContext context) {
|
private boolean containsJumpOutOfLoop(@NotNull KtExpression expression, ExpressionTypingContext context) {
|
||||||
@@ -466,14 +459,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
bodyTypeInfo = loopRangeInfo;
|
bodyTypeInfo = loopRangeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFlowInfo conservativeInfoAfterLoop =
|
|
||||||
components.languageVersionSettings.supportsFeature(LanguageFeature.SoundSmartcastFromLoopConditionForLoopAssignedVariables)
|
|
||||||
? loopVisitor.clearDataFlowInfoForAssignedLocalVariables(loopRangeInfo.getDataFlowInfo(), components.languageVersionSettings)
|
|
||||||
: loopRangeInfo.getDataFlowInfo();
|
|
||||||
|
|
||||||
return components.dataFlowAnalyzer
|
return components.dataFlowAnalyzer
|
||||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||||
.replaceDataFlowInfo(conservativeInfoAfterLoop);
|
.replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
private VariableDescriptor createLoopParameterDescriptor(
|
private VariableDescriptor createLoopParameterDescriptor(
|
||||||
|
|||||||
+1
-1
@@ -5,5 +5,5 @@ fun main(args: Array<String>) {
|
|||||||
if (i == 10) result = "non null"
|
if (i == 10) result = "non null"
|
||||||
else i++
|
else i++
|
||||||
}
|
}
|
||||||
result<!UNSAFE_CALL!>.<!>length
|
<!DEBUG_INFO_SMARTCAST!>result<!>.length
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,6 @@ enum class LanguageFeature(
|
|||||||
NormalizeConstructorCalls(KOTLIN_1_3),
|
NormalizeConstructorCalls(KOTLIN_1_3),
|
||||||
StrictJavaNullabilityAssertions(KOTLIN_1_3, kind = BUG_FIX),
|
StrictJavaNullabilityAssertions(KOTLIN_1_3, kind = BUG_FIX),
|
||||||
SoundSmartcastForEnumEntries(KOTLIN_1_3, kind = BUG_FIX),
|
SoundSmartcastForEnumEntries(KOTLIN_1_3, kind = BUG_FIX),
|
||||||
SoundSmartcastFromLoopConditionForLoopAssignedVariables(KOTLIN_1_3, kind = BUG_FIX),
|
|
||||||
DslMarkerOnFunctionTypeReceiver(KOTLIN_1_4, kind = BUG_FIX),
|
DslMarkerOnFunctionTypeReceiver(KOTLIN_1_4, kind = BUG_FIX),
|
||||||
ProhibitErroneousExpressionsInAnnotationsWithUseSiteTargets(KOTLIN_1_3, kind = BUG_FIX),
|
ProhibitErroneousExpressionsInAnnotationsWithUseSiteTargets(KOTLIN_1_3, kind = BUG_FIX),
|
||||||
NewCapturedReceiverFieldNamingConvention(KOTLIN_1_3, kind = BUG_FIX),
|
NewCapturedReceiverFieldNamingConvention(KOTLIN_1_3, kind = BUG_FIX),
|
||||||
@@ -94,6 +93,8 @@ enum class LanguageFeature(
|
|||||||
NoConstantValueAttributeForNonConstVals(KOTLIN_1_4, kind = BUG_FIX),
|
NoConstantValueAttributeForNonConstVals(KOTLIN_1_4, kind = BUG_FIX),
|
||||||
|
|
||||||
ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX),
|
ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX),
|
||||||
|
// Temporarily disabled, see KT-27084/KT-22379
|
||||||
|
SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX),
|
||||||
|
|
||||||
ProperIeee754Comparisons(sinceVersion = null, defaultState = State.DISABLED, kind = BUG_FIX),
|
ProperIeee754Comparisons(sinceVersion = null, defaultState = State.DISABLED, kind = BUG_FIX),
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user