diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index 5d88ede8299..a3251f5159c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -51,6 +51,7 @@ import java.util.Collections; import static org.jetbrains.kotlin.util.slicedMap.RewritePolicy.DO_NOTHING; import static org.jetbrains.kotlin.util.slicedMap.Slices.COMPILE_TIME_VALUE_REWRITE_POLICY; +import static org.jetbrains.kotlin.util.slicedMap.Slices.CONSERVATIVE_SET_INCLUSION_SEMANTICS; public interface BindingContext { BindingContext EMPTY = new BindingContext() { @@ -179,7 +180,7 @@ public interface BindingContext { WritableSlice PROCESSED = Slices.createSimpleSlice(); // Please do not use this slice (USED_AS_EXPRESSION) directly, // use extension element.isUsedAsExpression() instead - WritableSlice USED_AS_EXPRESSION = Slices.createSimpleSetSlice(); + WritableSlice USED_AS_EXPRESSION = new BasicWritableSlice<>(CONSERVATIVE_SET_INCLUSION_SEMANTICS); WritableSlice USED_AS_RESULT_OF_LAMBDA = Slices.createSimpleSetSlice(); WritableSlice CAPTURED_IN_CLOSURE = new BasicWritableSlice<>(DO_NOTHING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/bindingContextUtil/BindingContextUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/bindingContextUtil/BindingContextUtils.kt index 6a24b78e4f0..b3e15cbbbaf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/bindingContextUtil/BindingContextUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/bindingContextUtil/BindingContextUtils.kt @@ -57,11 +57,7 @@ fun KtReturnExpression.getTargetFunction(context: BindingContext): KtCallableDec } fun KtExpression.isUsedAsExpression(context: BindingContext): Boolean = - context[USED_AS_EXPRESSION, this] - ?: throw AssertionError( - "BindingContext returned null for Boolean slice: " + - if (context == EMPTY) "BindingContext.EMPTY" else context.javaClass.toString() - ) + context[USED_AS_EXPRESSION, this] ?: false fun KtExpression.isUsedAsResultOfLambda(context: BindingContext): Boolean = context[USED_AS_RESULT_OF_LAMBDA, this]!! fun KtExpression.isUsedAsStatement(context: BindingContext): Boolean = !isUsedAsExpression(context) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/Slices.java b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/Slices.java index 494434aef08..4b7d8b99120 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/Slices.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/util/slicedMap/Slices.java @@ -80,6 +80,24 @@ public class Slices { } }; + // For Boolean-valued slices modelling set-membership, this policy + // implements constructing a set by element-wise inclusion, conservatively: + // allow rewriting false->true but not true->false. + // + // Used in growing the set of `USED_AS_EXPRESSION` in CFG analysis. + public static final RewritePolicy CONSERVATIVE_SET_INCLUSION_SEMANTICS = new RewritePolicy() { + @Override + public boolean rewriteProcessingNeeded(K key) { + return true; + } + + @Override + public boolean processRewrite(WritableSlice slice, K key, V oldValue, V newValue) { + assert (newValue instanceof Boolean); + return (Boolean)newValue; + } + }; + private Slices() { } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt index da3dbbde25c..ab11928b8fa 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi2ir.deparenthesize import org.jetbrains.kotlin.psi2ir.intermediate.loadAt import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.utils.SmartList class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { @@ -142,7 +143,7 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta } private fun addElseBranchForExhaustiveWhenIfNeeded(irWhen: IrWhen, whenExpression: KtWhenExpression) { - val isUsedAsExpression = true == get(BindingContext.USED_AS_EXPRESSION, whenExpression) + val isUsedAsExpression = whenExpression.isUsedAsExpression(context.bindingContext) val isImplicitElseRequired = if (isUsedAsExpression) true == get(BindingContext.EXHAUSTIVE_WHEN, whenExpression)