FIR: Provide dispatch receiver for 'field' according to property type

This commit is contained in:
Jinseong Jeon
2020-03-27 22:31:44 -07:00
committed by Mikhail Glukhikh
parent a0978a50e8
commit 078cf02c8a
32 changed files with 39 additions and 34 deletions
@@ -51,6 +51,10 @@ class PersistentImplicitReceiverStack private constructor(
return stack.filterIsInstance<ImplicitDispatchReceiverValue>().lastOrNull()
}
override fun lastDispatchReceiver(lookupCondition: (ImplicitReceiverValue<*>) -> Boolean): ImplicitDispatchReceiverValue? {
return stack.filterIsInstance<ImplicitDispatchReceiverValue>().lastOrNull(lookupCondition)
}
override fun receiversAsReversed(): List<ImplicitReceiverValue<*>> = stack.asReversed()
override operator fun iterator(): Iterator<ImplicitReceiverValue<*>> {
@@ -11,9 +11,17 @@ import org.jetbrains.kotlin.name.Name
// NB: with className == null we are at top level
data class CallableId(val packageName: FqName, val className: FqName?, val callableName: Name) {
val classId: ClassId? get() = className?.let { ClassId(packageName, it, false) }
var classId: ClassId? = null
get() {
if (field == null && className != null) {
field = ClassId(packageName, className, false)
}
return field
}
constructor(classId: ClassId, callableName: Name) : this(classId.packageFqName, classId.relativeClassName, callableName)
constructor(classId: ClassId, callableName: Name) : this(classId.packageFqName, classId.relativeClassName, callableName) {
this.classId = classId
}
constructor(packageName: FqName, callableName: Name) : this(packageName, null, callableName)
@@ -338,7 +338,8 @@ internal class CallAndReferenceGenerator(
// Object case
val callableReference = calleeReference as? FirResolvedNamedReference
val ownerClassId = (callableReference?.resolvedSymbol as? FirCallableSymbol<*>)?.callableId?.classId
val ownerClassSymbol = ownerClassId?.let { session.firSymbolProvider.getClassLikeSymbolByFqName(it) }
val ownerClassSymbol =
ownerClassId?.takeUnless { it.isLocal }?.let { session.firSymbolProvider.getClassLikeSymbolByFqName(it) }
val firClass = (ownerClassSymbol?.fir as? FirClass)?.takeIf {
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.buildSingleExpressionBlock
import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.builder.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.ANONYMOUS_CLASS_ID
import org.jetbrains.kotlin.fir.symbols.impl.FirErrorFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
@@ -35,8 +36,6 @@ import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parsing.*
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtUnaryExpression
import org.jetbrains.kotlin.util.OperatorNameConventions
//T can be either PsiElement, or LighterASTNode
@@ -73,7 +72,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
when {
local -> CallableId(name)
context.className == FqName.ROOT -> CallableId(context.packageFqName, name)
context.className.shortName() === ANONYMOUS_OBJECT_NAME -> CallableId(FqName.ROOT, FqName("anonymous"), name)
context.className.shortName() === ANONYMOUS_OBJECT_NAME -> CallableId(ANONYMOUS_CLASS_ID, name)
else -> CallableId(context.packageFqName, context.className, name)
}
@@ -19,6 +19,7 @@ abstract class ImplicitReceiverStack : Iterable<ImplicitReceiverValue<*>> {
abstract operator fun get(name: String?): ImplicitReceiverValue<*>?
abstract fun lastDispatchReceiver(): ImplicitDispatchReceiverValue?
abstract fun lastDispatchReceiver(lookupCondition: (ImplicitReceiverValue<*>) -> Boolean): ImplicitDispatchReceiverValue?
abstract fun receiversAsReversed(): List<ImplicitReceiverValue<*>>
}
@@ -75,6 +76,10 @@ class ImplicitReceiverStackImpl private constructor(
return stack.filterIsInstance<ImplicitDispatchReceiverValue>().lastOrNull()
}
override fun lastDispatchReceiver(lookupCondition: (ImplicitReceiverValue<*>) -> Boolean): ImplicitDispatchReceiverValue? {
return stack.filterIsInstance<ImplicitDispatchReceiverValue>().lastOrNull(lookupCondition)
}
override fun receiversAsReversed(): List<ImplicitReceiverValue<*>> = stack.asReversed()
fun getReceiverIndex(symbol: FirBasedSymbol<*>): Int? = indexesPerSymbol[symbol]
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractImportingScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeNullability
import org.jetbrains.kotlin.fir.types.withNullability
@@ -190,8 +191,18 @@ class ScopeTowerLevel(
empty = false
if (candidate.hasConsistentReceivers(extensionReceiver)) {
val dispatchReceiverValue =
if (candidate !is FirBackingFieldSymbol) null
else bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver()
when {
candidate !is FirBackingFieldSymbol -> null
candidate.callableId.classId != null -> {
val propertyHolderId = candidate.callableId.classId
bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver { implicitReceiverValue ->
implicitReceiverValue.type.classId == propertyHolderId
}
}
else -> {
bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver()
}
}
processor.consumeCandidate(
candidate as T, dispatchReceiverValue,
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*>
@@ -27,7 +27,9 @@ sealed class FirClassSymbol<C : FirClass<C>>(classId: ClassId) : FirClassLikeSym
class FirRegularClassSymbol(classId: ClassId) : FirClassSymbol<FirRegularClass>(classId)
class FirAnonymousObjectSymbol : FirClassSymbol<FirAnonymousObject>(ClassId(FqName.ROOT, FqName("anonymous"), true))
val ANONYMOUS_CLASS_ID = ClassId(FqName.ROOT, FqName("anonymous"), true)
class FirAnonymousObjectSymbol : FirClassSymbol<FirAnonymousObject>(ANONYMOUS_CLASS_ID)
class FirTypeAliasSymbol(classId: ClassId) : FirClassLikeSymbol<FirTypeAlias>(classId) {
override fun toLookupTag() = ConeClassLikeLookupTagImpl(classId)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Outer {
val result = "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME
class World() {
@@ -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
class C(val value: String = "C") {
inner class B(val s: String) {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
class Outer(val foo: StringBuilder) {
inner class Inner() {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Foo(val x: () -> String)
class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base(val callback: () -> String)
class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base(val callback: () -> String)
class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base(val callback: () -> String)
class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Foo(val x: () -> String)
open class Foo2(val foo: Foo)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base(val callback: () -> String)
class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Callback {
fun invoke(): String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Callback {
fun invoke(): String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A {
private fun Int.foo(other: Int = 5): Int = this + other
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
enum class X {
B {
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
inline class S(val string: String)
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
inline class S(val string: String)
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
inline class S(val string: String)
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
inline class Z(val x: Int) {
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
inline class Z(val x: Int) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Outer {
val x = "O"
inner class Inner {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Outer(val x: String) {
inner class Inner(val y: String) {
val z = x + y
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
public object SomeObject {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class My {
var my: String = "U"
get() = { field }()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
abstract class Your {
abstract val your: String