Support exhaustive when
This commit is contained in:
committed by
Dmitry Petrov
parent
a0d9d24c1f
commit
0b45655b7b
@@ -41,7 +41,7 @@ import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil;
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptorBase;
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinsPackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature;
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
@@ -197,8 +197,8 @@ public class KotlinTypeMapper {
|
||||
if (facadeFqName != null) return facadeFqName;
|
||||
}
|
||||
|
||||
if (descriptor instanceof IrBuiltinOperatorDescriptorBase) {
|
||||
return "intrinsic";
|
||||
if (descriptor.getContainingDeclaration() instanceof IrBuiltinsPackageFragmentDescriptor) {
|
||||
return descriptor.getContainingDeclaration().getName().asString();
|
||||
}
|
||||
|
||||
throw new RuntimeException("Could not find package member for " + descriptor +
|
||||
|
||||
+1
@@ -37,6 +37,7 @@ class IrIntrinsicMethods(irBuiltIns: IrBuiltIns) {
|
||||
irMapping.put(irBuiltIns.gt0, compare)
|
||||
irMapping.put(irBuiltIns.gteq0, compare)
|
||||
irMapping.put(irBuiltIns.enumValueOf, IrEnumValueOf())
|
||||
irMapping.put(irBuiltIns.noWhenBranchMatchedException, IrNoWhenBranchMatchedException())
|
||||
}
|
||||
|
||||
fun getIntrinsic(descriptor: CallableMemberDescriptor): IntrinsicMethod? {
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.genThrow
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
|
||||
class IrNoWhenBranchMatchedException : IntrinsicMethod() {
|
||||
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
|
||||
return IrIntrinsicFunction.create(expression, signature, context) {
|
||||
genThrow(it, "kotlin/NoWhenBranchMatchedException", null)
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.generators
|
||||
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
@@ -108,10 +109,25 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
|
||||
val irBranchResult = statementGenerator.generateExpression(ktEntry.expression!!)
|
||||
irWhen.branches.add(IrBranchImpl(irBranchCondition!!, irBranchResult))
|
||||
}
|
||||
addElseBranchForExhaustiveWhenIfNeeded(irWhen, expression)
|
||||
|
||||
return generateWhenBody(expression, irSubject, irWhen)
|
||||
}
|
||||
|
||||
private fun addElseBranchForExhaustiveWhenIfNeeded(irWhen: IrWhen, whenExpression: KtWhenExpression) {
|
||||
if (irWhen.branches.filterIsInstance<IrElseBranch>().isEmpty()) {
|
||||
val bindingContext = context.bindingContext
|
||||
//TODO: check condition: seems it's safe to always generate exception
|
||||
val isExhaustive = java.lang.Boolean.TRUE == bindingContext.get(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, whenExpression) ||
|
||||
java.lang.Boolean.TRUE == bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, whenExpression)
|
||||
|
||||
if (isExhaustive) {
|
||||
val call = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.noWhenBranchMatchedException)
|
||||
irWhen.branches.add(IrBranchImpl.elseBranch(call))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateWhenBody(expression: KtWhenExpression, irSubject: IrVariable?, irWhen: IrWhen): IrExpression {
|
||||
if (irSubject == null) {
|
||||
if (irWhen.branches.isEmpty())
|
||||
|
||||
@@ -82,6 +82,19 @@ class IrBuiltIns(val builtIns: KotlinBuiltIns) {
|
||||
initialize(null, null, listOf(typeParameterT), listOf(valueParameterName), returnType, Modality.FINAL, Visibilities.PUBLIC)
|
||||
}
|
||||
|
||||
val noWhenBranchMatchedException: FunctionDescriptor =
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
packageFragment,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("noWhenBranchMatchedException"),
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE
|
||||
).apply {
|
||||
val returnType = KotlinTypeFactory.simpleType(Annotations.EMPTY, builtIns.unit.typeConstructor, listOf(), false)
|
||||
|
||||
initialize(null, null, listOf(), listOf(), returnType, Modality.FINAL, Visibilities.PUBLIC)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val KOTLIN_INTERNAL_IR_FQN = FqName("kotlin.internal.ir")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user