diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 1c52e6479d8..fb258f8360d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2107,19 +2107,7 @@ public class ExpressionCodegen extends KtVisitor impleme if (descriptor instanceof ConstructorDescriptor) { if (InlineClassesUtilsKt.isInlineClass(descriptor.getContainingDeclaration())) { - KtValueArgument valueArgument = CollectionsKt.firstOrNull(expression.getValueArguments()); - if (valueArgument == null) return null; - - SimpleType inlineClassType = ((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(); - - Type underlyingType = typeMapper.mapType(inlineClassType); - KotlinType underlyingKotlinType = InlineClassesUtilsKt.unsubstitutedUnderlyingType(inlineClassType); - - StackValue argumentValue = gen(valueArgument.getArgumentExpression()); - - return StackValue.coercionValueForArgumentOfInlineClassConstructor( - argumentValue, underlyingType, inlineClassType, underlyingKotlinType - ); + return generateInlineClassConstructorCall(expression); } return generateNewCall(expression, resolvedCall); @@ -2134,6 +2122,24 @@ public class ExpressionCodegen extends KtVisitor impleme return invokeFunction(resolvedCall, receiver); } + private StackValue generateInlineClassConstructorCall(@NotNull KtCallExpression expression) { + KtValueArgument valueArgument = CollectionsKt.singleOrNull(expression.getValueArguments()); + assert valueArgument != null : "Inline class constructor call should have single argument"; + + KotlinType inlineClassType = kotlinType(expression); + assert inlineClassType != null && InlineClassesUtilsKt.isInlineClassType(inlineClassType) : + "Constructor call expression of inline class should have inline class type, but have: " + inlineClassType; + + Type underlyingType = typeMapper.mapType(inlineClassType); + KotlinType underlyingKotlinType = InlineClassesUtilsKt.unsubstitutedUnderlyingType(inlineClassType); + + StackValue argumentValue = gen(valueArgument.getArgumentExpression()); + + return StackValue.coercionValueForArgumentOfInlineClassConstructor( + argumentValue, underlyingType, inlineClassType, underlyingKotlinType + ); + } + @Override public StackValue visitCollectionLiteralExpression( @NotNull KtCollectionLiteralExpression expression, StackValue data diff --git a/compiler/testData/codegen/box/inlineClasses/checkUnboxingResultFromTypeVariable.kt b/compiler/testData/codegen/box/inlineClasses/checkUnboxingResultFromTypeVariable.kt index 6aac12ec4ed..355b5ce453e 100644 --- a/compiler/testData/codegen/box/inlineClasses/checkUnboxingResultFromTypeVariable.kt +++ b/compiler/testData/codegen/box/inlineClasses/checkUnboxingResultFromTypeVariable.kt @@ -4,20 +4,37 @@ inline class Result(val a: Any?) { fun typed(): T = a as T } +fun takeResult(r: Result) {} +fun takeResultOfInt(r: Result) {} +fun takeInt(i: Int) {} + + fun box(): String { val asInt = Result(19) val asString = Result("sample") val asResult = Result>(asInt) + val asResultCtor = Result>(Result(10)) + + takeResult(asInt) + takeResult(asString) + takeResult(asResult) + takeResult(asResultCtor) + + takeResultOfInt(asInt) + takeInt(asInt.typed()) val unboxedInt = asInt.typed() val unboxedString = asString.typed() val unboxedResult = asResult.typed() + val unboxedAsCtor = asResultCtor.typed() if (unboxedInt != 19) return "fail" if (unboxedString != "sample") return "fail" if (unboxedResult.typed() != 19) return "fail" + if (unboxedAsCtor.typed() != 10) return "fail" if (asResult.typed().typed() != 19) return "fail" + if (asResultCtor.typed().typed() != 10) return "fail" return "OK" } \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/boxResultInlineClassOfConstructorCall.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/boxResultInlineClassOfConstructorCall.kt new file mode 100644 index 00000000000..1da4603dc88 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/boxResultInlineClassOfConstructorCall.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +InlineClasses + +inline class Result(val a: Any?) + +fun test() { + val a = Result(1) // valueOf + val b = Result("sample") + + val c = Result>(a) // box + val d = Result>(Result(1)) // valueOf, box +} + +// 2 INVOKESTATIC Result\$Erased.box +// 0 INVOKEVIRTUAL Result.unbox + +// 2 valueOf +// 0 intValue diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 6b66bc38c1b..1e9b06f566f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -1959,6 +1959,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } + @TestMetadata("boxResultInlineClassOfConstructorCall.kt") + public void testBoxResultInlineClassOfConstructorCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/boxResultInlineClassOfConstructorCall.kt"); + doTest(fileName); + } + @TestMetadata("boxThisOfInlineClass.kt") public void testBoxThisOfInlineClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/boxThisOfInlineClass.kt");