From 30b91b128a51815743ee7d8368febfc84d6d84de Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 9 Jul 2020 00:22:41 -0700 Subject: [PATCH] FIR: adjust type of integer operator call as property initializer --- ...egerLiteralTypeApproximationTransformer.kt | 19 ++++++++++++++++++- .../FirDeclarationsResolveTransformer.kt | 2 +- .../codegen/box/evaluate/unaryMinus.kt | 1 - .../codegen/box/evaluate/unaryPlus.kt | 1 - .../primitivesImplicitConversions.fir.txt | 6 +++--- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/IntegerLiteralTypeApproximationTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/IntegerLiteralTypeApproximationTransformer.kt index 60b7c1bdd1a..2fed3a6ffed 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/IntegerLiteralTypeApproximationTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/IntegerLiteralTypeApproximationTransformer.kt @@ -54,7 +54,24 @@ class IntegerLiteralTypeApproximationTransformer( } override fun transformFunctionCall(functionCall: FirFunctionCall, data: ConeKotlinType?): CompositeTransformResult { - val operator = functionCall.toResolvedCallableSymbol()?.fir as? FirIntegerOperator ?: return functionCall.compose() + val operator = functionCall.toResolvedCallableSymbol()?.fir as? FirIntegerOperator + if (operator == null) { + if (functionCall is FirIntegerOperatorCall) { + // functionCall _was_ a named call whose candidate symbol was an integer operator, but has been transformed to an integer + // operator call (by [IntegerOperatorsTypeUpdater]). So, technically, this _was_ a call that this transformer was looking + // for, i.e., a call with ILT, but in a resolved form already. Here we just adapt to the expected type if any. + // + // Note that such inequality can happen to the resolved call, since the call completer doesn't complete the call with the + // given, expected type: see [FirCallCompleter#completeCall]. One reason _not_ to propagate the expected type to the call + // completing transformation is to handle integer overflow naturally. E.g., if a property with Long, a bigger type, is + // intentionally set with an integer operator that overflows, knowing the expected type will hide the overflow. Rather, we + // have a second chance here to sort of wrap such overflowed integer with type conversion, like `n.toLong()`. + data?.let { + functionCall.resultType = functionCall.resultType.resolvedTypeFromPrototype(it) + } + } + return functionCall.compose() + } functionCall.transformChildren(this, data) val argumentType = functionCall.arguments.firstOrNull()?.resultType?.coneTypeUnsafe() val receiverClassId = functionCall.dispatchReceiver.typeRef.coneTypeUnsafe().lookupTag.classId diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 693cfbacee0..8deba5d0df8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -133,7 +133,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor withLocalScopeCleanup { addLocalScope(context.getPrimaryConstructorParametersScope()) property.transformChildrenWithoutAccessors(returnTypeRef) - property.transformInitializer(integerLiteralTypeApproximator, null) + property.transformInitializer(integerLiteralTypeApproximator, property.returnTypeRef.coneTypeSafe()) } if (property.initializer != null) { storeVariableReturnType(property) diff --git a/compiler/testData/codegen/box/evaluate/unaryMinus.kt b/compiler/testData/codegen/box/evaluate/unaryMinus.kt index 10e389f4704..5de3a0875ec 100644 --- a/compiler/testData/codegen/box/evaluate/unaryMinus.kt +++ b/compiler/testData/codegen/box/evaluate/unaryMinus.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/evaluate/unaryPlus.kt b/compiler/testData/codegen/box/evaluate/unaryPlus.kt index 3a7a330507d..65c85b34858 100644 --- a/compiler/testData/codegen/box/evaluate/unaryPlus.kt +++ b/compiler/testData/codegen/box/evaluate/unaryPlus.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.fir.txt b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.fir.txt index 37e765acb2c..26c0858a453 100644 --- a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.fir.txt +++ b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.fir.txt @@ -29,7 +29,7 @@ FILE fqName: fileName:/primitivesImplicitConversions.kt PROPERTY name:test4 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test4 type:kotlin.Long visibility:private [final,static] EXPRESSION_BODY - CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null + CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Long origin=null $this: CONST Int type=kotlin.Int value=42 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Long correspondingProperty: PROPERTY name:test4 visibility:public modality:FINAL [val] @@ -39,7 +39,7 @@ FILE fqName: fileName:/primitivesImplicitConversions.kt PROPERTY name:test5 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test5 type:kotlin.Short visibility:private [final,static] EXPRESSION_BODY - CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null + CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Short origin=null $this: CONST Int type=kotlin.Int value=42 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Short correspondingProperty: PROPERTY name:test5 visibility:public modality:FINAL [val] @@ -49,7 +49,7 @@ FILE fqName: fileName:/primitivesImplicitConversions.kt PROPERTY name:test6 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test6 type:kotlin.Byte visibility:private [final,static] EXPRESSION_BODY - CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null + CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Byte origin=null $this: CONST Int type=kotlin.Int value=42 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Byte correspondingProperty: PROPERTY name:test6 visibility:public modality:FINAL [val]