From 6c51666a852c92044a5b95b65d685877e5a84ea0 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 14 Mar 2019 11:06:21 +0700 Subject: [PATCH] DFA: better union of nullability states Union in merge procedure differs from normal union: in normal union it's ok to (NULLABLE | NOT_NULL) -> NULLABLE, but in merge we should produce FLUSHED --- .../intellij/codeInspection/dataFlow/DfaFactType.java | 10 +++++++--- .../codeInspection/dataFlow/DfaMemoryStateImpl.java | 10 +++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaFactType.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaFactType.java index 36da82871d02..87a04533b378 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaFactType.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaFactType.java @@ -73,10 +73,14 @@ public abstract class DfaFactType extends Key { if (left == right) { return left; } - if (left == DfaNullability.NULL || right == DfaNullability.NULL) { - return DfaNullability.UNKNOWN; + if (left == DfaNullability.NULL || right == DfaNullability.NULL || + left == DfaNullability.NULLABLE || right == DfaNullability.NULLABLE) { + return DfaNullability.NULLABLE; } - return DfaNullability.FLUSHED; + if (left == DfaNullability.FLUSHED || right == DfaNullability.FLUSHED) { + return DfaNullability.FLUSHED; + } + return DfaNullability.UNKNOWN; } @Nullable diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java index ef393415d6d4..da0cf067ea7a 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java @@ -1651,7 +1651,15 @@ public class DfaMemoryStateImpl implements DfaMemoryState { for (DfaVariableValue var : vars) { DfaVariableState state = getVariableState(var); DfaVariableState otherState = other.getVariableState(var); - setVariableState(var, state.withFacts(state.myFactMap.unite(otherState.myFactMap))); + DfaFactMap result = state.myFactMap.unite(otherState.myFactMap); + Nullability nullability = state.getNullability(); + Nullability otherNullability = otherState.getNullability(); + if (nullability != otherNullability && (nullability == Nullability.NULLABLE || otherNullability == Nullability.NULLABLE)) { + // When merging nullable with something we cannot warn about nullability violation anymore + // because we lose the information about coherent state, thus noise warnings could be produced + result = result.with(DfaFactType.NULLABILITY, DfaNullability.FLUSHED); + } + setVariableState(var, state.withFacts(result)); } }