[FIR2IR] Properly calculate the type of delegated function call

```
interface A {
    fun <T> foo(): T
}

class B(val a: A) : A by A {
    generated fun <T'> foo(): T' {
        return a.foo() // <------
    }
}
```

There was a problem that type of generated delegated call used
  an unsubstituted type of the original delegated declaration, which led
  to a situation when (see example) type of call `a.foo()` was not `T'`
  but `T`, which led to incorrect IR and further exceptions on backend

^KT-64257 Fixed
^KT-64284 Obsolete
This commit is contained in:
Dmitriy Novozhilov
2023-12-14 17:39:41 +02:00
committed by Space Team
parent c48753900c
commit 94c46d384a
28 changed files with 206 additions and 148 deletions
@@ -16784,6 +16784,12 @@ public class LLFirBlackBoxCodegenBasedTestGenerated extends AbstractLLFirBlackBo
runTest("compiler/testData/codegen/box/delegation/doubleDelegationEqualsHashcode.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -16784,6 +16784,12 @@ public class LLFirReversedBlackBoxCodegenBasedTestGenerated extends AbstractLLFi
runTest("compiler/testData/codegen/box/delegation/doubleDelegationEqualsHashcode.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -11,9 +11,11 @@ import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -51,8 +53,9 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
private val basePropertySymbols: MutableMap<IrProperty, Collection<FirPropertySymbol>> = mutableMapOf()
private data class DeclarationBodyInfo(
val declaration: IrDeclaration,
val field: IrField,
val delegatedFirDeclaration: FirCallableDeclaration,
val delegatedIrDeclaration: IrDeclaration,
val irField: IrField,
val delegateToSymbol: FirCallableSymbol<*>,
val delegateToLookupTag: ConeClassLikeLookupTag?
)
@@ -60,36 +63,36 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
private val bodiesInfo = mutableListOf<DeclarationBodyInfo>()
fun generateBodies() {
for ((declaration, irField, delegateToFirSymbol, delegateToLookupTag) in bodiesInfo) {
val delegatedDeclarationType = delegateToFirSymbol.fir.returnTypeRef.coneType.fullyExpandedType(session)
val callTypeCanBeNullable = Fir2IrImplicitCastInserter.typeCanBeEnhancedOrFlexibleNullable(delegatedDeclarationType)
when (declaration) {
for ((delegatedFirDeclaration, delegatedIrDeclaration, irField, delegateToFirSymbol, delegateToLookupTag) in bodiesInfo) {
when (delegatedIrDeclaration) {
is IrSimpleFunction -> {
val delegateToIrFunctionSymbol = declarationStorage.getIrFunctionSymbol(
delegateToFirSymbol as FirNamedFunctionSymbol, delegateToLookupTag
delegateToFirSymbol.unwrapCallRepresentative(delegateToLookupTag) as FirNamedFunctionSymbol,
delegateToLookupTag
) as? IrSimpleFunctionSymbol ?: continue
val body = createDelegateBody(
irField, declaration, delegateToFirSymbol.fir, delegateToIrFunctionSymbol,
callTypeCanBeNullable, isSetter = false
irField, delegatedFirDeclaration, delegatedIrDeclaration, delegateToFirSymbol.fir, delegateToIrFunctionSymbol,
isSetter = false
)
declaration.body = body
delegatedIrDeclaration.body = body
}
is IrProperty -> {
val delegateToIrPropertySymbol = declarationStorage.getIrPropertySymbol(
delegateToFirSymbol as FirPropertySymbol, delegateToLookupTag
delegateToFirSymbol.unwrapCallRepresentative(delegateToLookupTag) as FirPropertySymbol,
delegateToLookupTag
) as? IrPropertySymbol ?: continue
val delegateToGetterSymbol = declarationStorage.findGetterOfProperty(delegateToIrPropertySymbol)!!
val getter = declaration.getter!!
val getter = delegatedIrDeclaration.getter!!
getter.body = createDelegateBody(
irField, getter, delegateToFirSymbol.fir, delegateToGetterSymbol,
callTypeCanBeNullable, isSetter = false
irField, delegatedFirDeclaration, getter, delegateToFirSymbol.fir, delegateToGetterSymbol,
isSetter = false
)
if (declaration.isVar) {
if (delegatedIrDeclaration.isVar) {
val delegateToSetterSymbol = declarationStorage.findSetterOfProperty(delegateToIrPropertySymbol)!!
val setter = declaration.setter!!
val setter = delegatedIrDeclaration.setter!!
setter.body = createDelegateBody(
irField, setter, delegateToFirSymbol.fir, delegateToSetterSymbol,
callTypeCanBeNullable = false, isSetter = true
irField, delegatedFirDeclaration, setter, delegateToFirSymbol.fir, delegateToSetterSymbol,
isSetter = true
)
}
}
@@ -130,20 +133,16 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
val delegateToLookupTag = delegateToSymbol.dispatchReceiverClassLookupTagOrNull()
?: return@processAllFunctions
val irSubFunction = generateDelegatedFunction(
subClass, firSubClass, functionSymbol.fir
)
bodiesInfo += DeclarationBodyInfo(irSubFunction, irField, delegateToSymbol, delegateToLookupTag)
declarationStorage.cacheDelegationFunction(functionSymbol.fir, irSubFunction)
val delegatedFunction = functionSymbol.fir
val irSubFunction = generateDelegatedFunction(subClass, firSubClass, delegatedFunction)
bodiesInfo += DeclarationBodyInfo(delegatedFunction, irSubFunction, irField, delegateToSymbol, delegateToLookupTag)
declarationStorage.cacheDelegationFunction(delegatedFunction, irSubFunction)
}
subClassScope.processAllProperties { propertySymbol ->
if (propertySymbol !is FirPropertySymbol) return@processAllProperties
val unwrapped =
propertySymbol.unwrapDelegateTarget(subClassLookupTag, firField)
?: return@processAllProperties
val unwrapped = propertySymbol.unwrapDelegateTarget(subClassLookupTag, firField) ?: return@processAllProperties
val delegateToSymbol = findDelegateToSymbol(
unwrapped.symbol,
@@ -156,14 +155,11 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
delegateToScope::processOverriddenProperties
) ?: return@processAllProperties
val delegateToLookupTag = delegateToSymbol.dispatchReceiverClassLookupTagOrNull()
?: return@processAllProperties
val irSubProperty = generateDelegatedProperty(
subClass, firSubClass, propertySymbol.fir
)
bodiesInfo += DeclarationBodyInfo(irSubProperty, irField, delegateToSymbol, delegateToLookupTag)
declarationStorage.cacheDelegatedProperty(propertySymbol.fir, irSubProperty)
val delegateToLookupTag = delegateToSymbol.dispatchReceiverClassLookupTagOrNull() ?: return@processAllProperties
val delegatedProperty = propertySymbol.fir
val irSubProperty = generateDelegatedProperty(subClass, firSubClass, delegatedProperty)
bodiesInfo += DeclarationBodyInfo(delegatedProperty, irSubProperty, irField, delegateToSymbol, delegateToLookupTag)
declarationStorage.cacheDelegatedProperty(delegatedProperty, irSubProperty)
}
}
@@ -174,19 +170,24 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
): S? {
val unwrappedSymbol = symbol.unwrapUseSiteSubstitutionOverrides()
var result: S? = null
// The purpose of this code is to find member in delegate-to scope
// which matches or overrides unwrappedSymbol (which is in turn taken from subclass scope).
/*
* The purpose of this code is to find member in delegate-to scope
* which matches or overrides unwrappedSymbol (which is in turn taken from subclass scope).
*
* Note that it's important to not unwrap call-site substitution override of the found function, because
* later it will be used to compute the proper substituted type for call of this function
*/
processCallables(unwrappedSymbol.name) { candidateSymbol ->
if (result != null) return@processCallables
val unwrappedCandidateSymbol = candidateSymbol.unwrapUseSiteSubstitutionOverrides()
if (unwrappedCandidateSymbol === unwrappedSymbol) {
result = unwrappedCandidateSymbol
result = candidateSymbol
return@processCallables
}
processOverridden(candidateSymbol) { overriddenSymbol ->
val unwrappedOverriddenSymbol = overriddenSymbol.unwrapUseSiteSubstitutionOverrides()
if (unwrappedOverriddenSymbol === unwrappedSymbol) {
result = unwrappedCandidateSymbol
result = candidateSymbol
ProcessorAction.STOP
} else {
ProcessorAction.NEXT
@@ -277,23 +278,38 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
*/
private fun createDelegateBody(
irField: IrField,
delegateFunction: IrSimpleFunction,
delegatedFirDeclaration: FirCallableDeclaration,
delegatedIrFunction: IrSimpleFunction,
originalFirDeclaration: FirCallableDeclaration,
originalFunctionSymbol: IrSimpleFunctionSymbol,
callTypeCanBeNullable: Boolean,
isSetter: Boolean
): IrBlockBody {
val startOffset = SYNTHETIC_OFFSET
val endOffset = SYNTHETIC_OFFSET
val body = irFactory.createBlockBody(startOffset, endOffset)
val typeOrigin = when {
originalFirDeclaration is FirPropertyAccessor && originalFirDeclaration.isSetter -> ConversionTypeOrigin.SETTER
else -> ConversionTypeOrigin.DEFAULT
}
val callTypeCanBeNullable: Boolean
val callReturnType = when (isSetter) {
false -> originalFirDeclaration.returnTypeRef.toIrType(typeOrigin)
true -> irBuiltIns.unitType
false -> {
val substitution = originalFirDeclaration.typeParameters.zip(delegatedFirDeclaration.typeParameters)
.map { (original, delegated) ->
original.symbol to delegated.symbol.defaultType
}.toMap()
val substitutor = substitutorByMap(substitution, session)
val substitutedType = substitutor.substituteOrSelf(originalFirDeclaration.returnTypeRef.coneType)
callTypeCanBeNullable = Fir2IrImplicitCastInserter.typeCanBeEnhancedOrFlexibleNullable(substitutedType)
substitutedType.toIrType(typeOrigin)
}
true -> {
callTypeCanBeNullable = false
irBuiltIns.unitType
}
}
val irCall = IrCallImpl(
@@ -310,8 +326,8 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
irField.type,
IrGetValueImpl(
startOffset, endOffset,
delegateFunction.dispatchReceiverParameter?.type!!,
delegateFunction.dispatchReceiverParameter?.symbol!!
delegatedIrFunction.dispatchReceiverParameter?.type!!,
delegatedIrFunction.dispatchReceiverParameter?.symbol!!
)
)
@@ -327,16 +343,16 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
}
extensionReceiver =
delegateFunction.extensionReceiverParameter?.let { extensionReceiver ->
delegatedIrFunction.extensionReceiverParameter?.let { extensionReceiver ->
IrGetValueImpl(startOffset, endOffset, extensionReceiver.type, extensionReceiver.symbol)
}
delegateFunction.valueParameters.forEach {
delegatedIrFunction.valueParameters.forEach {
putValueArgument(it.index, IrGetValueImpl(startOffset, endOffset, it.type, it.symbol))
}
for (index in originalFirDeclaration.typeParameters.indices) {
putTypeArgument(
index, IrSimpleTypeImpl(
delegateFunction.typeParameters[index].symbol,
delegatedIrFunction.typeParameters[index].symbol,
hasQuestionMark = false,
arguments = emptyList(),
annotations = emptyList()
@@ -344,7 +360,7 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
)
}
}
val resultType = delegateFunction.returnType
val resultType = delegatedIrFunction.returnType
val irCastOrCall =
if (callTypeCanBeNullable && !resultType.isNullable()) Fir2IrImplicitCastInserter.implicitNotNullCast(irCall)
@@ -353,7 +369,7 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
if (isSetter || originalDeclarationReturnType.isUnit || originalDeclarationReturnType.isNothing) {
body.statements.add(irCastOrCall)
} else {
val irReturn = IrReturnImpl(startOffset, endOffset, irBuiltIns.nothingType, delegateFunction.symbol, irCastOrCall)
val irReturn = IrReturnImpl(startOffset, endOffset, irBuiltIns.nothingType, delegatedIrFunction.symbol, irCastOrCall)
body.statements.add(irReturn)
}
return body
@@ -16725,6 +16725,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/delegation/doubleDelegationEqualsHashcode.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -16725,6 +16725,12 @@ public class FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated
runTest("compiler/testData/codegen/box/delegation/doubleDelegationEqualsHashcode.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -16725,6 +16725,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/delegation/doubleDelegationEqualsHashcode.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -23,4 +23,4 @@ fun test(c: C, d: D): String {
return object: A by intersection {}.foo().toString()
}
fun box() = test(C(), D())
fun box() = test(C(), D())
@@ -0,0 +1,15 @@
// ISSUE: KT-64257
interface Base {
fun <R> fold(initial: R, operation: (R, String) -> R): R = operation(initial, "K")
}
interface Derived<T> : Base
class Impl<T> : Derived<T>
fun box(): String {
val impl = Impl<String>()
val delegated = object : Derived<String> by impl {}
return delegated.fold("O") { a, b -> a + b }
}
@@ -207,7 +207,7 @@ FILE fqName:<root> fileName:/delegatedPropertyWithMultipleOverriddens_generics.k
$this: VALUE_PARAMETER name:<this> type:<root>.MC
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun foo (): kotlin.String declared in <root>.MC'
CALL 'public open fun foo (): E6 of <root>.MyArrayList declared in <root>.MyArrayList' type=E6 of <root>.MyArrayList origin=null
CALL 'public open fun foo (): E6 of <root>.MyArrayList declared in <root>.MyArrayList' type=kotlin.String origin=null
$this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:<root>.MyArrayList<kotlin.String> visibility:private [final]' type=<root>.MyArrayList<kotlin.String> origin=null
receiver: GET_VAR '<this>: <root>.MC declared in <root>.MC.foo' type=<root>.MC origin=null
PROPERTY DELEGATED_MEMBER name:bar visibility:public modality:OPEN [val]
@@ -220,7 +220,7 @@ FILE fqName:<root> fileName:/delegatedPropertyWithMultipleOverriddens_generics.k
$this: VALUE_PARAMETER name:<this> type:<root>.MC
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-bar> (): kotlin.String declared in <root>.MC'
CALL 'public open fun <get-bar> (): E6 of <root>.MyArrayList declared in <root>.MyArrayList' type=E6 of <root>.MyArrayList origin=null
CALL 'public open fun <get-bar> (): E6 of <root>.MyArrayList declared in <root>.MyArrayList' type=kotlin.String origin=null
$this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:<root>.MyArrayList<kotlin.String> visibility:private [final]' type=<root>.MyArrayList<kotlin.String> origin=null
receiver: GET_VAR '<this>: <root>.MC declared in <root>.MC.<get-bar>' type=<root>.MC origin=null
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
@@ -75,7 +75,7 @@ FILE fqName:<root> fileName:/delegatedGenericImplementation.kt
$receiver: VALUE_PARAMETER name:<this> type:C of <root>.Test1.<get-id>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-id> <C> (): kotlin.collections.Map<E of <root>.Test1, C of <root>.Test1.<get-id>>? declared in <root>.Test1'
CALL 'public abstract fun <get-id> <C> (): kotlin.collections.Map<A of <root>.IBase, C of <root>.IBase.<get-id>>? declared in <root>.IBase' type=kotlin.collections.Map<A of <root>.IBase, C of <root>.IBase.<get-id>>? origin=null
CALL 'public abstract fun <get-id> <C> (): kotlin.collections.Map<A of <root>.IBase, C of <root>.IBase.<get-id>>? declared in <root>.IBase' type=kotlin.collections.Map<E of <root>.Test1, C of <root>.Test1.<get-id>>? origin=null
<C>: C of <root>.Test1.<get-id>
$this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:<root>.IBase<E of <root>.Test1> visibility:private [final]' type=<root>.IBase<E of <root>.Test1> origin=null
receiver: GET_VAR '<this>: <root>.Test1<E of <root>.Test1> declared in <root>.Test1.<get-id>' type=<root>.Test1<E of <root>.Test1> origin=null
@@ -92,7 +92,7 @@ FILE fqName:<root> fileName:/delegatedGenericImplementation.kt
$receiver: VALUE_PARAMETER name:<this> type:kotlin.collections.List<D of <root>.Test1.<get-x>>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-x> <D> (): D of <root>.Test1.<get-x>? declared in <root>.Test1'
CALL 'public abstract fun <get-x> <D> (): D of <root>.IBase.<get-x>? declared in <root>.IBase' type=D of <root>.IBase.<get-x>? origin=null
CALL 'public abstract fun <get-x> <D> (): D of <root>.IBase.<get-x>? declared in <root>.IBase' type=D of <root>.Test1.<get-x>? origin=null
<D>: D of <root>.Test1.<get-x>
$this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:<root>.IBase<E of <root>.Test1> visibility:private [final]' type=<root>.IBase<E of <root>.Test1> origin=null
receiver: GET_VAR '<this>: <root>.Test1<E of <root>.Test1> declared in <root>.Test1.<get-x>' type=<root>.Test1<E of <root>.Test1> origin=null
@@ -177,7 +177,7 @@ FILE fqName:<root> fileName:/delegatedGenericImplementation.kt
$receiver: VALUE_PARAMETER name:<this> type:C of <root>.Test2.<get-id>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-id> <C> (): kotlin.collections.Map<kotlin.String, C of <root>.Test2.<get-id>>? declared in <root>.Test2'
CALL 'public abstract fun <get-id> <C> (): kotlin.collections.Map<A of <root>.IBase, C of <root>.IBase.<get-id>>? declared in <root>.IBase' type=kotlin.collections.Map<A of <root>.IBase, C of <root>.IBase.<get-id>>? origin=null
CALL 'public abstract fun <get-id> <C> (): kotlin.collections.Map<A of <root>.IBase, C of <root>.IBase.<get-id>>? declared in <root>.IBase' type=kotlin.collections.Map<kotlin.String, C of <root>.Test2.<get-id>>? origin=null
<C>: C of <root>.Test2.<get-id>
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:j type:<root>.IBase<kotlin.String> visibility:private' type=<root>.IBase<kotlin.String> origin=null
receiver: GET_VAR '<this>: <root>.Test2 declared in <root>.Test2.<get-id>' type=<root>.Test2 origin=null
@@ -194,7 +194,7 @@ FILE fqName:<root> fileName:/delegatedGenericImplementation.kt
$receiver: VALUE_PARAMETER name:<this> type:kotlin.collections.List<D of <root>.Test2.<get-x>>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-x> <D> (): D of <root>.Test2.<get-x>? declared in <root>.Test2'
CALL 'public abstract fun <get-x> <D> (): D of <root>.IBase.<get-x>? declared in <root>.IBase' type=D of <root>.IBase.<get-x>? origin=null
CALL 'public abstract fun <get-x> <D> (): D of <root>.IBase.<get-x>? declared in <root>.IBase' type=D of <root>.Test2.<get-x>? origin=null
<D>: D of <root>.Test2.<get-x>
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:j type:<root>.IBase<kotlin.String> visibility:private' type=<root>.IBase<kotlin.String> origin=null
receiver: GET_VAR '<this>: <root>.Test2 declared in <root>.Test2.<get-x>' type=<root>.Test2 origin=null
@@ -1,65 +0,0 @@
FILE fqName:<root> fileName:/kt35550.kt
CLASS INTERFACE name:I modality:ABSTRACT visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.I
PROPERTY name:id visibility:public modality:OPEN [val]
FUN name:<get-id> visibility:public modality:OPEN <T> ($this:<root>.I, $receiver:T of <root>.I.<get-id>) returnType:T of <root>.I.<get-id>
correspondingProperty: PROPERTY name:id visibility:public modality:OPEN [val]
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
$this: VALUE_PARAMETER name:<this> type:<root>.I
$receiver: VALUE_PARAMETER name:<this> type:T of <root>.I.<get-id>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-id> <T> (): T of <root>.I.<get-id> declared in <root>.I'
GET_VAR '<this>: T of <root>.I.<get-id> declared in <root>.I.<get-id>' type=T of <root>.I.<get-id> 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 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
CLASS CLASS name:A modality:FINAL visibility:public superTypes:[<root>.I]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.A
CONSTRUCTOR visibility:public <> (i:<root>.I) returnType:<root>.A [primary]
VALUE_PARAMETER name:i index:0 type:<root>.I
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:A modality:FINAL visibility:public superTypes:[<root>.I]'
FIELD DELEGATE name:$$delegate_0 type:<root>.I visibility:private [final]
EXPRESSION_BODY
GET_VAR 'i: <root>.I declared in <root>.A.<init>' type=<root>.I origin=null
PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val]
overridden:
public open id: T of <root>.I.<get-id>
FUN DELEGATED_MEMBER name:<get-id> visibility:public modality:OPEN <T> ($this:<root>.A, $receiver:T of <root>.A.<get-id>) returnType:T of <root>.A.<get-id>
correspondingProperty: PROPERTY DELEGATED_MEMBER name:id visibility:public modality:OPEN [val]
overridden:
public open fun <get-id> <T> (): T of <root>.I.<get-id> declared in <root>.I
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?] reified:false
$this: VALUE_PARAMETER name:<this> type:<root>.A
$receiver: VALUE_PARAMETER name:<this> type:T of <root>.A.<get-id>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-id> <T> (): T of <root>.A.<get-id> declared in <root>.A'
CALL 'public open fun <get-id> <T> (): T of <root>.I.<get-id> declared in <root>.I' type=T of <root>.I.<get-id> origin=null
<T>: T of <root>.A.<get-id>
$this: GET_FIELD 'FIELD DELEGATE name:$$delegate_0 type:<root>.I visibility:private [final]' type=<root>.I origin=null
receiver: GET_VAR '<this>: <root>.A declared in <root>.A.<get-id>' type=<root>.A origin=null
$receiver: GET_VAR '<this>: T of <root>.A.<get-id> declared in <root>.A.<get-id>' type=T of <root>.A.<get-id> 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 declared in <root>.I
$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 <root>.I
$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 <root>.I
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
@@ -1,22 +0,0 @@
interface I {
val <T : Any?> T.id: T
get(): T {
return <this>
}
}
class A : I {
constructor(i: I) /* primary */ {
super/*Any*/()
/* <init>() */
}
private /* final field */ val $$delegate_0: I = i
override val <T : Any?> T.id: T
override get(): T {
return (<this>.#$$delegate_0, <this>).<get-id><T>()
}
}
+1
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface I {
val <T> T.id: T
get() = this
+4 -4
View File
@@ -48,7 +48,7 @@ FILE fqName:<root> fileName:/kt43342.kt
VALUE_PARAMETER name:key index:0 type:K of <root>.ControlFlowInfo
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun get (key: K of <root>.ControlFlowInfo): V of <root>.ControlFlowInfo? declared in <root>.ControlFlowInfo'
CALL 'public abstract fun get (key: K of kotlin.collections.Map): V of kotlin.collections.Map? declared in kotlin.collections.Map' type=V of kotlin.collections.Map? origin=null
CALL 'public abstract fun get (key: K of kotlin.collections.Map): V of kotlin.collections.Map? declared in kotlin.collections.Map' type=V of <root>.ControlFlowInfo? origin=null
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> visibility:private [final]' type=kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
receiver: GET_VAR '<this>: <root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> declared in <root>.ControlFlowInfo.get' type=<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
key: GET_VAR 'key: K of <root>.ControlFlowInfo declared in <root>.ControlFlowInfo.get' type=K of <root>.ControlFlowInfo origin=null
@@ -71,7 +71,7 @@ FILE fqName:<root> fileName:/kt43342.kt
$this: VALUE_PARAMETER name:<this> type:<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-entries> (): kotlin.collections.Set<kotlin.collections.Map.Entry<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>> declared in <root>.ControlFlowInfo'
CALL 'public abstract fun <get-entries> (): kotlin.collections.Set<kotlin.collections.Map.Entry<K of kotlin.collections.Map, V of kotlin.collections.Map>> declared in kotlin.collections.Map' type=kotlin.collections.Set<kotlin.collections.Map.Entry<K of kotlin.collections.Map, V of kotlin.collections.Map>> origin=null
CALL 'public abstract fun <get-entries> (): kotlin.collections.Set<kotlin.collections.Map.Entry<K of kotlin.collections.Map, V of kotlin.collections.Map>> declared in kotlin.collections.Map' type=kotlin.collections.Set<kotlin.collections.Map.Entry<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>> origin=null
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> visibility:private [final]' type=kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
receiver: GET_VAR '<this>: <root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> declared in <root>.ControlFlowInfo.<get-entries>' type=<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
PROPERTY DELEGATED_MEMBER name:keys visibility:public modality:OPEN [val]
@@ -84,7 +84,7 @@ FILE fqName:<root> fileName:/kt43342.kt
$this: VALUE_PARAMETER name:<this> type:<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-keys> (): kotlin.collections.Set<K of <root>.ControlFlowInfo> declared in <root>.ControlFlowInfo'
CALL 'public abstract fun <get-keys> (): kotlin.collections.Set<K of kotlin.collections.Map> declared in kotlin.collections.Map' type=kotlin.collections.Set<K of kotlin.collections.Map> origin=null
CALL 'public abstract fun <get-keys> (): kotlin.collections.Set<K of kotlin.collections.Map> declared in kotlin.collections.Map' type=kotlin.collections.Set<K of <root>.ControlFlowInfo> origin=null
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> visibility:private [final]' type=kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
receiver: GET_VAR '<this>: <root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> declared in <root>.ControlFlowInfo.<get-keys>' type=<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
PROPERTY DELEGATED_MEMBER name:size visibility:public modality:OPEN [val]
@@ -110,7 +110,7 @@ FILE fqName:<root> fileName:/kt43342.kt
$this: VALUE_PARAMETER name:<this> type:<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun <get-values> (): kotlin.collections.Collection<V of <root>.ControlFlowInfo> declared in <root>.ControlFlowInfo'
CALL 'public abstract fun <get-values> (): kotlin.collections.Collection<V of kotlin.collections.Map> declared in kotlin.collections.Map' type=kotlin.collections.Collection<V of kotlin.collections.Map> origin=null
CALL 'public abstract fun <get-values> (): kotlin.collections.Collection<V of kotlin.collections.Map> declared in kotlin.collections.Map' type=kotlin.collections.Collection<V of <root>.ControlFlowInfo> origin=null
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> visibility:private [final]' type=kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
receiver: GET_VAR '<this>: <root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> declared in <root>.ControlFlowInfo.<get-values>' type=<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
FUN FAKE_OVERRIDE name:getOrDefault visibility:public modality:OPEN <> ($this:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>, key:K of <root>.ControlFlowInfo, defaultValue:V of <root>.ControlFlowInfo) returnType:V of <root>.ControlFlowInfo [fake_override]
@@ -16359,6 +16359,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/delegation/doubleDelegationEqualsHashcode.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -16725,6 +16725,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/delegation/doubleDelegationEqualsHashcode.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -16725,6 +16725,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
runTest("compiler/testData/codegen/box/delegation/doubleDelegationEqualsHashcode.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -13794,6 +13794,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/delegation/differentModules.kt");
}
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericProperty.kt");
@@ -12681,6 +12681,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -12681,6 +12681,12 @@ public class FirJsES6CodegenBoxTestGenerated extends AbstractFirJsES6CodegenBoxT
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -12681,6 +12681,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -12681,6 +12681,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -13736,6 +13736,12 @@ public class FirNativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTe
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -14050,6 +14050,12 @@ public class FirNativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenB
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -13422,6 +13422,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -13737,6 +13737,12 @@ public class NativeCodegenBoxTestNoPLGenerated extends AbstractNativeCodegenBoxT
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -12657,6 +12657,12 @@ public class FirWasmCodegenBoxTestGenerated extends AbstractFirWasmCodegenBoxTes
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {
@@ -12657,6 +12657,12 @@ public class K1WasmCodegenBoxTestGenerated extends AbstractK1WasmCodegenBoxTest
runTest("compiler/testData/codegen/box/delegation/delegationWithPrivateConstructor.kt");
}
@Test
@TestMetadata("genericFunctionInGenericInterface.kt")
public void testGenericFunctionInGenericInterface() throws Exception {
runTest("compiler/testData/codegen/box/delegation/genericFunctionInGenericInterface.kt");
}
@Test
@TestMetadata("genericProperty.kt")
public void testGenericProperty() throws Exception {