diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index 1ddaa3bdd85..74d69a739c9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -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 + diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt index 4c091454ff5..0c51c712535 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt @@ -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? { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrNoWhenBranchMatchedException.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrNoWhenBranchMatchedException.kt new file mode 100644 index 00000000000..767649141e2 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrNoWhenBranchMatchedException.kt @@ -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) + } + } +} \ No newline at end of file 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 85138f1dbaa..2f5a92c1ed8 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 @@ -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().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()) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt index 8dab89a96d5..369fbff858b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt @@ -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") }