From 8e8f83656f7ec6a42015d9d59105b474dcf84195 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Fri, 3 Mar 2017 14:30:08 +0300 Subject: [PATCH] KT-16618 `IMPLICIT_INTEGER_COERCION` isn't generated for global properties and default parameters --- .../transformations/InsertImplicitCasts.kt | 25 ++++++ .../ir/declarations/IrGeneralFunction.kt | 4 +- .../kotlin/ir/declarations/IrProperty.kt | 1 - .../ir/declarations/impl/IrFunctionBase.kt | 8 +- .../jetbrains/kotlin/ir/expressions/IrBody.kt | 3 + .../primitivesImplicitConversions.kt | 13 +++- .../primitivesImplicitConversions.txt | 78 +++++++++++++++++++ 7 files changed, 124 insertions(+), 8 deletions(-) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt index a77d9ab0d14..2ea107e947b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt @@ -18,6 +18,9 @@ package org.jetbrains.kotlin.psi2ir.transformations import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl @@ -122,6 +125,24 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformerVoi return declaration } + override fun visitField(declaration: IrField): IrStatement { + declaration.transformChildrenVoid(this) + + declaration.initializer?.coerce(declaration.descriptor.type) + + return declaration + } + + override fun visitFunction(declaration: IrFunction): IrStatement { + declaration.transformChildrenVoid(this) + + declaration.descriptor.valueParameters.forEach { + declaration.getDefault(it)?.coerce(it.type) + } + + return declaration + } + override fun visitWhen(expression: IrWhen): IrExpression { expression.transformChildrenVoid(this) @@ -184,6 +205,10 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformerVoi return expression } + private fun IrExpressionBody.coerce(expectedType: KotlinType) { + expression = expression.cast(expectedType) + } + private fun IrExpression.cast(expectedType: KotlinType?): IrExpression { if (expectedType == null) return this if (expectedType.isError) return this diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrGeneralFunction.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrGeneralFunction.kt index ebabc80287c..bb8236ab1b7 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrGeneralFunction.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrGeneralFunction.kt @@ -28,7 +28,7 @@ interface IrFunction : IrDeclaration { override val declarationKind: IrDeclarationKind get() = IrDeclarationKind.FUNCTION - fun putDefault(parameter: ValueParameterDescriptor, expressionBody: IrBody) - fun getDefault(parameter: ValueParameterDescriptor): IrBody? + fun putDefault(parameter: ValueParameterDescriptor, expressionBody: IrExpressionBody) + fun getDefault(parameter: ValueParameterDescriptor): IrExpressionBody? } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt index 76b23aea27f..d613e30b38d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.ir.declarations import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrExpressionBody interface IrProperty : IrDeclaration { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionBase.kt index 17b7a402276..53aa60feca3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrFunctionBase.kt @@ -19,7 +19,7 @@ package org.jetbrains.kotlin.ir.declarations.impl import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import java.util.* @@ -29,12 +29,12 @@ abstract class IrFunctionBase( endOffset: Int, origin: IrDeclarationOrigin ) : IrGeneralFunctionBase(startOffset, endOffset, origin), IrFunction { - private val defaults = LinkedHashMap() + private val defaults = LinkedHashMap() - override fun getDefault(parameter: ValueParameterDescriptor): IrBody? = + override fun getDefault(parameter: ValueParameterDescriptor): IrExpressionBody? = defaults[parameter] - override fun putDefault(parameter: ValueParameterDescriptor, expressionBody: IrBody) { + override fun putDefault(parameter: ValueParameterDescriptor, expressionBody: IrExpressionBody) { defaults[parameter] = expressionBody } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt index a2407e25d5f..e4de17893f6 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt @@ -26,6 +26,9 @@ interface IrBody : IrElement { interface IrExpressionBody : IrBody { var expression: IrExpression + + override fun transform(transformer: IrElementTransformer, data: D): IrExpressionBody = + accept(transformer, data) as IrExpressionBody } interface IrBlockBody : IrBody, IrStatementContainer diff --git a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.kt b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.kt index 37cfb06a536..577b9732d72 100644 --- a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.kt +++ b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.kt @@ -1,3 +1,10 @@ +val test1: Long = 42 +val test2: Short = 42 +val test3: Byte = 42 +val test4: Long = 42.unaryMinus() +val test5: Short = 42.unaryMinus() +val test6: Byte = 42.unaryMinus() + fun test() { val test1: Int? = 42 val test2: Long = 42 @@ -6,4 +13,8 @@ fun test() { val test5: Long? = 1.unaryMinus() val test6: Short? = 1.unaryMinus() val test7: Byte? = 1.unaryMinus() -} \ No newline at end of file +} + +fun testImplicitArguments(x: Long = 1.unaryMinus()) {} + +class TestImplicitArguments(val x: Long = 1.unaryMinus()) \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.txt b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.txt index 8b5970fa100..c07d580a404 100644 --- a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.txt +++ b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.txt @@ -1,4 +1,58 @@ FILE /primitivesImplicitConversions.kt + PROPERTY public val test1: kotlin.Long = 42.toLong() + FIELD PROPERTY_BACKING_FIELD public val test1: kotlin.Long = 42.toLong() + EXPRESSION_BODY + CONST Long type=kotlin.Long value='42' + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.Long + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Long' + GET_FIELD 'test1: Long' type=kotlin.Long origin=null + PROPERTY public val test2: kotlin.Short = 42.toShort() + FIELD PROPERTY_BACKING_FIELD public val test2: kotlin.Short = 42.toShort() + EXPRESSION_BODY + CONST Short type=kotlin.Short value='42' + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.Short + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Short' + GET_FIELD 'test2: Short' type=kotlin.Short origin=null + PROPERTY public val test3: kotlin.Byte = 42.toByte() + FIELD PROPERTY_BACKING_FIELD public val test3: kotlin.Byte = 42.toByte() + EXPRESSION_BODY + CONST Byte type=kotlin.Byte value='42' + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.Byte + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Byte' + GET_FIELD 'test3: Byte' type=kotlin.Byte origin=null + PROPERTY public val test4: kotlin.Long = -42.toLong() + FIELD PROPERTY_BACKING_FIELD public val test4: kotlin.Long = -42.toLong() + EXPRESSION_BODY + TYPE_OP origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.Long + CALL 'unaryMinus(): Int' type=kotlin.Int origin=null + $this: CONST Int type=kotlin.Int value='42' + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.Long + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Long' + GET_FIELD 'test4: Long' type=kotlin.Long origin=null + PROPERTY public val test5: kotlin.Short = -42.toShort() + FIELD PROPERTY_BACKING_FIELD public val test5: kotlin.Short = -42.toShort() + EXPRESSION_BODY + TYPE_OP origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.Short + CALL 'unaryMinus(): Int' type=kotlin.Int origin=null + $this: CONST Int type=kotlin.Int value='42' + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.Short + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Short' + GET_FIELD 'test5: Short' type=kotlin.Short origin=null + PROPERTY public val test6: kotlin.Byte = -42.toByte() + FIELD PROPERTY_BACKING_FIELD public val test6: kotlin.Byte = -42.toByte() + EXPRESSION_BODY + TYPE_OP origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.Byte + CALL 'unaryMinus(): Int' type=kotlin.Int origin=null + $this: CONST Int type=kotlin.Int value='42' + FUN DEFAULT_PROPERTY_ACCESSOR public fun (): kotlin.Byte + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Byte' + GET_FIELD 'test6: Byte' type=kotlin.Byte origin=null FUN public fun test(): kotlin.Unit BLOCK_BODY VAR val test1: kotlin.Int? = 42 @@ -21,3 +75,27 @@ FILE /primitivesImplicitConversions.kt TYPE_OP origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.Byte CALL 'unaryMinus(): Int' type=kotlin.Int origin=null $this: CONST Int type=kotlin.Int value='1' + FUN public fun testImplicitArguments(x: kotlin.Long = ...): kotlin.Unit + x: EXPRESSION_BODY + TYPE_OP origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.Long + CALL 'unaryMinus(): Int' type=kotlin.Int origin=null + $this: CONST Int type=kotlin.Int value='1' + BLOCK_BODY + CLASS CLASS TestImplicitArguments + CONSTRUCTOR public constructor TestImplicitArguments(x: kotlin.Long = ...) + x: EXPRESSION_BODY + TYPE_OP origin=IMPLICIT_INTEGER_COERCION typeOperand=kotlin.Long + CALL 'unaryMinus(): Int' type=kotlin.Int origin=null + $this: CONST Int type=kotlin.Int value='1' + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + INSTANCE_INITIALIZER_CALL classDescriptor='TestImplicitArguments' + PROPERTY public final val x: kotlin.Long + FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Long + EXPRESSION_BODY + GET_VAR 'value-parameter x: Long = ...' type=kotlin.Long origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): kotlin.Long + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Long' + GET_FIELD 'x: Long' type=kotlin.Long origin=null + receiver: GET_VAR '' type=TestImplicitArguments origin=null