JVM IR: replace unoverridden Number.toChar with toInt().toChar()
This fixes failing tests for JVM_IR in `box/primitiveTypes/numberToChar`. #KT-23447 Fixed #KT-46465
This commit is contained in:
committed by
Space Team
parent
a962ec4553
commit
e56e058b7b
+5
-9
@@ -162,8 +162,11 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
|||||||
private fun binaryOp(methodName: String, opcode: Int) = binaryFunForPrimitivesAcrossPrimitives(methodName, BinaryOp(opcode))
|
private fun binaryOp(methodName: String, opcode: Int) = binaryFunForPrimitivesAcrossPrimitives(methodName, BinaryOp(opcode))
|
||||||
|
|
||||||
private fun numberConversionMethods(): List<Pair<Key, IntrinsicMethod>> =
|
private fun numberConversionMethods(): List<Pair<Key, IntrinsicMethod>> =
|
||||||
PrimitiveType.NUMBER_TYPES.flatMap { type -> numberConversionMethods(type.symbol) } +
|
PrimitiveType.NUMBER_TYPES.flatMap { type ->
|
||||||
numberConversionMethods(irBuiltIns.numberClass)
|
OperatorConventions.NUMBER_CONVERSIONS.map { method ->
|
||||||
|
createKeyMapping(NumberCast, type.symbol, method.asString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun arrayMethods(): List<Pair<Key, IntrinsicMethod>> =
|
private fun arrayMethods(): List<Pair<Key, IntrinsicMethod>> =
|
||||||
symbols.primitiveArraysToPrimitiveTypes.flatMap { (array, primitiveType) -> arrayMethods(primitiveType.symbol, array) } +
|
symbols.primitiveArraysToPrimitiveTypes.flatMap { (array, primitiveType) -> arrayMethods(primitiveType.symbol, array) } +
|
||||||
@@ -234,12 +237,5 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
|||||||
): Pair<Key, IntrinsicMethod> =
|
): Pair<Key, IntrinsicMethod> =
|
||||||
Key(klass.owner.fqNameWhenAvailable!!, null, name, args.map { getParameterFqName(it) }) to
|
Key(klass.owner.fqNameWhenAvailable!!, null, name, args.map { getParameterFqName(it) }) to
|
||||||
intrinsic
|
intrinsic
|
||||||
|
|
||||||
private fun numberConversionMethods(numberClass: IrClassSymbol) =
|
|
||||||
OperatorConventions.NUMBER_CONVERSIONS.map { method ->
|
|
||||||
createKeyMapping(NumberCast, numberClass, method.asString())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -444,6 +444,7 @@ private val jvmFilePhases = listOf(
|
|||||||
kotlinNothingValueExceptionPhase,
|
kotlinNothingValueExceptionPhase,
|
||||||
makePropertyDelegateMethodsStaticPhase,
|
makePropertyDelegateMethodsStaticPhase,
|
||||||
addSuperQualifierToJavaFieldAccessPhase,
|
addSuperQualifierToJavaFieldAccessPhase,
|
||||||
|
replaceNumberToCharCallSitesPhase,
|
||||||
|
|
||||||
renameFieldsPhase,
|
renameFieldsPhase,
|
||||||
fakeInliningLocalVariablesLowering,
|
fakeInliningLocalVariablesLowering,
|
||||||
|
|||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.functionByName
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.types.isNumber
|
||||||
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
|
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||||
|
|
||||||
|
internal val replaceNumberToCharCallSitesPhase = makeIrFilePhase(
|
||||||
|
::ReplaceNumberToCharCallSitesLowering,
|
||||||
|
name = "ReplaceNumberToCharCallSites",
|
||||||
|
description = "Replace `Number.toChar` call sites with `toInt().toChar()`",
|
||||||
|
)
|
||||||
|
|
||||||
|
// This lowering replaces call sites of the form `x.toChar()` to `x.toInt().toChar()`, but only if the declaration of `toChar`
|
||||||
|
// in the scope of `x` comes from the library class `kotlin.Number`. For example, if `x` is some `MyNumber` which overrides
|
||||||
|
// `toChar`, we won't replace it because there might be some custom logic, different from `toInt().toChar()`.
|
||||||
|
//
|
||||||
|
// This allows us to migrate usages of deprecated `Number.toChar` less painfully in order to remove it in the future (KT-56822).
|
||||||
|
// Also, this allows to invoke `toChar` on `Number` subclasses declared in Java, which do not have it declared, even though the
|
||||||
|
// compiler sees it there because `java.lang.Number` is mapped to `kotlin.Number`.
|
||||||
|
class ReplaceNumberToCharCallSitesLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoid() {
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
irFile.transformChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
val callee = expression.symbol.owner
|
||||||
|
if (callee.name != OperatorConventions.CHAR) return expression
|
||||||
|
|
||||||
|
val declaration = callee.resolveFakeOverride() ?: callee
|
||||||
|
val declaringClassType = declaration.dispatchReceiverParameter?.type ?: return expression
|
||||||
|
if (!declaringClassType.isNumber()) return expression
|
||||||
|
|
||||||
|
val dispatchReceiver = expression.dispatchReceiver ?: return expression
|
||||||
|
expression.dispatchReceiver = IrCallImpl(
|
||||||
|
dispatchReceiver.startOffset, dispatchReceiver.endOffset,
|
||||||
|
context.irBuiltIns.intType, context.irBuiltIns.numberClass.functionByName("toInt"), 0, 0,
|
||||||
|
).also { toInt ->
|
||||||
|
toInt.dispatchReceiver = dispatchReceiver
|
||||||
|
}
|
||||||
|
|
||||||
|
return irCall(expression, context.irBuiltIns.intClass.functionByName("toChar"))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,9 @@
|
|||||||
// ISSUE: KT-23447
|
// ISSUE: KT-23447
|
||||||
// WITH_STDLIB
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
// IGNORE_BACKEND_K2: JVM_IR
|
||||||
|
// Ignore reason: KT-57217
|
||||||
|
|
||||||
// FILE: MyNumber.java
|
// FILE: MyNumber.java
|
||||||
|
|
||||||
public class MyNumber extends Number {
|
public class MyNumber extends Number {
|
||||||
|
|||||||
Reference in New Issue
Block a user