DFA bug fix: assignment of unstable to stable uses predictable nullability (see test)
This commit is contained in:
+6
-6
@@ -145,7 +145,7 @@ import static org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
|
|||||||
public Set<KotlinType> getPossibleTypes(@NotNull DataFlowValue key) {
|
public Set<KotlinType> getPossibleTypes(@NotNull DataFlowValue key) {
|
||||||
KotlinType originalType = key.getType();
|
KotlinType originalType = key.getType();
|
||||||
Set<KotlinType> types = collectTypesFromMeAndParents(key);
|
Set<KotlinType> types = collectTypesFromMeAndParents(key);
|
||||||
if (getNullability(key).canBeNull()) {
|
if (getPredictableNullability(key).canBeNull()) {
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ import static org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
|
|||||||
@NotNull
|
@NotNull
|
||||||
public DataFlowInfo assign(@NotNull DataFlowValue a, @NotNull DataFlowValue b) {
|
public DataFlowInfo assign(@NotNull DataFlowValue a, @NotNull DataFlowValue b) {
|
||||||
Map<DataFlowValue, Nullability> nullability = Maps.newHashMap();
|
Map<DataFlowValue, Nullability> nullability = Maps.newHashMap();
|
||||||
Nullability nullabilityOfB = getNullability(b);
|
Nullability nullabilityOfB = getPredictableNullability(b);
|
||||||
putNullability(nullability, a, nullabilityOfB);
|
putNullability(nullability, a, nullabilityOfB);
|
||||||
|
|
||||||
SetMultimap<DataFlowValue, KotlinType> newTypeInfo = newTypeInfo();
|
SetMultimap<DataFlowValue, KotlinType> newTypeInfo = newTypeInfo();
|
||||||
@@ -208,8 +208,8 @@ import static org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
|
|||||||
@NotNull
|
@NotNull
|
||||||
public DataFlowInfo equate(@NotNull DataFlowValue a, @NotNull DataFlowValue b) {
|
public DataFlowInfo equate(@NotNull DataFlowValue a, @NotNull DataFlowValue b) {
|
||||||
Map<DataFlowValue, Nullability> builder = Maps.newHashMap();
|
Map<DataFlowValue, Nullability> builder = Maps.newHashMap();
|
||||||
Nullability nullabilityOfA = getNullability(a);
|
Nullability nullabilityOfA = getPredictableNullability(a);
|
||||||
Nullability nullabilityOfB = getNullability(b);
|
Nullability nullabilityOfB = getPredictableNullability(b);
|
||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
changed |= putNullability(builder, a, nullabilityOfA.refine(nullabilityOfB));
|
changed |= putNullability(builder, a, nullabilityOfA.refine(nullabilityOfB));
|
||||||
@@ -267,8 +267,8 @@ import static org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability.NOT_NULL
|
|||||||
@NotNull
|
@NotNull
|
||||||
public DataFlowInfo disequate(@NotNull DataFlowValue a, @NotNull DataFlowValue b) {
|
public DataFlowInfo disequate(@NotNull DataFlowValue a, @NotNull DataFlowValue b) {
|
||||||
Map<DataFlowValue, Nullability> builder = Maps.newHashMap();
|
Map<DataFlowValue, Nullability> builder = Maps.newHashMap();
|
||||||
Nullability nullabilityOfA = getNullability(a);
|
Nullability nullabilityOfA = getPredictableNullability(a);
|
||||||
Nullability nullabilityOfB = getNullability(b);
|
Nullability nullabilityOfB = getPredictableNullability(b);
|
||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
changed |= putNullability(builder, a, nullabilityOfA.refine(nullabilityOfB.invert()));
|
changed |= putNullability(builder, a, nullabilityOfA.refine(nullabilityOfB.invert()));
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
class Foo(var x: Int?) {
|
||||||
|
init {
|
||||||
|
if (x != null) {
|
||||||
|
val y = x
|
||||||
|
// Error: x is not stable, Type(y) = Int?
|
||||||
|
<!SMARTCAST_IMPOSSIBLE!>x<!>.hashCode()
|
||||||
|
y<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
|
if (y == x) {
|
||||||
|
// Still error
|
||||||
|
y<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
|
}
|
||||||
|
if (x == null && y != x) {
|
||||||
|
// Still error
|
||||||
|
y<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public final class Foo {
|
||||||
|
public constructor Foo(/*0*/ x: kotlin.Int?)
|
||||||
|
public final var x: kotlin.Int?
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -15060,6 +15060,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unstableToStable.kt")
|
||||||
|
public void testUnstableToStable() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/unstableToStable.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("varChangedInInitializer.kt")
|
@TestMetadata("varChangedInInitializer.kt")
|
||||||
public void testVarChangedInInitializer() throws Exception {
|
public void testVarChangedInInitializer() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/varChangedInInitializer.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/varChangedInInitializer.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user