FIR: set & use dispatch receiver for q. access with super reference

This commit is contained in:
Mikhail Glukhikh
2020-05-06 12:46:28 +03:00
parent b058ca635c
commit 38fc4d0f1f
15 changed files with 45 additions and 82 deletions
@@ -25,8 +25,8 @@ FILE: abstractSuperCall.kt
public abstract fun f(): R|kotlin/Unit| public abstract fun f(): R|kotlin/Unit|
public final fun t(): R|kotlin/Unit| { public final fun t(): R|kotlin/Unit| {
super<R|C|>.R|/C.h|() this@R|/A|.super<R|C|>.R|/C.h|()
super<R|C|>.R|/C.x| this@R|/A|.super<R|C|>.R|/C.x|
} }
} }
@@ -39,10 +39,10 @@ FILE: abstractSuperCall.kt
} }
public final fun g(): R|kotlin/Unit| { public final fun g(): R|kotlin/Unit| {
super<R|A|>.R|/A.f|() this@R|/B|.super<R|A|>.R|/A.f|()
super<R|A|>.R|/A.t|() this@R|/B|.super<R|A|>.R|/A.t|()
super<R|A|>.R|/A.x| this@R|/B|.super<R|A|>.R|/A.x|
super<R|A|>.R|/A.y| this@R|/B|.super<R|A|>.R|/A.y|
} }
} }
@@ -52,10 +52,10 @@ FILE: abstractSuperCall.kt
} }
public final fun r(): R|kotlin/Unit| { public final fun r(): R|kotlin/Unit| {
super<R|A|>.R|/A.f|() this@R|/J|.super<R|A|>.R|/A.f|()
super<R|A|>.R|/A.t|() this@R|/J|.super<R|A|>.R|/A.t|()
super<R|A|>.R|/A.x| this@R|/J|.super<R|A|>.R|/A.x|
super<R|A|>.R|/A.y| this@R|/J|.super<R|A|>.R|/A.y|
} }
} }
@@ -14,8 +14,8 @@ FILE: notASupertype.kt
} }
public final fun g(): R|kotlin/Unit| { public final fun g(): R|kotlin/Unit| {
super<R|kotlin/String|>.<Unresolved name: f>#() this@R|/B|.super<R|kotlin/String|>.<Unresolved name: f>#()
super<R|A|>.R|/A.f|() this@R|/B|.super<R|A|>.R|/A.f|()
} }
} }
@@ -23,11 +23,11 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt
} }
public final fun test(): R|kotlin/Unit| { public final fun test(): R|kotlin/Unit| {
super<R|IBase|>.R|/IBase.foo|() this@R|/Test|.super<R|IBase|>.R|/IBase.foo|()
super<R|IBase|>.R|/IBase.bar|() this@R|/Test|.super<R|IBase|>.R|/IBase.bar|()
super<R|IDerived|>.R|/IDerived.foo|() this@R|/Test|.super<R|IDerived|>.R|/IDerived.foo|()
super<R|IDerived|>.R|/IBase.bar|() this@R|/Test|.super<R|IDerived|>.R|/IBase.bar|()
super<R|IDerived|>.R|/IDerived.qux|() this@R|/Test|.super<R|IDerived|>.R|/IDerived.qux|()
} }
} }
@@ -37,13 +37,13 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt
} }
public final fun test(): R|kotlin/Unit| { public final fun test(): R|kotlin/Unit| {
super<R|IBase|>.R|/IBase.foo|() this@R|/Test2|.super<R|IBase|>.R|/IBase.foo|()
super<R|IBase|>.R|/IBase.bar|() this@R|/Test2|.super<R|IBase|>.R|/IBase.bar|()
super<R|AliasedIBase|>.R|/IBase.foo|() this@R|/Test2|.super<R|AliasedIBase|>.R|/IBase.foo|()
super<R|AliasedIBase|>.R|/IBase.bar|() this@R|/Test2|.super<R|AliasedIBase|>.R|/IBase.bar|()
super<R|IDerived|>.R|/IDerived.foo|() this@R|/Test2|.super<R|IDerived|>.R|/IDerived.foo|()
super<R|IDerived|>.R|/IBase.bar|() this@R|/Test2|.super<R|IDerived|>.R|/IBase.bar|()
super<R|IDerived|>.R|/IDerived.qux|() this@R|/Test2|.super<R|IDerived|>.R|/IDerived.qux|()
} }
} }
@@ -10,7 +10,7 @@ FILE: superclassNotAccessibleFromInterface.kt
} }
public abstract interface ATrait : R|A| { public abstract interface ATrait : R|A| {
public open override fun foo(): R|kotlin/Unit| { public open override fun foo(): R|kotlin/Unit| {
super<R|A|>.R|/A.foo|() this@R|/ATrait|.super<R|A|>.R|/A.foo|()
} }
} }
@@ -54,11 +54,11 @@ FILE: nestedVisibility.kt
public final fun foo(): R|kotlin/Unit| { public final fun foo(): R|kotlin/Unit| {
Q|Outer|.<Inapplicable(HIDDEN): [/Outer.PrivateNested.PrivateNested]>#() Q|Outer|.<Inapplicable(HIDDEN): [/Outer.PrivateNested.PrivateNested]>#()
super<R|Outer|>.<Inapplicable(HIDDEN): [/Outer.PrivateInner.PrivateInner]>#() this@R|/Derived|.super<R|Outer|>.<Inapplicable(HIDDEN): [/Outer.PrivateInner.PrivateInner]>#()
Q|Outer|.R|/Outer.ProtectedNested.ProtectedNested|() Q|Outer|.R|/Outer.ProtectedNested.ProtectedNested|()
super<R|Outer|>.R|/Outer.ProtectedInner.ProtectedInner|() this@R|/Derived|.super<R|Outer|>.R|/Outer.ProtectedInner.ProtectedInner|()
Q|Outer|.R|/Outer.PublicNested.PublicNested|() Q|Outer|.R|/Outer.PublicNested.PublicNested|()
super<R|Outer|>.R|/Outer.PublicInner.PublicInner|() this@R|/Derived|.super<R|Outer|>.R|/Outer.PublicInner.PublicInner|()
} }
} }
@@ -101,7 +101,7 @@ FILE: protectedVisibility.kt
} }
public final override fun foo(): R|kotlin/Int| { public final override fun foo(): R|kotlin/Int| {
^foo super<R|Generic<kotlin/Int>|>.R|FakeOverride</Generic.foo: R|kotlin/Int|>|() ^foo this@R|/DerivedGeneric|.super<R|Generic<kotlin/Int>|>.R|FakeOverride</Generic.foo: R|kotlin/Int|>|()
} }
} }
@@ -27,9 +27,9 @@ FILE: incorrectSuperCall.kt
} }
public final override fun foo(): R|kotlin/Unit| { public final override fun foo(): R|kotlin/Unit| {
super<R|A|R|B|>.R|/B.foo|() this@R|/C|.super<R|A|R|B|>.R|/B.foo|()
super<R|A|R|B|>.<Ambiguity: bar, [/A.bar, /B.bar]>#() this@R|/C|.super<R|A|R|B|>.<Ambiguity: bar, [/A.bar, /B.bar]>#()
super<R|A|R|B|>.R|/B.baz|() this@R|/C|.super<R|A|R|B|>.R|/B.baz|()
this@R|/C|.R|/A.baz|() this@R|/C|.R|/A.baz|()
} }
@@ -96,31 +96,6 @@ class Fir2IrConversionScope {
return irClass.thisReceiver return irClass.thisReceiver
} }
fun dispatchReceiverParameter(label: String): IrValueParameter? {
for (function in functionStack.asReversed()) {
if (!function.name.isSpecial && function.name.identifier == label) {
function.dispatchReceiverParameter?.let { return it }
}
}
for (irClass in classStack.asReversed()) {
if (!irClass.name.isSpecial && irClass.name.identifier == label) {
return irClass.thisReceiver
}
}
return null
}
fun lastDispatchReceiverParameter(): IrValueParameter? {
// Use the dispatch receiver of the containing/enclosing functions (from the last to the first)
for (function in functionStack.asReversed()) {
function.dispatchReceiverParameter?.let { return it }
}
// Use the dispatch receiver of the containing class
val lastClass = classStack.lastOrNull()
return lastClass?.thisReceiver
}
fun lastClass(): IrClass? = classStack.lastOrNull() fun lastClass(): IrClass? = classStack.lastOrNull()
fun lastSubject(): IrVariable = subjectVariableStack.last() fun lastSubject(): IrVariable = subjectVariableStack.last()
@@ -30,10 +30,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.psi.KtPropertyDelegate import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
@@ -165,21 +162,15 @@ internal class CallAndReferenceGenerator(
conversionScope conversionScope
) )
return typeRef.convertWithOffsets { startOffset, endOffset -> return typeRef.convertWithOffsets { startOffset, endOffset ->
val dispatchReceiver = qualifiedAccess.dispatchReceiver
if (qualifiedAccess.calleeReference is FirSuperReference) { if (qualifiedAccess.calleeReference is FirSuperReference) {
val superReference = qualifiedAccess.calleeReference as FirSuperReference if (typeRef !is FirComposedSuperTypeRef && dispatchReceiver !is FirNoReceiverExpression) {
if (typeRef !is FirComposedSuperTypeRef) { return@convertWithOffsets visitor.convertToIrExpression(dispatchReceiver)
val label = superReference.labelName
val dispatchReceiver =
if (label != null) conversionScope.dispatchReceiverParameter(label)
else conversionScope.lastDispatchReceiverParameter()
if (dispatchReceiver != null) {
return@convertWithOffsets IrGetValueImpl(startOffset, endOffset, dispatchReceiver.type, dispatchReceiver.symbol)
}
} }
} }
var superQualifierSymbol: IrClassSymbol? = null var superQualifierSymbol: IrClassSymbol? = null
if (qualifiedAccess.dispatchReceiver is FirQualifiedAccess) { if (dispatchReceiver is FirQualifiedAccess) {
val dispatchReceiverReference = (qualifiedAccess.dispatchReceiver as FirQualifiedAccess).calleeReference val dispatchReceiverReference = dispatchReceiver.calleeReference
if (dispatchReceiverReference is FirSuperReference) { if (dispatchReceiverReference is FirSuperReference) {
val coneSuperType = dispatchReceiverReference.superTypeRef.coneTypeSafe<ConeClassLikeType>() val coneSuperType = dispatchReceiverReference.superTypeRef.coneTypeSafe<ConeClassLikeType>()
(coneSuperType?.lookupTag?.toSymbol(session) as? FirClassSymbol<*>)?.let { (coneSuperType?.lookupTag?.toSymbol(session) as? FirClassSymbol<*>)?.let {
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.symbols.invoke import org.jetbrains.kotlin.fir.symbols.invoke
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.* import org.jetbrains.kotlin.fir.types.builder.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.visitors.* import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -81,6 +80,13 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
qualifiedAccessExpression qualifiedAccessExpression
} }
is FirSuperReference -> { is FirSuperReference -> {
val labelName = callee.labelName
val implicitReceiver =
if (labelName != null) implicitReceiverStack[labelName] as? ImplicitDispatchReceiverValue
else implicitReceiverStack.lastDispatchReceiver()
implicitReceiver?.receiverExpression?.let {
qualifiedAccessExpression.transformDispatchReceiver(StoreReceiver, it)
}
when (val superTypeRef = callee.superTypeRef) { when (val superTypeRef = callee.superTypeRef) {
is FirResolvedTypeRef -> { is FirResolvedTypeRef -> {
qualifiedAccessExpression.resultType = superTypeRef qualifiedAccessExpression.resultType = superTypeRef
@@ -90,10 +96,6 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
qualifiedAccessExpression.resultType = callee.superTypeRef qualifiedAccessExpression.resultType = callee.superTypeRef
} }
else -> { else -> {
val labelName = callee.labelName
val implicitReceiver =
if (labelName != null) implicitReceiverStack[labelName] as? ImplicitDispatchReceiverValue
else implicitReceiverStack.lastDispatchReceiver()
val superTypeRefs = implicitReceiver?.boundSymbol?.phasedFir?.superTypeRefs val superTypeRefs = implicitReceiver?.boundSymbol?.phasedFir?.superTypeRefs
val resultType = when { val resultType = when {
superTypeRefs?.isNotEmpty() != true -> { superTypeRefs?.isNotEmpty() != true -> {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class A(val value: String) { open class A(val value: String) {
inner class B(val s: String) { inner class B(val s: String) {
val result = value + "_" + s val result = value + "_" + s
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface BK { interface BK {
fun foo(): String fun foo(): String
fun bar(): String fun bar(): String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
//inspired by kt3492 //inspired by kt3492
interface BK { interface BK {
fun foo(): String fun foo(): String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Base { interface Base {
val foo: String val foo: String
fun bar(): String fun bar(): String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
//inspired by kt3492 //inspired by kt3492
interface Base { interface Base {
val foo: String val foo: String