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 final fun t(): R|kotlin/Unit| {
super<R|C|>.R|/C.h|()
super<R|C|>.R|/C.x|
this@R|/A|.super<R|C|>.R|/C.h|()
this@R|/A|.super<R|C|>.R|/C.x|
}
}
@@ -39,10 +39,10 @@ FILE: abstractSuperCall.kt
}
public final fun g(): R|kotlin/Unit| {
super<R|A|>.R|/A.f|()
super<R|A|>.R|/A.t|()
super<R|A|>.R|/A.x|
super<R|A|>.R|/A.y|
this@R|/B|.super<R|A|>.R|/A.f|()
this@R|/B|.super<R|A|>.R|/A.t|()
this@R|/B|.super<R|A|>.R|/A.x|
this@R|/B|.super<R|A|>.R|/A.y|
}
}
@@ -52,10 +52,10 @@ FILE: abstractSuperCall.kt
}
public final fun r(): R|kotlin/Unit| {
super<R|A|>.R|/A.f|()
super<R|A|>.R|/A.t|()
super<R|A|>.R|/A.x|
super<R|A|>.R|/A.y|
this@R|/J|.super<R|A|>.R|/A.f|()
this@R|/J|.super<R|A|>.R|/A.t|()
this@R|/J|.super<R|A|>.R|/A.x|
this@R|/J|.super<R|A|>.R|/A.y|
}
}
@@ -14,8 +14,8 @@ FILE: notASupertype.kt
}
public final fun g(): R|kotlin/Unit| {
super<R|kotlin/String|>.<Unresolved name: f>#()
super<R|A|>.R|/A.f|()
this@R|/B|.super<R|kotlin/String|>.<Unresolved name: f>#()
this@R|/B|.super<R|A|>.R|/A.f|()
}
}
@@ -23,11 +23,11 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt
}
public final fun test(): R|kotlin/Unit| {
super<R|IBase|>.R|/IBase.foo|()
super<R|IBase|>.R|/IBase.bar|()
super<R|IDerived|>.R|/IDerived.foo|()
super<R|IDerived|>.R|/IBase.bar|()
super<R|IDerived|>.R|/IDerived.qux|()
this@R|/Test|.super<R|IBase|>.R|/IBase.foo|()
this@R|/Test|.super<R|IBase|>.R|/IBase.bar|()
this@R|/Test|.super<R|IDerived|>.R|/IDerived.foo|()
this@R|/Test|.super<R|IDerived|>.R|/IBase.bar|()
this@R|/Test|.super<R|IDerived|>.R|/IDerived.qux|()
}
}
@@ -37,13 +37,13 @@ FILE: qualifiedSupertypeExtendedByOtherSupertype.kt
}
public final fun test(): R|kotlin/Unit| {
super<R|IBase|>.R|/IBase.foo|()
super<R|IBase|>.R|/IBase.bar|()
super<R|AliasedIBase|>.R|/IBase.foo|()
super<R|AliasedIBase|>.R|/IBase.bar|()
super<R|IDerived|>.R|/IDerived.foo|()
super<R|IDerived|>.R|/IBase.bar|()
super<R|IDerived|>.R|/IDerived.qux|()
this@R|/Test2|.super<R|IBase|>.R|/IBase.foo|()
this@R|/Test2|.super<R|IBase|>.R|/IBase.bar|()
this@R|/Test2|.super<R|AliasedIBase|>.R|/IBase.foo|()
this@R|/Test2|.super<R|AliasedIBase|>.R|/IBase.bar|()
this@R|/Test2|.super<R|IDerived|>.R|/IDerived.foo|()
this@R|/Test2|.super<R|IDerived|>.R|/IBase.bar|()
this@R|/Test2|.super<R|IDerived|>.R|/IDerived.qux|()
}
}
@@ -10,7 +10,7 @@ FILE: superclassNotAccessibleFromInterface.kt
}
public abstract interface ATrait : R|A| {
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| {
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|()
super<R|Outer|>.R|/Outer.ProtectedInner.ProtectedInner|()
this@R|/Derived|.super<R|Outer|>.R|/Outer.ProtectedInner.ProtectedInner|()
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| {
^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| {
super<R|A|R|B|>.R|/B.foo|()
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.foo|()
this@R|/C|.super<R|A|R|B|>.<Ambiguity: bar, [/A.bar, /B.bar]>#()
this@R|/C|.super<R|A|R|B|>.R|/B.baz|()
this@R|/C|.R|/A.baz|()
}
@@ -96,31 +96,6 @@ class Fir2IrConversionScope {
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 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.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType
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.ir.types.*
import org.jetbrains.kotlin.psi.KtPropertyDelegate
import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects
@@ -165,21 +162,15 @@ internal class CallAndReferenceGenerator(
conversionScope
)
return typeRef.convertWithOffsets { startOffset, endOffset ->
val dispatchReceiver = qualifiedAccess.dispatchReceiver
if (qualifiedAccess.calleeReference is FirSuperReference) {
val superReference = qualifiedAccess.calleeReference as FirSuperReference
if (typeRef !is FirComposedSuperTypeRef) {
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)
}
if (typeRef !is FirComposedSuperTypeRef && dispatchReceiver !is FirNoReceiverExpression) {
return@convertWithOffsets visitor.convertToIrExpression(dispatchReceiver)
}
}
var superQualifierSymbol: IrClassSymbol? = null
if (qualifiedAccess.dispatchReceiver is FirQualifiedAccess) {
val dispatchReceiverReference = (qualifiedAccess.dispatchReceiver as FirQualifiedAccess).calleeReference
if (dispatchReceiver is FirQualifiedAccess) {
val dispatchReceiverReference = dispatchReceiver.calleeReference
if (dispatchReceiverReference is FirSuperReference) {
val coneSuperType = dispatchReceiverReference.superTypeRef.coneTypeSafe<ConeClassLikeType>()
(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.types.*
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.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -81,6 +80,13 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
qualifiedAccessExpression
}
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) {
is FirResolvedTypeRef -> {
qualifiedAccessExpression.resultType = superTypeRef
@@ -90,10 +96,6 @@ class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransformer) :
qualifiedAccessExpression.resultType = callee.superTypeRef
}
else -> {
val labelName = callee.labelName
val implicitReceiver =
if (labelName != null) implicitReceiverStack[labelName] as? ImplicitDispatchReceiverValue
else implicitReceiverStack.lastDispatchReceiver()
val superTypeRefs = implicitReceiver?.boundSymbol?.phasedFir?.superTypeRefs
val resultType = when {
superTypeRefs?.isNotEmpty() != true -> {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class A(val value: String) {
inner class B(val s: String) {
val result = value + "_" + s
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface BK {
fun foo(): String
fun bar(): String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
//inspired by kt3492
interface BK {
fun foo(): String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Base {
val foo: String
fun bar(): String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
//inspired by kt3492
interface Base {
val foo: String