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:
Dmitry Savvinov
2018-09-24 18:50:00 +03:00
parent 99454aa78d
commit 6065095e24
3 changed files with 5 additions and 16 deletions
@@ -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(
@@ -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),