[FIR2IR] Fix applying of equals intrinsics
This commit is contained in:
committed by
TeamCityServer
parent
31507e7e7e
commit
15d23f2a72
+51
-13
@@ -11,15 +11,14 @@ import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.isNullable
|
||||
import org.jetbrains.kotlin.ir.builders.primitiveOp1
|
||||
import org.jetbrains.kotlin.ir.builders.primitiveOp2
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.isDoubleOrFloatWithoutNullability
|
||||
import org.jetbrains.kotlin.ir.util.getSimpleFunction
|
||||
|
||||
internal class OperatorExpressionGenerator(
|
||||
@@ -69,9 +68,13 @@ internal class OperatorExpressionGenerator(
|
||||
val (symbol, origin) = getSymbolAndOriginForComparison(operation, comparisonIrType.classifierOrFail)
|
||||
|
||||
return primitiveOp2(
|
||||
startOffset, endOffset, symbol!!, irBuiltIns.booleanType, origin,
|
||||
visitor.convertToIrExpression(comparisonExpression.left).asComparisonOperand(comparisonInfo.leftType, comparisonType),
|
||||
visitor.convertToIrExpression(comparisonExpression.right).asComparisonOperand(comparisonInfo.rightType, comparisonType),
|
||||
startOffset,
|
||||
endOffset,
|
||||
symbol!!,
|
||||
irBuiltIns.booleanType,
|
||||
origin,
|
||||
comparisonExpression.left.convertToIrExpression(comparisonInfo, isLeftType = true),
|
||||
comparisonExpression.right.convertToIrExpression(comparisonInfo, isLeftType = false)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -108,10 +111,15 @@ internal class OperatorExpressionGenerator(
|
||||
val comparisonType = comparisonInfo?.comparisonType
|
||||
val eqeqSymbol = comparisonType?.let { typeConverter.classIdToSymbolMap[it.lookupTag.classId] }
|
||||
?.let { irBuiltIns.ieee754equalsFunByOperandType[it] } ?: irBuiltIns.eqeqSymbol
|
||||
|
||||
val equalsCall = primitiveOp2(
|
||||
startOffset, endOffset, eqeqSymbol, irBuiltIns.booleanType, origin,
|
||||
visitor.convertToIrExpression(arguments[0]).asComparisonOperand(comparisonInfo?.leftType, comparisonType),
|
||||
visitor.convertToIrExpression(arguments[1]).asComparisonOperand(comparisonInfo?.rightType, comparisonType)
|
||||
startOffset,
|
||||
endOffset,
|
||||
eqeqSymbol,
|
||||
irBuiltIns.booleanType,
|
||||
origin,
|
||||
arguments[0].convertToIrExpression(comparisonInfo, isLeftType = true),
|
||||
arguments[1].convertToIrExpression(comparisonInfo, isLeftType = false)
|
||||
)
|
||||
return if (operation == FirOperation.EQ) {
|
||||
equalsCall
|
||||
@@ -129,7 +137,10 @@ internal class OperatorExpressionGenerator(
|
||||
else -> error("Not an identity operation: $operation")
|
||||
}
|
||||
val identityCall = primitiveOp2(
|
||||
startOffset, endOffset, irBuiltIns.eqeqeqSymbol, irBuiltIns.booleanType, origin,
|
||||
startOffset, endOffset,
|
||||
irBuiltIns.eqeqeqSymbol,
|
||||
irBuiltIns.booleanType,
|
||||
origin,
|
||||
visitor.convertToIrExpression(arguments[0]),
|
||||
visitor.convertToIrExpression(arguments[1])
|
||||
)
|
||||
@@ -143,16 +154,43 @@ internal class OperatorExpressionGenerator(
|
||||
private fun IrExpression.negate(origin: IrStatementOrigin) =
|
||||
primitiveOp1(startOffset, endOffset, irBuiltIns.booleanNotSymbol, irBuiltIns.booleanType, origin, this)
|
||||
|
||||
private fun FirExpression.convertToIrExpression(
|
||||
comparisonInfo: PrimitiveConeNumericComparisonInfo?,
|
||||
isLeftType: Boolean
|
||||
): IrExpression {
|
||||
return visitor.convertToIrExpression(this).asComparisonOperand(
|
||||
if (isLeftType) comparisonInfo?.leftType else comparisonInfo?.rightType,
|
||||
comparisonInfo?.comparisonType,
|
||||
noImplicitCast = comparisonInfo?.leftType == comparisonInfo?.rightType
|
||||
)
|
||||
}
|
||||
|
||||
private fun IrExpression.asComparisonOperand(
|
||||
operandType: ConeClassLikeType?,
|
||||
targetType: ConeClassLikeType?
|
||||
targetType: ConeClassLikeType?,
|
||||
noImplicitCast: Boolean
|
||||
): IrExpression {
|
||||
if (targetType == null) return this
|
||||
fun eraseImplicitCast(): IrExpression {
|
||||
return if (noImplicitCast &&
|
||||
this is IrTypeOperatorCall &&
|
||||
this.operator == IrTypeOperator.IMPLICIT_CAST &&
|
||||
!this.type.isDoubleOrFloatWithoutNullability()
|
||||
) {
|
||||
this.argument
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
if (targetType == null) {
|
||||
return eraseImplicitCast()
|
||||
}
|
||||
|
||||
if (operandType == null) error("operandType should be non-null if targetType is non-null")
|
||||
|
||||
val operandClassId = operandType.lookupTag.classId
|
||||
val targetClassId = targetType.lookupTag.classId
|
||||
if (operandClassId == targetClassId) return this
|
||||
if (operandClassId == targetClassId) return eraseImplicitCast()
|
||||
val conversionFunction =
|
||||
typeConverter.classIdToSymbolMap[operandClassId]?.getSimpleFunction("to${targetType.lookupTag.classId.shortClassName.asString()}")
|
||||
?: error("No conversion function for $operandType ~> $targetType")
|
||||
|
||||
@@ -132,6 +132,10 @@ fun IrType.isULong(): Boolean = isNotNullClassType(IdSignatureValues.uLong)
|
||||
fun IrType.isFloat(): Boolean = isNotNullClassType(IdSignatureValues._float)
|
||||
fun IrType.isDouble(): Boolean = isNotNullClassType(IdSignatureValues._double)
|
||||
fun IrType.isNumber(): Boolean = isNotNullClassType(IdSignatureValues.number)
|
||||
fun IrType.isDoubleOrFloatWithoutNullability(): Boolean {
|
||||
return isClassType(IdSignatureValues._double, hasQuestionMark = null) ||
|
||||
isClassType(IdSignatureValues._float, hasQuestionMark = null)
|
||||
}
|
||||
|
||||
fun IrType.isComparable(): Boolean = isNotNullClassType(IdSignatureValues.comparable)
|
||||
fun IrType.isCharSequence(): Boolean = isNotNullClassType(IdSignatureValues.charSequence)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun equals3(a: Char?, b: Char?) = a != null && b != null && a == b
|
||||
|
||||
fun equals4(a: Char?, b: Char?) = if (a is Char && b is Char) a == b else null!!
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +ProperIeee754Comparisons
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun equals3(a: Int?, b: Int?) = a != null && b != null && a == b
|
||||
|
||||
fun equals4(a: Int?, b: Int?) = if (a is Int && b is Int) a == b else null!!
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: -ProperIeee754Comparisons
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun equals3(a: Int?, b: Int?) = a != null && b != null && a == b
|
||||
|
||||
fun equals4(a: Int?, b: Int?) = if (a is Int && b is Int) a == b else null!!
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
fun equals3(a: Long?, b: Long?) = a != null && b != null && a == b
|
||||
|
||||
fun equals4(a: Long?, b: Long?) = if (a is Long && b is Long) a == b else null!!
|
||||
|
||||
-163
@@ -1,163 +0,0 @@
|
||||
FILE fqName:<root> fileName:/typeParameterWithPrimitiveNumericSupertype.kt
|
||||
FUN name:test0 visibility:public modality:FINAL <T> (x:kotlin.Any, y:T of <root>.test0) returnType:kotlin.Boolean
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
||||
VALUE_PARAMETER name:y index:1 type:T of <root>.test0
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test0 <T> (x: kotlin.Any, y: T of <root>.test0): kotlin.Boolean declared in <root>'
|
||||
WHEN type=kotlin.Boolean origin=ANDAND
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test0' type=kotlin.Any origin=null
|
||||
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test0' type=kotlin.Any origin=null
|
||||
arg1: GET_VAR 'y: T of <root>.test0 declared in <root>.test0' type=T of <root>.test0 origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
FUN name:test1 visibility:public modality:FINAL <T> (x:kotlin.Any, y:T of <root>.test1) returnType:kotlin.Boolean
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Float]
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
||||
VALUE_PARAMETER name:y index:1 type:T of <root>.test1
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 <T> (x: kotlin.Any, y: T of <root>.test1): kotlin.Boolean declared in <root>'
|
||||
WHEN type=kotlin.Boolean origin=ANDAND
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test1' type=kotlin.Any origin=null
|
||||
then: CALL 'public final fun ieee754equals (arg0: kotlin.Float?, arg1: kotlin.Float?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test1' type=kotlin.Any origin=null
|
||||
arg1: GET_VAR 'y: T of <root>.test1 declared in <root>.test1' type=T of <root>.test1 origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
FUN name:test2 visibility:public modality:FINAL <T> (x:kotlin.Any, y:T of <root>.test2) returnType:kotlin.Boolean
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Double]
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
||||
VALUE_PARAMETER name:y index:1 type:T of <root>.test2
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test2 <T> (x: kotlin.Any, y: T of <root>.test2): kotlin.Boolean declared in <root>'
|
||||
WHEN type=kotlin.Boolean origin=ANDAND
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Float
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test2' type=kotlin.Any origin=null
|
||||
then: CALL 'public final fun ieee754equals (arg0: kotlin.Double?, arg1: kotlin.Double?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
|
||||
$this: TYPE_OP type=kotlin.Float origin=IMPLICIT_CAST typeOperand=kotlin.Float
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test2' type=kotlin.Any origin=null
|
||||
arg1: GET_VAR 'y: T of <root>.test2 declared in <root>.test2' type=T of <root>.test2 origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
FUN name:test3 visibility:public modality:FINAL <T> (x:kotlin.Any, y:T of <root>.test3) returnType:kotlin.Boolean
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Float]
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
||||
VALUE_PARAMETER name:y index:1 type:T of <root>.test3
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 <T> (x: kotlin.Any, y: T of <root>.test3): kotlin.Boolean declared in <root>'
|
||||
WHEN type=kotlin.Boolean origin=ANDAND
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null
|
||||
then: CALL 'public final fun ieee754equals (arg0: kotlin.Float?, arg1: kotlin.Float?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: CALL 'public open fun toFloat (): kotlin.Float declared in kotlin.Int' type=kotlin.Float origin=null
|
||||
$this: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test3' type=kotlin.Any origin=null
|
||||
arg1: GET_VAR 'y: T of <root>.test3 declared in <root>.test3' type=T of <root>.test3 origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
FUN name:test4 visibility:public modality:FINAL <T> (x:kotlin.Any, y:T of <root>.test4) returnType:kotlin.Boolean
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Float?]
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
||||
VALUE_PARAMETER name:y index:1 type:T of <root>.test4
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test4 <T> (x: kotlin.Any, y: T of <root>.test4): kotlin.Boolean declared in <root>'
|
||||
WHEN type=kotlin.Boolean origin=ANDAND
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test4' type=kotlin.Any origin=null
|
||||
then: CALL 'public final fun ieee754equals (arg0: kotlin.Float?, arg1: kotlin.Float?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: CALL 'public open fun toFloat (): kotlin.Float declared in kotlin.Int' type=kotlin.Float origin=null
|
||||
$this: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test4' type=kotlin.Any origin=null
|
||||
arg1: GET_VAR 'y: T of <root>.test4 declared in <root>.test4' type=T of <root>.test4 origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
FUN name:test5 visibility:public modality:FINAL <T, R> (x:kotlin.Any, y:R of <root>.test5) returnType:kotlin.Boolean
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Float?]
|
||||
TYPE_PARAMETER name:R index:1 variance: superTypes:[T of <root>.test5]
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
||||
VALUE_PARAMETER name:y index:1 type:R of <root>.test5
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test5 <T, R> (x: kotlin.Any, y: R of <root>.test5): kotlin.Boolean declared in <root>'
|
||||
WHEN type=kotlin.Boolean origin=ANDAND
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null
|
||||
then: CALL 'public final fun ieee754equals (arg0: kotlin.Float?, arg1: kotlin.Float?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: CALL 'public open fun toFloat (): kotlin.Float declared in kotlin.Int' type=kotlin.Float origin=null
|
||||
$this: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test5' type=kotlin.Any origin=null
|
||||
arg1: GET_VAR 'y: R of <root>.test5 declared in <root>.test5' type=R of <root>.test5 origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
FUN name:test6 visibility:public modality:FINAL <T> (x:kotlin.Any, y:T of <root>.test6) returnType:kotlin.Boolean
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Number]
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.Any
|
||||
VALUE_PARAMETER name:y index:1 type:T of <root>.test6
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test6 <T> (x: kotlin.Any, y: T of <root>.test6): kotlin.Boolean declared in <root>'
|
||||
WHEN type=kotlin.Boolean origin=ANDAND
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test6' type=kotlin.Any origin=null
|
||||
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.test6' type=kotlin.Any origin=null
|
||||
arg1: GET_VAR 'y: T of <root>.test6 declared in <root>.test6' type=T of <root>.test6 origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
CLASS CLASS name:F modality:FINAL visibility:public superTypes:[kotlin.Any]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.F<T of <root>.F>
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Float]
|
||||
CONSTRUCTOR visibility:public <> () returnType:<root>.F<T of <root>.F> [primary]
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:F modality:FINAL visibility:public superTypes:[kotlin.Any]'
|
||||
FUN name:testCapturedType visibility:public modality:FINAL <> ($this:<root>.F<T of <root>.F>, x:T of <root>.F, y:kotlin.Any) returnType:kotlin.Boolean
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.F<T of <root>.F>
|
||||
VALUE_PARAMETER name:x index:0 type:T of <root>.F
|
||||
VALUE_PARAMETER name:y index:1 type:kotlin.Any
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun testCapturedType (x: T of <root>.F, y: kotlin.Any): kotlin.Boolean declared in <root>.F'
|
||||
WHEN type=kotlin.Boolean origin=ANDAND
|
||||
BRANCH
|
||||
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.Double
|
||||
GET_VAR 'y: kotlin.Any declared in <root>.F.testCapturedType' type=kotlin.Any origin=null
|
||||
then: CALL 'public final fun ieee754equals (arg0: kotlin.Double?, arg1: kotlin.Double?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: CALL 'public open fun toDouble (): kotlin.Double declared in kotlin.Float' type=kotlin.Double origin=null
|
||||
$this: GET_VAR 'x: T of <root>.F declared in <root>.F.testCapturedType' type=T of <root>.F origin=null
|
||||
arg1: TYPE_OP type=kotlin.Double origin=IMPLICIT_CAST typeOperand=kotlin.Double
|
||||
GET_VAR 'y: kotlin.Any declared in <root>.F.testCapturedType' type=kotlin.Any origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||
overridden:
|
||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
||||
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
|
||||
overridden:
|
||||
public open fun hashCode (): kotlin.Int declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
fun <T : Any?> test0(x: Any, y: T): Boolean {
|
||||
return when {
|
||||
x is Int -> EQEQ(arg0 = x /*as Int */, arg1 = y)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Float> test1(x: Any, y: T): Boolean {
|
||||
return when {
|
||||
x is Float -> ieee754equals(arg0 = x /*as Float */, arg1 = y)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Double> test2(x: Any, y: T): Boolean {
|
||||
return when {
|
||||
x is Float -> ieee754equals(arg0 = x /*as Float */.toDouble(), arg1 = y)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Float> test3(x: Any, y: T): Boolean {
|
||||
return when {
|
||||
x is Int -> ieee754equals(arg0 = x /*as Int */.toFloat(), arg1 = y)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Float?> test4(x: Any, y: T): Boolean {
|
||||
return when {
|
||||
x is Int -> ieee754equals(arg0 = x /*as Int */.toFloat(), arg1 = y)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Float?, R : T> test5(x: Any, y: R): Boolean {
|
||||
return when {
|
||||
x is Int -> ieee754equals(arg0 = x /*as Int */.toFloat(), arg1 = y)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Number> test6(x: Any, y: T): Boolean {
|
||||
return when {
|
||||
x is Int -> EQEQ(arg0 = x /*as Int */, arg1 = y)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
class F<T : Float> {
|
||||
constructor() /* primary */ {
|
||||
super/*Any*/()
|
||||
/* <init>() */
|
||||
|
||||
}
|
||||
|
||||
fun testCapturedType(x: T, y: Any): Boolean {
|
||||
return when {
|
||||
y is Double -> ieee754equals(arg0 = x.toDouble(), arg1 = y /*as Double */)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
fun <T> test0(x: Any, y: T) = x is Int && x == y
|
||||
fun <T : Float> test1(x: Any, y: T) = x is Float && x == y
|
||||
fun <T : Double> test2(x: Any, y: T) = x is Float && x == y
|
||||
|
||||
@@ -58,10 +58,8 @@ FILE fqName:<root> fileName:/kt23030.kt
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
then: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int
|
||||
GET_VAR 'x: kotlin.Any declared in <root>.testEqualsWithSmartCast' type=kotlin.Any origin=null
|
||||
arg1: TYPE_OP type=kotlin.Char origin=IMPLICIT_CAST typeOperand=kotlin.Char
|
||||
GET_VAR 'y: kotlin.Any declared in <root>.testEqualsWithSmartCast' type=kotlin.Any origin=null
|
||||
arg0: GET_VAR 'x: kotlin.Any declared in <root>.testEqualsWithSmartCast' type=kotlin.Any origin=null
|
||||
arg1: GET_VAR 'y: kotlin.Any declared in <root>.testEqualsWithSmartCast' type=kotlin.Any origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: CONST Boolean type=kotlin.Boolean value=false
|
||||
|
||||
@@ -21,7 +21,7 @@ fun testEqualsWithSmartCast(x: Any, y: Any): Boolean {
|
||||
when {
|
||||
x is Int -> y is Char
|
||||
else -> false
|
||||
} -> EQEQ(arg0 = x /*as Int */, arg1 = y /*as Char */)
|
||||
} -> EQEQ(arg0 = x, arg1 = y)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
@@ -52,3 +52,4 @@ class C {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user