Fix unsound smartcast from loop condition on assigned vars
^KT-22379 Fixed
This commit is contained in:
committed by
Dmitry Savvinov
parent
a7d706f693
commit
447c127036
+14
-2
@@ -286,9 +286,16 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
dataFlowInfo = dataFlowInfo.and(loopVisitor.clearDataFlowInfoForAssignedLocalVariables(bodyTypeInfo.getJumpFlowInfo(),
|
||||
components.languageVersionSettings));
|
||||
}
|
||||
|
||||
DataFlowInfo conservativeInfoAfterLoop =
|
||||
components.languageVersionSettings.supportsFeature(LanguageFeature.SoundSmartcastFromLoopConditionForLoopAssignedVariables)
|
||||
? loopVisitor.clearDataFlowInfoForAssignedLocalVariables(dataFlowInfo, components.languageVersionSettings)
|
||||
: dataFlowInfo;
|
||||
|
||||
|
||||
return components.dataFlowAnalyzer
|
||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||
.replaceDataFlowInfo(dataFlowInfo);
|
||||
.replaceDataFlowInfo(conservativeInfoAfterLoop);
|
||||
}
|
||||
|
||||
private boolean containsJumpOutOfLoop(@NotNull KtExpression expression, ExpressionTypingContext context) {
|
||||
@@ -459,9 +466,14 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
bodyTypeInfo = loopRangeInfo;
|
||||
}
|
||||
|
||||
DataFlowInfo conservativeInfoAfterLoop =
|
||||
components.languageVersionSettings.supportsFeature(LanguageFeature.SoundSmartcastFromLoopConditionForLoopAssignedVariables)
|
||||
? loopVisitor.clearDataFlowInfoForAssignedLocalVariables(loopRangeInfo.getDataFlowInfo(), components.languageVersionSettings)
|
||||
: loopRangeInfo.getDataFlowInfo();
|
||||
|
||||
return components.dataFlowAnalyzer
|
||||
.checkType(bodyTypeInfo.replaceType(components.builtIns.getUnitType()), expression, contextWithExpectedType)
|
||||
.replaceDataFlowInfo(loopRangeInfo.getDataFlowInfo());
|
||||
.replaceDataFlowInfo(conservativeInfoAfterLoop);
|
||||
}
|
||||
|
||||
private VariableDescriptor createLoopParameterDescriptor(
|
||||
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
// !LANGUAGE: +SoundSmartcastFromLoopConditionForLoopAssignedVariables
|
||||
|
||||
fun foo() {
|
||||
var x: String? = "123"
|
||||
while (x!!.length < 42) {
|
||||
x = null
|
||||
break
|
||||
|
||||
}
|
||||
x<!UNSAFE_CALL!>.<!>length // 'x' is unsoundly smartcasted here
|
||||
}
|
||||
|
||||
fun bar() {
|
||||
var x: List<Int>? = ArrayList<Int>(1)
|
||||
for (i in x!!) {
|
||||
x = null
|
||||
break
|
||||
|
||||
}
|
||||
x<!UNSAFE_CALL!>.<!>size // 'x' is unsoundly smartcasted here
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun bar(): kotlin.Unit
|
||||
public fun foo(): kotlin.Unit
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
// !LANGUAGE: -SoundSmartcastFromLoopConditionForLoopAssignedVariables
|
||||
|
||||
fun foo() {
|
||||
var x: String? = "123"
|
||||
while (x!!.length < 42) {
|
||||
x = null
|
||||
break
|
||||
|
||||
}
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length // 'x' is unsoundly smartcasted here
|
||||
}
|
||||
|
||||
fun bar() {
|
||||
var x: List<Int>? = ArrayList<Int>(1)
|
||||
for (i in x!!) {
|
||||
x = null
|
||||
break
|
||||
|
||||
}
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.size // 'x' is unsoundly smartcasted here
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun bar(): kotlin.Unit
|
||||
public fun foo(): kotlin.Unit
|
||||
@@ -19822,6 +19822,16 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
public void testWhileTrueWithBreakInIfCondition() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/loops/WhileTrueWithBreakInIfCondition.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("whileWithAssertInConditionAndBreakAfter.kt")
|
||||
public void testWhileWithAssertInConditionAndBreakAfter() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/loops/whileWithAssertInConditionAndBreakAfter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("whileWithAssertInConditionAndBreakBefore.kt")
|
||||
public void testWhileWithAssertInConditionAndBreakBefore() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/loops/whileWithAssertInConditionAndBreakBefore.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/smartCasts/objectLiterals")
|
||||
|
||||
Generated
+10
@@ -19822,6 +19822,16 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
public void testWhileTrueWithBreakInIfCondition() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/loops/WhileTrueWithBreakInIfCondition.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("whileWithAssertInConditionAndBreakAfter.kt")
|
||||
public void testWhileWithAssertInConditionAndBreakAfter() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/loops/whileWithAssertInConditionAndBreakAfter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("whileWithAssertInConditionAndBreakBefore.kt")
|
||||
public void testWhileWithAssertInConditionAndBreakBefore() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/smartCasts/loops/whileWithAssertInConditionAndBreakBefore.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/smartCasts/objectLiterals")
|
||||
|
||||
@@ -85,6 +85,7 @@ enum class LanguageFeature(
|
||||
NormalizeConstructorCalls(KOTLIN_1_3),
|
||||
StrictJavaNullabilityAssertions(KOTLIN_1_3, kind = BUG_FIX),
|
||||
SoundSmartcastForEnumEntries(KOTLIN_1_3, kind = BUG_FIX),
|
||||
SoundSmartcastFromLoopConditionForLoopAssignedVariables(KOTLIN_1_3, kind = BUG_FIX),
|
||||
|
||||
RestrictReturnStatementTarget(KOTLIN_1_4, kind = BUG_FIX),
|
||||
ProperIeee754Comparisons(sinceVersion = null, defaultState = State.DISABLED, kind = BUG_FIX),
|
||||
|
||||
Reference in New Issue
Block a user