Call factory method for primary constructors of inner classes

We might want to add 'init' blocks later, so now, for the sake of
binary compatibility with 1.3-RC binaries, we have to generate these
'constructor' calls.

Note that in some tests inline class boxing is no longer redundant,
because resulting value is passed to 'constructor' as an argument.
This commit is contained in:
Dmitry Petrov
2018-08-30 16:04:20 +03:00
parent b1016936b2
commit a2900282fd
13 changed files with 119 additions and 26 deletions
@@ -2180,11 +2180,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor descriptor = accessibleFunctionDescriptor(resolvedCall);
if (descriptor instanceof ConstructorDescriptor) {
if (InlineClassesUtilsKt.isInlineClass(descriptor.getContainingDeclaration()) && ((ConstructorDescriptor) descriptor).isPrimary()) {
// we do not call static function `constructor`, because it's empty
return generateInlineClassConstructorCall(expression);
}
return generateNewCall(expression, resolvedCall);
}
@@ -2197,24 +2192,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> 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
@@ -4215,8 +4192,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
private StackValue generateNewCall(@NotNull KtCallExpression expression, @NotNull ResolvedCall<?> resolvedCall) {
Type type = expressionType(expression);
if (type.getSort() == Type.ARRAY) {
//noinspection ConstantConditions
return generateNewArray(expression, bindingContext.getType(expression), resolvedCall);
KotlinType kotlinType = kotlinType(expression);
assert kotlinType != null : "No kotlinType for expression of type " + type + ": " + expression.getText();
if (KotlinBuiltIns.isArrayOrPrimitiveArray(kotlinType)) {
//noinspection ConstantConditions
return generateNewArray(expression, bindingContext.getType(expression), resolvedCall);
}
}
return generateConstructorCall(resolvedCall, type);
@@ -4250,7 +4231,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@NotNull
public StackValue generateConstructorCall(@NotNull ResolvedCall<?> resolvedCall, @NotNull Type objectType) {
return StackValue.functionCall(objectType, null, v -> {
return StackValue.functionCall(objectType, resolvedCall.getResultingDescriptor().getReturnType(), v -> {
ClassConstructorDescriptor constructor = getConstructorDescriptor(resolvedCall);
ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter();
ClassDescriptor containingDeclaration = constructor.getContainingDeclaration();
@@ -0,0 +1,24 @@
// !LANGUAGE: +InlineClasses
inline class Result<T>(val a: Any?)
fun box(): String {
val a = Result<Int>(1) // valueOf
val b = Result<String>("sample")
val c = Result<Result<Int>>(a)
val d = Result<Result<Int>>(Result<Int>(1)) // valueOf
if (a.a !is Int) throw AssertionError()
if (b.a !is String) throw AssertionError()
if (c.a !is Result<*>) throw AssertionError()
val ca = c.a as Result<*>
if (ca.a !is Int) throw AssertionError()
if (d.a !is Result<*>) throw AssertionError()
val da = d.a as Result<*>
if (da.a !is Int) throw AssertionError()
return "OK"
}
@@ -0,0 +1,20 @@
// !LANGUAGE: +InlineClasses
// WITH_RUNTIME
// IGNORE_BACKEND: JVM_IR
inline class Z(val x: Int) {
constructor(vararg ys: Long) : this(ys.size)
}
fun box(): String {
val z1 = Z(111)
if (z1.x != 111) throw AssertionError()
val z2 = Z()
if (z2.x != 0) throw AssertionError()
val z3 = Z(2222L)
if (z3.x != 1) throw AssertionError()
return "OK"
}
@@ -12,6 +12,7 @@ fun f() {
// @TestKt.class:
// 0 INVOKESTATIC UInt\$Erased.box
// 0 INVOKESTATIC UInt\.box
// 0 INVOKEVIRTUAL UInt.unbox
// 0 valueOf
// 0 intValue
@@ -16,6 +16,7 @@ fun test() {
// @TestKt.class:
// 0 INVOKESTATIC Result\$Erased.box
// 2 INVOKESTATIC Result\.box
// 0 INVOKEVIRTUAL Result.unbox
// 2 valueOf
@@ -0,0 +1,10 @@
// !LANGUAGE: +InlineClasses
// FILE: Z.kt
inline class Z(val x: Int)
// FILE: test.kt
fun testZ() = Z(42)
// @TestKt.class:
// 1 INVOKESTATIC Z\.constructor \(I\)I
@@ -27,6 +27,7 @@ fun test(asInt: Result<Int>, asString: Result<String>, asResult: Result<Result<I
// @TestKt.class:
// 0 INVOKESTATIC Result\$Erased.box
// 0 INVOKESTATIC Result\.box
// 3 INVOKEVIRTUAL Result.unbox
// 0 valueOf
@@ -11471,6 +11471,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithPrimitiveUnderlyingType.kt");
}
@TestMetadata("boxResultInlineClassOfConstructorCall.kt")
public void testBoxResultInlineClassOfConstructorCall() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxResultInlineClassOfConstructorCall.kt");
}
@TestMetadata("boxUnboxInlineClassesWithOperatorsGetSet.kt")
public void testBoxUnboxInlineClassesWithOperatorsGetSet() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxInlineClassesWithOperatorsGetSet.kt");
@@ -11761,6 +11766,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyOfInlineClass.kt");
}
@TestMetadata("secondaryConstructorWithVararg.kt")
public void testSecondaryConstructorWithVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorWithVararg.kt");
}
@TestMetadata("secondaryConstructorsInsideInlineClass.kt")
public void testSecondaryConstructorsInsideInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");
@@ -2158,6 +2158,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/propertySetterWithInlineClassTypeArgument.kt");
}
@TestMetadata("primaryConstructorCalledByInlineClass.kt")
public void testPrimaryConstructorCalledByInlineClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/primaryConstructorCalledByInlineClass.kt");
}
@TestMetadata("skipCallToUnderlyingValueOfInlineClass.kt")
public void testSkipCallToUnderlyingValueOfInlineClass() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/skipCallToUnderlyingValueOfInlineClass.kt");
@@ -11471,6 +11471,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithPrimitiveUnderlyingType.kt");
}
@TestMetadata("boxResultInlineClassOfConstructorCall.kt")
public void testBoxResultInlineClassOfConstructorCall() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxResultInlineClassOfConstructorCall.kt");
}
@TestMetadata("boxUnboxInlineClassesWithOperatorsGetSet.kt")
public void testBoxUnboxInlineClassesWithOperatorsGetSet() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxInlineClassesWithOperatorsGetSet.kt");
@@ -11761,6 +11766,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyOfInlineClass.kt");
}
@TestMetadata("secondaryConstructorWithVararg.kt")
public void testSecondaryConstructorWithVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorWithVararg.kt");
}
@TestMetadata("secondaryConstructorsInsideInlineClass.kt")
public void testSecondaryConstructorsInsideInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");
@@ -11471,6 +11471,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithPrimitiveUnderlyingType.kt");
}
@TestMetadata("boxResultInlineClassOfConstructorCall.kt")
public void testBoxResultInlineClassOfConstructorCall() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxResultInlineClassOfConstructorCall.kt");
}
@TestMetadata("boxUnboxInlineClassesWithOperatorsGetSet.kt")
public void testBoxUnboxInlineClassesWithOperatorsGetSet() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxInlineClassesWithOperatorsGetSet.kt");
@@ -11761,6 +11766,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyOfInlineClass.kt");
}
@TestMetadata("secondaryConstructorWithVararg.kt")
public void testSecondaryConstructorWithVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorWithVararg.kt");
}
@TestMetadata("secondaryConstructorsInsideInlineClass.kt")
public void testSecondaryConstructorsInsideInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");
@@ -10016,6 +10016,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithPrimitiveUnderlyingType.kt");
}
@TestMetadata("boxResultInlineClassOfConstructorCall.kt")
public void testBoxResultInlineClassOfConstructorCall() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxResultInlineClassOfConstructorCall.kt");
}
@TestMetadata("boxUnboxInlineClassesWithOperatorsGetSet.kt")
public void testBoxUnboxInlineClassesWithOperatorsGetSet() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxInlineClassesWithOperatorsGetSet.kt");
@@ -10296,6 +10301,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyOfInlineClass.kt");
}
@TestMetadata("secondaryConstructorWithVararg.kt")
public void testSecondaryConstructorWithVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorWithVararg.kt");
}
@TestMetadata("secondaryConstructorsInsideInlineClass.kt")
public void testSecondaryConstructorsInsideInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");
@@ -11081,6 +11081,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/boxNullableValueOfInlineClassWithPrimitiveUnderlyingType.kt");
}
@TestMetadata("boxResultInlineClassOfConstructorCall.kt")
public void testBoxResultInlineClassOfConstructorCall() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxResultInlineClassOfConstructorCall.kt");
}
@TestMetadata("boxUnboxInlineClassesWithOperatorsGetSet.kt")
public void testBoxUnboxInlineClassesWithOperatorsGetSet() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/boxUnboxInlineClassesWithOperatorsGetSet.kt");
@@ -11361,6 +11366,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/referToUnderlyingPropertyOfInlineClass.kt");
}
@TestMetadata("secondaryConstructorWithVararg.kt")
public void testSecondaryConstructorWithVararg() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorWithVararg.kt");
}
@TestMetadata("secondaryConstructorsInsideInlineClass.kt")
public void testSecondaryConstructorsInsideInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/secondaryConstructorsInsideInlineClass.kt");