Implicit exhaustive whens now have exception in else branch #KT-8700 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
011a9f23b9
commit
7d6ccc40c2
@@ -3801,8 +3801,9 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
return StackValue.operation(resultType, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
SwitchCodegen switchCodegen =
|
||||
SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible(expression, isStatement, ExpressionCodegen.this);
|
||||
SwitchCodegen switchCodegen = SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible(
|
||||
expression, isStatement, isExhaustive(expression, isStatement), ExpressionCodegen.this
|
||||
);
|
||||
if (switchCodegen != null) {
|
||||
switchCodegen.generate();
|
||||
return Unit.INSTANCE;
|
||||
@@ -3848,9 +3849,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
}
|
||||
if (!hasElse && nextCondition != null) {
|
||||
v.mark(nextCondition);
|
||||
if (!isStatement) {
|
||||
putUnitInstanceOntoStackForNonExhaustiveWhen(expression);
|
||||
}
|
||||
putUnitInstanceOntoStackForNonExhaustiveWhen(expression, isStatement);
|
||||
}
|
||||
|
||||
markLineNumber(expression, isStatement);
|
||||
@@ -3863,14 +3862,24 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isExhaustive(@NotNull KtWhenExpression whenExpression, boolean isStatement) {
|
||||
if (isStatement) {
|
||||
return Boolean.TRUE.equals(bindingContext.get(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, whenExpression));
|
||||
}
|
||||
else {
|
||||
return Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, whenExpression));
|
||||
}
|
||||
}
|
||||
|
||||
public void putUnitInstanceOntoStackForNonExhaustiveWhen(
|
||||
@NotNull KtWhenExpression expression
|
||||
@NotNull KtWhenExpression whenExpression,
|
||||
boolean isStatement
|
||||
) {
|
||||
if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) {
|
||||
if (isExhaustive(whenExpression, isStatement)) {
|
||||
// when() is supposed to be exhaustive
|
||||
genThrow(v, "kotlin/NoWhenBranchMatchedException", null);
|
||||
}
|
||||
else {
|
||||
else if (!isStatement) {
|
||||
// non-exhaustive when() with no else -> Unit must be expected
|
||||
StackValue.putUnitInstance(v);
|
||||
}
|
||||
|
||||
@@ -30,10 +30,11 @@ public class EnumSwitchCodegen extends SwitchCodegen {
|
||||
public EnumSwitchCodegen(
|
||||
@NotNull KtWhenExpression expression,
|
||||
boolean isStatement,
|
||||
boolean isExhaustive,
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull WhenByEnumsMapping mapping
|
||||
) {
|
||||
super(expression, isStatement, codegen);
|
||||
super(expression, isStatement, isExhaustive, codegen);
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -26,9 +26,10 @@ public class IntegralConstantsSwitchCodegen extends SwitchCodegen {
|
||||
public IntegralConstantsSwitchCodegen(
|
||||
@NotNull KtWhenExpression expression,
|
||||
boolean isStatement,
|
||||
boolean isExhaustive,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
super(expression, isStatement, codegen);
|
||||
super(expression, isStatement, isExhaustive, codegen);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,9 +40,10 @@ public class StringSwitchCodegen extends SwitchCodegen {
|
||||
public StringSwitchCodegen(
|
||||
@NotNull KtWhenExpression expression,
|
||||
boolean isStatement,
|
||||
boolean isExhaustive,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
super(expression, isStatement, codegen);
|
||||
super(expression, isStatement, isExhaustive, codegen);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.util.*;
|
||||
abstract public class SwitchCodegen {
|
||||
protected final KtWhenExpression expression;
|
||||
protected final boolean isStatement;
|
||||
protected final boolean isExhaustive;
|
||||
protected final ExpressionCodegen codegen;
|
||||
protected final BindingContext bindingContext;
|
||||
protected final Type subjectType;
|
||||
@@ -49,10 +50,11 @@ abstract public class SwitchCodegen {
|
||||
|
||||
public SwitchCodegen(
|
||||
@NotNull KtWhenExpression expression, boolean isStatement,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
boolean isExhaustive, @NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
this.expression = expression;
|
||||
this.isStatement = isStatement;
|
||||
this.isExhaustive = isExhaustive;
|
||||
this.codegen = codegen;
|
||||
this.bindingContext = codegen.getBindingContext();
|
||||
|
||||
@@ -70,7 +72,7 @@ abstract public class SwitchCodegen {
|
||||
boolean hasElse = expression.getElseExpression() != null;
|
||||
|
||||
// if there is no else-entry and it's statement then default --- endLabel
|
||||
defaultLabel = (hasElse || !isStatement) ? elseLabel : endLabel;
|
||||
defaultLabel = (hasElse || !isStatement || isExhaustive) ? elseLabel : endLabel;
|
||||
|
||||
generateSubject();
|
||||
|
||||
@@ -79,9 +81,9 @@ abstract public class SwitchCodegen {
|
||||
generateEntries();
|
||||
|
||||
// there is no else-entry but this is not statement, so we should return Unit
|
||||
if (!hasElse && !isStatement) {
|
||||
if (!hasElse && (!isStatement || isExhaustive)) {
|
||||
v.visitLabel(elseLabel);
|
||||
codegen.putUnitInstanceOntoStackForNonExhaustiveWhen(expression);
|
||||
codegen.putUnitInstanceOntoStackForNonExhaustiveWhen(expression, isStatement);
|
||||
}
|
||||
|
||||
codegen.markLineNumber(expression, isStatement);
|
||||
|
||||
@@ -102,6 +102,7 @@ public class SwitchCodegenUtil {
|
||||
public static SwitchCodegen buildAppropriateSwitchCodegenIfPossible(
|
||||
@NotNull KtWhenExpression expression,
|
||||
boolean isStatement,
|
||||
boolean isExhaustive,
|
||||
@NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
BindingContext bindingContext = codegen.getBindingContext();
|
||||
@@ -114,15 +115,15 @@ public class SwitchCodegenUtil {
|
||||
WhenByEnumsMapping mapping = codegen.getBindingContext().get(CodegenBinding.MAPPING_FOR_WHEN_BY_ENUM, expression);
|
||||
|
||||
if (mapping != null) {
|
||||
return new EnumSwitchCodegen(expression, isStatement, codegen, mapping);
|
||||
return new EnumSwitchCodegen(expression, isStatement, isExhaustive, codegen, mapping);
|
||||
}
|
||||
|
||||
if (isIntegralConstantsSwitch(expression, subjectType, bindingContext)) {
|
||||
return new IntegralConstantsSwitchCodegen(expression, isStatement, codegen);
|
||||
return new IntegralConstantsSwitchCodegen(expression, isStatement, isExhaustive, codegen);
|
||||
}
|
||||
|
||||
if (isStringConstantsSwitch(expression, subjectType, bindingContext)) {
|
||||
return new StringSwitchCodegen(expression, isStatement, codegen);
|
||||
return new StringSwitchCodegen(expression, isStatement, isExhaustive, codegen);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user