Cast step expression to the correct Number type, if necessary.
This commit is contained in:
committed by
max-kammerer
parent
f6e74079bb
commit
6b83c04472
+4
-4
@@ -26,10 +26,10 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
// TODO: Handle UIntProgression, ULongProgression
|
||||
|
||||
/** Represents a progression type in the Kotlin stdlib. */
|
||||
enum class ProgressionType(val numberCastFunctionName: Name) {
|
||||
INT_PROGRESSION(Name.identifier("toInt")),
|
||||
LONG_PROGRESSION(Name.identifier("toLong")),
|
||||
CHAR_PROGRESSION(Name.identifier("toChar"));
|
||||
enum class ProgressionType(val elementCastFunctionName: Name, val stepCastFunctionName: Name) {
|
||||
INT_PROGRESSION(Name.identifier("toInt"), Name.identifier("toInt")),
|
||||
LONG_PROGRESSION(Name.identifier("toLong"), Name.identifier("toLong")),
|
||||
CHAR_PROGRESSION(Name.identifier("toChar"), Name.identifier("toInt"));
|
||||
|
||||
/** Returns the [IrType] of the `first`/`last` properties and elements in the progression. */
|
||||
fun elementType(builtIns: IrBuiltIns): IrType = when (this) {
|
||||
|
||||
+20
-6
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.functions
|
||||
import org.jetbrains.kotlin.ir.util.isNullable
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
/** Contains information about variables used in the loop. */
|
||||
internal sealed class ForLoopHeader(
|
||||
@@ -224,7 +225,10 @@ internal class HeaderProcessor(
|
||||
// In the above example, if first() is a Long and last() is an Int, this creates a
|
||||
// LongProgression so last(), should be cast to a Long.
|
||||
val inductionVariable = scope.createTemporaryVariable(
|
||||
first.castIfNecessary(progressionType),
|
||||
first.castIfNecessary(
|
||||
progressionType.elementType(context.irBuiltIns),
|
||||
progressionType.elementCastFunctionName
|
||||
),
|
||||
nameHint = "inductionVariable",
|
||||
isMutable = true,
|
||||
origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE
|
||||
@@ -235,13 +239,23 @@ internal class HeaderProcessor(
|
||||
// them to non-nullable.
|
||||
// TODO: Confirm if casting to non-nullable is still necessary
|
||||
val lastValue = scope.createTemporaryVariable(
|
||||
ensureNotNullable(last.castIfNecessary(progressionType)),
|
||||
ensureNotNullable(
|
||||
last.castIfNecessary(
|
||||
progressionType.elementType(context.irBuiltIns),
|
||||
progressionType.elementCastFunctionName
|
||||
)
|
||||
),
|
||||
nameHint = "last",
|
||||
origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE
|
||||
)
|
||||
|
||||
val stepValue = scope.createTemporaryVariable(
|
||||
ensureNotNullable(step),
|
||||
ensureNotNullable(
|
||||
step.castIfNecessary(
|
||||
progressionType.stepType(context.irBuiltIns),
|
||||
progressionType.stepCastFunctionName
|
||||
)
|
||||
),
|
||||
nameHint = "step",
|
||||
origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE
|
||||
)
|
||||
@@ -265,11 +279,11 @@ internal class HeaderProcessor(
|
||||
}
|
||||
|
||||
|
||||
private fun IrExpression.castIfNecessary(progressionType: ProgressionType): IrExpression {
|
||||
return if (type.toKotlinType() == progressionType.elementType(context.irBuiltIns).toKotlinType()) {
|
||||
private fun IrExpression.castIfNecessary(targetType: IrType, numberCastFunctionName: Name): IrExpression {
|
||||
return if (type.toKotlinType() == targetType.toKotlinType()) {
|
||||
this
|
||||
} else {
|
||||
val function = type.getClass()!!.functions.first { it.name == progressionType.numberCastFunctionName }
|
||||
val function = type.getClass()!!.functions.first { it.name == numberCastFunctionName }
|
||||
IrCallImpl(startOffset, endOffset, function.returnType, function.symbol)
|
||||
.apply { dispatchReceiver = this@castIfNecessary }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user