diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java index 69d4285b385..4d8801bc000 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java @@ -1740,6 +1740,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/types/platformTypeReceiver.kt"); } + @TestMetadata("smartCastOnFakeOverrideReceiver.kt") + public void testSmartCastOnFakeOverrideReceiver() throws Exception { + runTest("compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.kt"); + } + @TestMetadata("smartCastOnFieldReceiverOfGenericType.kt") public void testSmartCastOnFieldReceiverOfGenericType() throws Exception { runTest("compiler/testData/ir/irText/types/smartCastOnFieldReceiverOfGenericType.kt"); 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 a4a3b2c2bde..e1fb77b9ec5 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,8 @@ package org.jetbrains.kotlin.psi2ir.transformations import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrClass @@ -38,10 +40,7 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.KotlinTypeChecker -import org.jetbrains.kotlin.types.typeUtil.isNullableAny -import org.jetbrains.kotlin.types.typeUtil.isUnit -import org.jetbrains.kotlin.types.typeUtil.makeNotNullable -import org.jetbrains.kotlin.types.typeUtil.makeNullable +import org.jetbrains.kotlin.types.typeUtil.* fun insertImplicitCasts(element: IrElement, context: GeneratorContext) { element.transformChildren( @@ -77,10 +76,27 @@ open class InsertImplicitCasts( } private fun IrMemberAccessExpression.transformReceiverArguments(substitutedDescriptor: CallableDescriptor) { - dispatchReceiver = dispatchReceiver?.cast(substitutedDescriptor.dispatchReceiverParameter?.type) + dispatchReceiver = dispatchReceiver?.cast(getEffectiveDispatchReceiverType(substitutedDescriptor)) extensionReceiver = extensionReceiver?.cast(substitutedDescriptor.extensionReceiverParameter?.type) } + private fun getEffectiveDispatchReceiverType(descriptor: CallableDescriptor): KotlinType? = + when { + descriptor !is CallableMemberDescriptor -> + null + + descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE -> { + val containingDeclaration = descriptor.containingDeclaration + if (containingDeclaration !is ClassDescriptor) + throw AssertionError("Containing declaration for $descriptor should be a class: $containingDeclaration") + else + containingDeclaration.defaultType.replaceArgumentsWithStarProjections() + } + + else -> + descriptor.dispatchReceiverParameter?.type + } + override fun visitMemberAccess(expression: IrMemberAccessExpression): IrExpression { val substitutedDescriptor = expression.substitutedDescriptor return expression.transformPostfix { @@ -132,8 +148,14 @@ open class InsertImplicitCasts( value = value.cast(expression.symbol.descriptor.type) } + override fun visitGetField(expression: IrGetField): IrExpression = + expression.transformPostfix { + receiver = receiver?.cast(getEffectiveDispatchReceiverType(expression.symbol.descriptor)) + } + override fun visitSetField(expression: IrSetField): IrExpression = expression.transformPostfix { + receiver = receiver?.cast(getEffectiveDispatchReceiverType(expression.symbol.descriptor)) value = value.cast(expression.symbol.descriptor.type) } diff --git a/compiler/testData/codegen/box/regressions/kt5445.kt b/compiler/testData/codegen/box/regressions/kt5445.kt index ea6fff72bea..4d2d387d5a5 100644 --- a/compiler/testData/codegen/box/regressions/kt5445.kt +++ b/compiler/testData/codegen/box/regressions/kt5445.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.fir.txt b/compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.fir.txt new file mode 100644 index 00000000000..96ae9b8d90e --- /dev/null +++ b/compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.fir.txt @@ -0,0 +1,209 @@ +FILE fqName: fileName:/smartCastOnFakeOverrideReceiver.kt + CLASS CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.A + CONSTRUCTOR visibility:public <> () returnType:.A [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Any]' + FUN name:f visibility:public modality:FINAL <> ($this:.A) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.A + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun f (): kotlin.Int declared in .A' + CONST Int type=kotlin.Int value=1 + PROPERTY name:aVal visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:aVal type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + CONST Int type=kotlin.Int value=42 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.A) returnType:kotlin.Int + correspondingProperty: PROPERTY name:aVal visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.A + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .A' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:aVal type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .A declared in .A.' type=.A origin=null + FUN name:testA1 visibility:public modality:FINAL <> ($this:.A, x:kotlin.Any) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.A + VALUE_PARAMETER name:x index:0 type:kotlin.Any + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testA1 (x: kotlin.Any): kotlin.Int? declared in .A' + WHEN type=kotlin.Int? origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .A.testA1' type=kotlin.Any origin=null + then: CALL 'public final fun f (): kotlin.Int declared in .A' type=kotlin.Int origin=null + $this: GET_VAR 'x: kotlin.Any declared in .A.testA1' type=.B origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null + FUN name:testA2 visibility:public modality:FINAL <> ($this:.A, x:kotlin.Any) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.A + VALUE_PARAMETER name:x index:0 type:kotlin.Any + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testA2 (x: kotlin.Any): kotlin.Int? declared in .A' + WHEN type=kotlin.Int? origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .A.testA2' type=kotlin.Any origin=null + then: CALL 'public final fun (): kotlin.Int declared in .A' type=kotlin.Int origin=null + $this: GET_VAR 'x: kotlin.Any declared in .A.testA2' type=.B origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null + 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: 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: 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: type:kotlin.Any + CLASS CLASS name:B modality:FINAL visibility:public superTypes:[.A] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.B + CONSTRUCTOR visibility:public <> () returnType:.B [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in .A' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:B modality:FINAL visibility:public superTypes:[.A]' + FUN name:testB1 visibility:public modality:FINAL <> ($this:.B, x:kotlin.Any) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.B + VALUE_PARAMETER name:x index:0 type:kotlin.Any + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testB1 (x: kotlin.Any): kotlin.Int? declared in .B' + WHEN type=kotlin.Int? origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .B.testB1' type=kotlin.Any origin=null + then: CALL 'public final fun f (): kotlin.Int declared in .A' type=kotlin.Int origin=null + $this: GET_VAR 'x: kotlin.Any declared in .B.testB1' type=.B origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null + FUN name:testB2 visibility:public modality:FINAL <> ($this:.B, x:kotlin.Any) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.B + VALUE_PARAMETER name:x index:0 type:kotlin.Any + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testB2 (x: kotlin.Any): kotlin.Int? declared in .B' + WHEN type=kotlin.Int? origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .B.testB2' type=kotlin.Any origin=null + then: CALL 'public final fun (): kotlin.Int declared in .A' type=kotlin.Int origin=null + $this: GET_VAR 'x: kotlin.Any declared in .B.testB2' type=.B origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null + FUN FAKE_OVERRIDE name:f visibility:public modality:FINAL <> ($this:.A) returnType:kotlin.Int [fake_override] + overridden: + public final fun f (): kotlin.Int declared in .A + $this: VALUE_PARAMETER name: type:.A + PROPERTY FAKE_OVERRIDE name:aVal visibility:public modality:FINAL [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.B) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:aVal visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.Int declared in .A + $this: VALUE_PARAMETER name: type:.B + FUN FAKE_OVERRIDE name:testA1 visibility:public modality:FINAL <> ($this:.A, x:kotlin.Any) returnType:kotlin.Int? [fake_override] + overridden: + public final fun testA1 (x: kotlin.Any): kotlin.Int? declared in .A + $this: VALUE_PARAMETER name: type:.A + VALUE_PARAMETER name:x index:0 type:kotlin.Any + FUN FAKE_OVERRIDE name:testA2 visibility:public modality:FINAL <> ($this:.A, x:kotlin.Any) returnType:kotlin.Int? [fake_override] + overridden: + public final fun testA2 (x: kotlin.Any): kotlin.Int? declared in .A + $this: VALUE_PARAMETER name: type:.A + VALUE_PARAMETER name:x index:0 type:kotlin.Any + 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: 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: 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: type:kotlin.Any + CLASS CLASS name:GA modality:OPEN visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.GA + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + CONSTRUCTOR visibility:public <> () returnType:.GA.GA> [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:GA modality:OPEN visibility:public superTypes:[kotlin.Any]' + FUN name:f visibility:public modality:FINAL <> ($this:.GA) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.GA + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun f (): kotlin.Int declared in .GA' + CONST Int type=kotlin.Int value=1 + PROPERTY name:aVal visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:aVal type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + CONST Int type=kotlin.Int value=42 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.GA) returnType:kotlin.Int + correspondingProperty: PROPERTY name:aVal visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.GA + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .GA' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:aVal type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .GA declared in .GA.' type=.GA origin=null + 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: 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: 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: type:kotlin.Any + CLASS CLASS name:GB modality:FINAL visibility:public superTypes:[.GA.GB>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.GB + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + TYPE_PARAMETER name:S index:1 variance: superTypes:[kotlin.Any?] + CONSTRUCTOR visibility:public <> () returnType:.GB.GB, S of .GB> [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in .GA' + : + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:GB modality:FINAL visibility:public superTypes:[.GA.GB>]' + FUN name:testGB1 visibility:public modality:FINAL <> ($this:.GB, a:kotlin.Any) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.GB + VALUE_PARAMETER name:a index:0 type:kotlin.Any + BLOCK_BODY + TYPE_OP type=.GB origin=CAST typeOperand=.GB + GET_VAR 'a: kotlin.Any declared in .GB.testGB1' type=kotlin.Any origin=null + CALL 'public final fun f (): kotlin.Int declared in .GA' type=kotlin.Int origin=null + $this: GET_VAR 'a: kotlin.Any declared in .GB.testGB1' type=.GB origin=null + CALL 'public final fun (): kotlin.Int declared in .GA' type=kotlin.Int origin=null + $this: GET_VAR 'a: kotlin.Any declared in .GB.testGB1' type=.GB origin=null + FUN FAKE_OVERRIDE name:f visibility:public modality:FINAL <> ($this:.GA) returnType:kotlin.Int [fake_override] + overridden: + public final fun f (): kotlin.Int declared in .GA + $this: VALUE_PARAMETER name: type:.GA + PROPERTY FAKE_OVERRIDE name:aVal visibility:public modality:FINAL [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.GB) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:aVal visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.Int declared in .GA + $this: VALUE_PARAMETER name: type:.GB + 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: 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: 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: type:kotlin.Any diff --git a/compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.kt b/compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.kt new file mode 100644 index 00000000000..82ceaf8eaee --- /dev/null +++ b/compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.kt @@ -0,0 +1,25 @@ +open class A { + fun f() = 1 + val aVal = 42 + + fun testA1(x: Any) = if (x is B) x.f() else null + fun testA2(x: Any) = if (x is B) x.aVal else null +} + +class B : A() { + fun testB1(x: Any) = if (x is B) x.f() else null + fun testB2(x: Any) = if (x is B) x.aVal else null +} + +open class GA { + fun f() = 1 + val aVal = 42 +} + +class GB : GA() { + fun testGB1(a: Any) { + a as GB + a.f() + a.aVal + } +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.txt b/compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.txt new file mode 100644 index 00000000000..0bb26d5c38d --- /dev/null +++ b/compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.txt @@ -0,0 +1,218 @@ +FILE fqName: fileName:/smartCastOnFakeOverrideReceiver.kt + CLASS CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.A + CONSTRUCTOR visibility:public <> () returnType:.A [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:A modality:OPEN visibility:public superTypes:[kotlin.Any]' + FUN name:f visibility:public modality:FINAL <> ($this:.A) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.A + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun f (): kotlin.Int declared in .A' + CONST Int type=kotlin.Int value=1 + PROPERTY name:aVal visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:aVal type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + CONST Int type=kotlin.Int value=42 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.A) returnType:kotlin.Int + correspondingProperty: PROPERTY name:aVal visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.A + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .A' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:aVal type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .A declared in .A.' type=.A origin=null + FUN name:testA1 visibility:public modality:FINAL <> ($this:.A, x:kotlin.Any) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.A + VALUE_PARAMETER name:x index:0 type:kotlin.Any + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testA1 (x: kotlin.Any): kotlin.Int? declared in .A' + WHEN type=kotlin.Int? origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .A.testA1' type=kotlin.Any origin=null + then: CALL 'public final fun f (): kotlin.Int [fake_override] declared in .B' type=kotlin.Int origin=null + $this: TYPE_OP type=.B origin=IMPLICIT_CAST typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .A.testA1' type=kotlin.Any origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null + FUN name:testA2 visibility:public modality:FINAL <> ($this:.A, x:kotlin.Any) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.A + VALUE_PARAMETER name:x index:0 type:kotlin.Any + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testA2 (x: kotlin.Any): kotlin.Int? declared in .A' + WHEN type=kotlin.Int? origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .A.testA2' type=kotlin.Any origin=null + then: CALL 'public final fun (): kotlin.Int [fake_override] declared in .B' type=kotlin.Int origin=GET_PROPERTY + $this: TYPE_OP type=.B origin=IMPLICIT_CAST typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .A.testA2' type=kotlin.Any origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null + 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: 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: 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: type:kotlin.Any + CLASS CLASS name:B modality:FINAL visibility:public superTypes:[.A] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.B + CONSTRUCTOR visibility:public <> () returnType:.B [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in .A' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:B modality:FINAL visibility:public superTypes:[.A]' + FUN name:testB1 visibility:public modality:FINAL <> ($this:.B, x:kotlin.Any) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.B + VALUE_PARAMETER name:x index:0 type:kotlin.Any + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testB1 (x: kotlin.Any): kotlin.Int? declared in .B' + WHEN type=kotlin.Int? origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .B.testB1' type=kotlin.Any origin=null + then: CALL 'public final fun f (): kotlin.Int [fake_override] declared in .B' type=kotlin.Int origin=null + $this: TYPE_OP type=.B origin=IMPLICIT_CAST typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .B.testB1' type=kotlin.Any origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null + FUN name:testB2 visibility:public modality:FINAL <> ($this:.B, x:kotlin.Any) returnType:kotlin.Int? + $this: VALUE_PARAMETER name: type:.B + VALUE_PARAMETER name:x index:0 type:kotlin.Any + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun testB2 (x: kotlin.Any): kotlin.Int? declared in .B' + WHEN type=kotlin.Int? origin=IF + BRANCH + if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .B.testB2' type=kotlin.Any origin=null + then: CALL 'public final fun (): kotlin.Int [fake_override] declared in .B' type=kotlin.Int origin=GET_PROPERTY + $this: TYPE_OP type=.B origin=IMPLICIT_CAST typeOperand=.B + GET_VAR 'x: kotlin.Any declared in .B.testB2' type=kotlin.Any origin=null + BRANCH + if: CONST Boolean type=kotlin.Boolean value=true + then: CONST Null type=kotlin.Nothing? value=null + FUN FAKE_OVERRIDE name:f visibility:public modality:FINAL <> ($this:.A) returnType:kotlin.Int [fake_override] + overridden: + public final fun f (): kotlin.Int declared in .A + $this: VALUE_PARAMETER name: type:.A + FUN FAKE_OVERRIDE name:testA1 visibility:public modality:FINAL <> ($this:.A, x:kotlin.Any) returnType:kotlin.Int? [fake_override] + overridden: + public final fun testA1 (x: kotlin.Any): kotlin.Int? declared in .A + $this: VALUE_PARAMETER name: type:.A + VALUE_PARAMETER name:x index:0 type:kotlin.Any + FUN FAKE_OVERRIDE name:testA2 visibility:public modality:FINAL <> ($this:.A, x:kotlin.Any) returnType:kotlin.Int? [fake_override] + overridden: + public final fun testA2 (x: kotlin.Any): kotlin.Int? declared in .A + $this: VALUE_PARAMETER name: type:.A + VALUE_PARAMETER name:x index:0 type:kotlin.Any + PROPERTY FAKE_OVERRIDE name:aVal visibility:public modality:FINAL [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.A) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:aVal visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.Int declared in .A + $this: VALUE_PARAMETER name: type:.A + 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 [fake_override,operator] declared in .A + $this: VALUE_PARAMETER name: 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 [fake_override] declared in .A + $this: VALUE_PARAMETER name: 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 [fake_override] declared in .A + $this: VALUE_PARAMETER name: type:kotlin.Any + CLASS CLASS name:GA modality:OPEN visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.GA.GA> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + CONSTRUCTOR visibility:public <> () returnType:.GA.GA> [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:GA modality:OPEN visibility:public superTypes:[kotlin.Any]' + FUN name:f visibility:public modality:FINAL <> ($this:.GA.GA>) returnType:kotlin.Int + $this: VALUE_PARAMETER name: type:.GA.GA> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun f (): kotlin.Int declared in .GA' + CONST Int type=kotlin.Int value=1 + PROPERTY name:aVal visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:aVal type:kotlin.Int visibility:private [final] + EXPRESSION_BODY + CONST Int type=kotlin.Int value=42 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:.GA.GA>) returnType:kotlin.Int + correspondingProperty: PROPERTY name:aVal visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:.GA.GA> + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in .GA' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:aVal type:kotlin.Int visibility:private [final]' type=kotlin.Int origin=null + receiver: GET_VAR ': .GA.GA> declared in .GA.' type=.GA.GA> origin=null + 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: 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: 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: type:kotlin.Any + CLASS CLASS name:GB modality:FINAL visibility:public superTypes:[.GA.GB>] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.GB.GB, S of .GB> + TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] + TYPE_PARAMETER name:S index:1 variance: superTypes:[kotlin.Any?] + CONSTRUCTOR visibility:public <> () returnType:.GB.GB, S of .GB> [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () [primary] declared in .GA' + : T of .GB + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:GB modality:FINAL visibility:public superTypes:[.GA.GB>]' + FUN name:testGB1 visibility:public modality:FINAL <> ($this:.GB.GB, S of .GB>, a:kotlin.Any) returnType:kotlin.Unit + $this: VALUE_PARAMETER name: type:.GB.GB, S of .GB> + VALUE_PARAMETER name:a index:0 type:kotlin.Any + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + TYPE_OP type=.GB origin=CAST typeOperand=.GB + GET_VAR 'a: kotlin.Any declared in .GB.testGB1' type=kotlin.Any origin=null + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public final fun f (): kotlin.Int [fake_override] declared in .GB' type=kotlin.Int origin=null + $this: TYPE_OP type=.GB<*, *> origin=IMPLICIT_CAST typeOperand=.GB<*, *> + GET_VAR 'a: kotlin.Any declared in .GB.testGB1' type=kotlin.Any origin=null + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public final fun (): kotlin.Int [fake_override] declared in .GB' type=kotlin.Int origin=GET_PROPERTY + $this: TYPE_OP type=.GB<*, *> origin=IMPLICIT_CAST typeOperand=.GB<*, *> + GET_VAR 'a: kotlin.Any declared in .GB.testGB1' type=kotlin.Any origin=null + FUN FAKE_OVERRIDE name:f visibility:public modality:FINAL <> ($this:.GA.GB>) returnType:kotlin.Int [fake_override] + overridden: + public final fun f (): kotlin.Int declared in .GA + $this: VALUE_PARAMETER name: type:.GA.GB> + PROPERTY FAKE_OVERRIDE name:aVal visibility:public modality:FINAL [fake_override,val] + FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.GA.GB>) returnType:kotlin.Int [fake_override] + correspondingProperty: PROPERTY FAKE_OVERRIDE name:aVal visibility:public modality:FINAL [fake_override,val] + overridden: + public final fun (): kotlin.Int declared in .GA + $this: VALUE_PARAMETER name: type:.GA.GB> + 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 [fake_override,operator] declared in .GA + $this: VALUE_PARAMETER name: 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 [fake_override] declared in .GA + $this: VALUE_PARAMETER name: 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 [fake_override] declared in .GA + $this: VALUE_PARAMETER name: type:kotlin.Any diff --git a/compiler/testData/ir/irText/types/smartCastOnFieldReceiverOfGenericType.txt b/compiler/testData/ir/irText/types/smartCastOnFieldReceiverOfGenericType.txt index 813daee3473..553eb17833e 100644 --- a/compiler/testData/ir/irText/types/smartCastOnFieldReceiverOfGenericType.txt +++ b/compiler/testData/ir/irText/types/smartCastOnFieldReceiverOfGenericType.txt @@ -10,7 +10,8 @@ FILE fqName: fileName:/smartCastOnFieldReceiverOfGenericType.kt TYPE_OP type=kotlin.String origin=CAST typeOperand=kotlin.String GET_VAR 'b: kotlin.Any declared in .testSetField' type=kotlin.Any origin=null SET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:value type:T of .JCell? visibility:public' type=kotlin.Unit origin=EQ - receiver: GET_VAR 'a: kotlin.Any declared in .testSetField' type=kotlin.Any origin=null + receiver: TYPE_OP type=.JCell.JCell> origin=IMPLICIT_CAST typeOperand=.JCell.JCell> + GET_VAR 'a: kotlin.Any declared in .testSetField' type=kotlin.Any origin=null value: TYPE_OP type=T of .JCell origin=IMPLICIT_CAST typeOperand=T of .JCell GET_VAR 'b: kotlin.Any declared in .testSetField' type=kotlin.Any origin=null FUN name:testGetField visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.String @@ -22,4 +23,5 @@ FILE fqName: fileName:/smartCastOnFieldReceiverOfGenericType.kt RETURN type=kotlin.Nothing from='public final fun testGetField (a: kotlin.Any): kotlin.String declared in ' TYPE_OP type=kotlin.String origin=IMPLICIT_NOTNULL typeOperand=kotlin.String GET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:value type:T of .JCell? visibility:public' type=kotlin.String? origin=GET_PROPERTY - receiver: GET_VAR 'a: kotlin.Any declared in .testGetField' type=kotlin.Any origin=null + receiver: TYPE_OP type=.JCell.JCell> origin=IMPLICIT_CAST typeOperand=.JCell.JCell> + GET_VAR 'a: kotlin.Any declared in .testGetField' type=kotlin.Any origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index a96438ffc83..ccc8c988a1c 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -1740,6 +1740,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/types/platformTypeReceiver.kt"); } + @TestMetadata("smartCastOnFakeOverrideReceiver.kt") + public void testSmartCastOnFakeOverrideReceiver() throws Exception { + runTest("compiler/testData/ir/irText/types/smartCastOnFakeOverrideReceiver.kt"); + } + @TestMetadata("smartCastOnFieldReceiverOfGenericType.kt") public void testSmartCastOnFieldReceiverOfGenericType() throws Exception { runTest("compiler/testData/ir/irText/types/smartCastOnFieldReceiverOfGenericType.kt");