Clear DF info for variables assigned in 'try' #KT-17929 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
0fd70df681
commit
adbece82ef
+13
-3
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
@@ -513,11 +514,20 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
|
|
||||||
KotlinTypeInfo tryResult = facade.getTypeInfo(tryBlock, context);
|
KotlinTypeInfo tryResult = facade.getTypeInfo(tryBlock, context);
|
||||||
|
ExpressionTypingContext tryOutputContext = context.replaceExpectedType(NO_EXPECTED_TYPE);
|
||||||
|
if (!nothingInAllCatchBranches &&
|
||||||
|
facade.getComponents().languageVersionSettings.supportsFeature(LanguageFeature.SoundSmartCastsAfterTry)) {
|
||||||
|
PreliminaryLoopVisitor tryVisitor = PreliminaryLoopVisitor.visitTryBlock(expression);
|
||||||
|
tryOutputContext = tryOutputContext.replaceDataFlowInfo(
|
||||||
|
tryVisitor.clearDataFlowInfoForAssignedLocalVariables(tryOutputContext.dataFlowInfo,
|
||||||
|
components.languageVersionSettings)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(tryOutputContext);
|
||||||
if (finallyBlock != null) {
|
if (finallyBlock != null) {
|
||||||
result = facade.getTypeInfo(finallyBlock.getFinalExpression(),
|
result = facade.getTypeInfo(finallyBlock.getFinalExpression(), tryOutputContext);
|
||||||
context.replaceExpectedType(NO_EXPECTED_TYPE));
|
|
||||||
}
|
}
|
||||||
else if (nothingInAllCatchBranches) {
|
else if (nothingInAllCatchBranches) {
|
||||||
result = tryResult;
|
result = tryResult;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.types.expressions
|
|||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtLoopExpression
|
import org.jetbrains.kotlin.psi.KtLoopExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtTryExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
||||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.IdentifierInfo
|
import org.jetbrains.kotlin.resolve.calls.smartcasts.IdentifierInfo
|
||||||
@@ -59,5 +60,12 @@ class PreliminaryLoopVisitor private constructor() : AssignedVariablesSearcher()
|
|||||||
loopExpression.accept(visitor, null)
|
loopExpression.accept(visitor, null)
|
||||||
return visitor
|
return visitor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun visitTryBlock(tryExpression: KtTryExpression): PreliminaryLoopVisitor {
|
||||||
|
val visitor = PreliminaryLoopVisitor()
|
||||||
|
tryExpression.tryBlock.accept(visitor, null)
|
||||||
|
return visitor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -1,3 +1,5 @@
|
|||||||
|
// !LANGUAGE: +SoundSmartCastsAfterTry
|
||||||
|
|
||||||
fun bar(arg: Any?) = arg
|
fun bar(arg: Any?) = arg
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
@@ -6,7 +8,7 @@ fun foo() {
|
|||||||
try {
|
try {
|
||||||
s = "Test"
|
s = "Test"
|
||||||
} catch (ex: Exception) {}
|
} catch (ex: Exception) {}
|
||||||
bar(<!DEBUG_INFO_CONSTANT!>s<!>)
|
bar(s)
|
||||||
if (<!SENSELESS_COMPARISON!><!DEBUG_INFO_CONSTANT!>s<!> != null<!>) { }
|
if (s != null) { }
|
||||||
<!DEBUG_INFO_CONSTANT!>s<!><!UNSAFE_CALL!>.<!>hashCode()
|
s<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
// !LANGUAGE: +SoundSmartCastsAfterTry
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
var s: String?
|
var s: String?
|
||||||
s = "Test"
|
s = "Test"
|
||||||
try {
|
try {
|
||||||
s = null
|
s = null
|
||||||
} catch (ex: Exception) {}
|
} catch (ex: Exception) {}
|
||||||
<!DEBUG_INFO_SMARTCAST!>s<!>.hashCode()
|
s<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
}
|
}
|
||||||
+3
-1
@@ -1,3 +1,5 @@
|
|||||||
|
// !LANGUAGE: +SoundSmartCastsAfterTry
|
||||||
|
|
||||||
fun bar() {}
|
fun bar() {}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
@@ -10,5 +12,5 @@ fun foo() {
|
|||||||
finally {
|
finally {
|
||||||
bar()
|
bar()
|
||||||
}
|
}
|
||||||
<!DEBUG_INFO_SMARTCAST!>s<!>.hashCode()
|
s<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
}
|
}
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
fun foo() {
|
||||||
|
var s: String?
|
||||||
|
s = "Test"
|
||||||
|
try {
|
||||||
|
s = null
|
||||||
|
} catch (ex: Exception) {}
|
||||||
|
<!DEBUG_INFO_SMARTCAST!>s<!>.hashCode()
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(): kotlin.Unit
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
|
// !LANGUAGE: +SoundSmartCastsAfterTry
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
var s: String?
|
var s: String?
|
||||||
s = "Test"
|
s = "Test"
|
||||||
try {
|
try {
|
||||||
s = "Other"
|
s = "Other"
|
||||||
} catch (ex: Exception) {}
|
} catch (ex: Exception) {}
|
||||||
<!DEBUG_INFO_SMARTCAST!>s<!>.hashCode()
|
// Problem: here we do not see that 's' is always not-null
|
||||||
|
s<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
}
|
}
|
||||||
@@ -21186,6 +21186,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("setNullInTryUnsound.kt")
|
||||||
|
public void testSetNullInTryUnsound() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/varnotnull/setNullInTryUnsound.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("setSameInTry.kt")
|
@TestMetadata("setSameInTry.kt")
|
||||||
public void testSetSameInTry() throws Exception {
|
public void testSetSameInTry() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/varnotnull/setSameInTry.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/varnotnull/setSameInTry.kt");
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ enum class LanguageFeature(
|
|||||||
|
|
||||||
ArrayLiteralsInAnnotations(KOTLIN_1_2),
|
ArrayLiteralsInAnnotations(KOTLIN_1_2),
|
||||||
InlineDefaultFunctionalParameters(KOTLIN_1_2),
|
InlineDefaultFunctionalParameters(KOTLIN_1_2),
|
||||||
|
SoundSmartCastsAfterTry(KOTLIN_1_2),
|
||||||
|
|
||||||
// Experimental features
|
// Experimental features
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user