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() 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 fun receiversAsReversed(): List<ImplicitReceiverValue<*>> = stack.asReversed()
override operator fun iterator(): Iterator<ImplicitReceiverValue<*>> { 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 // NB: with className == null we are at top level
data class CallableId(val packageName: FqName, val className: FqName?, val callableName: Name) { 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) constructor(packageName: FqName, callableName: Name) : this(packageName, null, callableName)
@@ -338,7 +338,8 @@ internal class CallAndReferenceGenerator(
// Object case // Object case
val callableReference = calleeReference as? FirResolvedNamedReference val callableReference = calleeReference as? FirResolvedNamedReference
val ownerClassId = (callableReference?.resolvedSymbol as? FirCallableSymbol<*>)?.callableId?.classId 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 { val firClass = (ownerClassSymbol?.fir as? FirClass)?.takeIf {
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT 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.FirReference
import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.references.builder.*
import org.jetbrains.kotlin.fir.symbols.CallableId 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.FirErrorFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol 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.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parsing.* import org.jetbrains.kotlin.parsing.*
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtUnaryExpression
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
//T can be either PsiElement, or LighterASTNode //T can be either PsiElement, or LighterASTNode
@@ -73,7 +72,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
when { when {
local -> CallableId(name) local -> CallableId(name)
context.className == FqName.ROOT -> CallableId(context.packageFqName, 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) else -> CallableId(context.packageFqName, context.className, name)
} }
@@ -19,6 +19,7 @@ abstract class ImplicitReceiverStack : Iterable<ImplicitReceiverValue<*>> {
abstract operator fun get(name: String?): ImplicitReceiverValue<*>? abstract operator fun get(name: String?): ImplicitReceiverValue<*>?
abstract fun lastDispatchReceiver(): ImplicitDispatchReceiverValue? abstract fun lastDispatchReceiver(): ImplicitDispatchReceiverValue?
abstract fun lastDispatchReceiver(lookupCondition: (ImplicitReceiverValue<*>) -> Boolean): ImplicitDispatchReceiverValue?
abstract fun receiversAsReversed(): List<ImplicitReceiverValue<*>> abstract fun receiversAsReversed(): List<ImplicitReceiverValue<*>>
} }
@@ -75,6 +76,10 @@ class ImplicitReceiverStackImpl private constructor(
return stack.filterIsInstance<ImplicitDispatchReceiverValue>().lastOrNull() 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 fun receiversAsReversed(): List<ImplicitReceiverValue<*>> = stack.asReversed()
fun getReceiverIndex(symbol: FirBasedSymbol<*>): Int? = indexesPerSymbol[symbol] 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.scopes.impl.FirAbstractImportingScope
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* 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.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeNullability import org.jetbrains.kotlin.fir.types.ConeNullability
import org.jetbrains.kotlin.fir.types.withNullability import org.jetbrains.kotlin.fir.types.withNullability
@@ -190,8 +191,18 @@ class ScopeTowerLevel(
empty = false empty = false
if (candidate.hasConsistentReceivers(extensionReceiver)) { if (candidate.hasConsistentReceivers(extensionReceiver)) {
val dispatchReceiverValue = val dispatchReceiverValue =
if (candidate !is FirBackingFieldSymbol) null when {
else bodyResolveComponents.implicitReceiverStack.lastDispatchReceiver() 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( processor.consumeCandidate(
candidate as T, dispatchReceiverValue, candidate as T, dispatchReceiverValue,
implicitExtensionReceiverValue = extensionReceiver as? ImplicitReceiverValue<*> 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 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) { class FirTypeAliasSymbol(classId: ClassId) : FirClassLikeSymbol<FirTypeAlias>(classId) {
override fun toLookupTag() = ConeClassLikeLookupTagImpl(classId) override fun toLookupTag() = ConeClassLikeLookupTagImpl(classId)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Outer { class Outer {
val result = "OK" val result = "OK"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME // WITH_RUNTIME
class World() { class World() {
@@ -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
class C(val value: String = "C") { class C(val value: String = "C") {
inner class B(val s: String) { inner class B(val s: String) {
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME // KJS_WITH_FULL_RUNTIME
class Outer(val foo: StringBuilder) { class Outer(val foo: StringBuilder) {
inner class Inner() { inner class Inner() {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Foo(val x: () -> String) open class Foo(val x: () -> String)
class Outer { class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base(val callback: () -> String) open class Base(val callback: () -> String)
class Outer { class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base(val callback: () -> String) open class Base(val callback: () -> String)
class Outer { class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base(val callback: () -> String) open class Base(val callback: () -> String)
class Outer { class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Foo(val x: () -> String) open class Foo(val x: () -> String)
open class Foo2(val foo: Foo) open class Foo2(val foo: Foo)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base(val callback: () -> String) open class Base(val callback: () -> String)
class Outer { class Outer {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Callback { interface Callback {
fun invoke(): String fun invoke(): String
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Callback { interface Callback {
fun invoke(): String fun invoke(): String
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class A { class A {
private fun Int.foo(other: Int = 5): Int = this + other private fun Int.foo(other: Int = 5): Int = this + other
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
enum class X { enum class X {
B { B {
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
inline class S(val string: String) inline class S(val string: String)
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
inline class S(val string: String) inline class S(val string: String)
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
inline class S(val string: String) inline class S(val string: String)
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
inline class Z(val x: Int) { inline class Z(val x: Int) {
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses // !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
inline class Z(val x: Int) { inline class Z(val x: Int) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Outer { class Outer {
val x = "O" val x = "O"
inner class Inner { inner class Inner {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class Outer(val x: String) { class Outer(val x: String) {
inner class Inner(val y: String) { inner class Inner(val y: String) {
val z = x + y val z = x + y
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
public object SomeObject { public object SomeObject {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
class My { class My {
var my: String = "U" var my: String = "U"
get() = { field }() get() = { field }()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
abstract class Your { abstract class Your {
abstract val your: String abstract val your: String