FIR2IR: populate overriddenSymbols for overriding functions

#KT-38416 Fixed
This commit is contained in:
Jinseong Jeon
2020-04-23 23:57:47 -07:00
committed by Mikhail Glukhikh
parent b51649dcc6
commit 57fe01c375
122 changed files with 167 additions and 112 deletions
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.fir.backend
import com.intellij.psi.PsiCompiledElement
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
@@ -26,19 +28,23 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.descriptors.WrappedReceiverParameterDescriptor
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrErrorType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.isFakeOverride
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -279,6 +285,73 @@ internal tailrec fun FirCallableSymbol<*>.deepestMatchingOverriddenSymbol(root:
return overriddenSymbol.deepestMatchingOverriddenSymbol(this)
}
internal fun IrClass.findMatchingOverriddenSymbolsFromSupertypes(
irBuiltIns: IrBuiltIns,
target: IrDeclaration,
result: MutableList<IrSymbol> = mutableListOf()
): List<IrSymbol> {
for (superType in superTypes) {
val superTypeClass = superType.classOrNull
if (superTypeClass is IrClassSymbolImpl) {
superTypeClass.owner.findMatchingOverriddenSymbolsFromThisAndSupertypes(irBuiltIns, target, result)
}
}
return result
}
private fun IrClass.findMatchingOverriddenSymbolsFromThisAndSupertypes(
irBuiltIns: IrBuiltIns,
target: IrDeclaration,
result: MutableList<IrSymbol>
): List<IrSymbol> {
for (declaration in declarations) {
when {
declaration is IrFunction && target is IrFunction ->
if (declaration !is IrConstructor &&
!declaration.isFakeOverride &&
declaration.descriptor.modality != Modality.FINAL &&
!Visibilities.isPrivate(declaration.visibility) &&
isOverriding(irBuiltIns, target, declaration)
) {
result.add(declaration.symbol)
}
// TODO: property lookup to set overriddenSymbols for IrProperty (and accessors)?
}
}
// Stop traversing upwards if we find matching overridden symbols at this level.
if (result.isNotEmpty()) {
return result
}
return findMatchingOverriddenSymbolsFromSupertypes(irBuiltIns, target, result)
}
fun isOverriding(
irBuiltIns: IrBuiltIns,
target: IrFunction,
superCandidate: IrFunction
): Boolean {
val typeCheckerContext = IrTypeCheckerContext(irBuiltIns) as AbstractTypeCheckerContext
fun equalTypes(first: IrType, second: IrType): Boolean {
return AbstractTypeChecker.equalTypes(
typeCheckerContext, first, second
) ||
// TODO: should pass type parameter cache, and make sure target type is indeed a matched type argument.
second.classifierOrNull is IrTypeParameterSymbol
}
return target.name == superCandidate.name &&
// Not checking the return type (they should match each other if everything other match, otherwise it's a compilation error)
target.extensionReceiverParameter?.type?.let {
val superCandidateReceiverType = superCandidate.extensionReceiverParameter?.type
superCandidateReceiverType != null && equalTypes(it, superCandidateReceiverType)
} != false &&
target.valueParameters.size == superCandidate.valueParameters.size &&
target.valueParameters.zip(superCandidate.valueParameters).all { (targetParameter, superCandidateParameter) ->
equalTypes(targetParameter.type, superCandidateParameter.type)
}
}
private val nameToOperationConventionOrigin = mutableMapOf(
OperatorNameConventions.PLUS to IrStatementOrigin.PLUS,
OperatorNameConventions.MINUS to IrStatementOrigin.MINUS,
@@ -453,6 +453,13 @@ class Fir2IrDeclarationStorage(
created.overriddenSymbols += getIrFunctionSymbol(it) as IrSimpleFunctionSymbol
}
}
if (!created.isFakeOverride && simpleFunction?.isOverride == true && thisReceiverOwner != null) {
thisReceiverOwner.findMatchingOverriddenSymbolsFromSupertypes(components.irBuiltIns, created).forEach {
if (it is IrSimpleFunctionSymbol) {
created.overriddenSymbols += it
}
}
}
functionCache[function] = created
return created
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Base<T> {
open fun f(x: T): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FULL_JDK
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class C {
open fun f(): Any = "C f"
}
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A<T> {
open fun foo(t: T) = "A"
}
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class A<T> {
open fun foo(t: T) = "A"
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: J.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class A<T> {
open fun foo(t: T) = "A"
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A<T1> {
fun <T2> T2.foo(x: T1): String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A {
fun foo(): Any?
}
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: Enable when JS backend supports Java class library, since FunctionX are required for interoperation
// IGNORE_BACKEND: JS
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME
// WITH_COROUTINES
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,8 +1,6 @@
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
// TODO (SPECIAL IGNORE_BACKEND_FIR): this test isn't run in FIR mode at all due to infinite loop
import helpers.*
import COROUTINES_PACKAGE.*
import COROUTINES_PACKAGE.intrinsics.*
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FULL_JDK
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FULL_JDK
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FULL_JDK
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FULL_JDK
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FULL_JDK
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
abstract class Base {
abstract fun foo(a: String = "abc"): String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// See KT-21968
interface A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Foo {
open fun foo(x: CharSequence = "O"): CharSequence = x
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Foo {
open fun foo(x: CharSequence = "O"): CharSequence = x
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Foo {
fun foo(a: Double = 1.0): Double
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS
// Test for KT-36188 bug compatibility between non-IR and IR backends
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS
// Test for KT-36188 bug compatibility between non-IR and IR backends
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A {
fun visit(a:String, b:String="") : String = b + a
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface Base {
fun bar(a: String = "abc"): String = a + " from interface"
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface FooTrait<T> {
fun make(size: Int = 16) : T
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class Player(val name: String)
open class SlashPlayer(name: String) : Player(name)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
abstract class A<T> {
abstract fun test(a: T, b:Boolean = false) : String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// DONT_RUN_GENERATED_CODE: JS
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A {
fun bar2(arg: Int = 239) : Int
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
open abstract class B {
abstract fun foo2(arg: Int = 239) : Int
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class X(val x: Any)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class X(val x: Any?)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class X(val x: Any)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface IFoo {
fun foo(): String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class X(val x: Char)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface IQ1
interface IQ2
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class X(val x: Any)
interface IFoo<T> {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface GFoo<out T> {
fun foo(): T
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class X(val x: String)
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class ResultOrClosed(val x: Any?)
interface A<T> {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class X(val x: Any?)
interface IFoo<out T : X?> {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
inline class X(val x: Any?)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class X(val x: Any?)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
inline class X(val x: Any?)
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface IQ {
fun ok(): String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface IQ {
fun ok(): String
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface IBase
interface IQ : IBase {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface IBase
interface IQ : IBase {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface IFoo1<out T> {
fun foo(): T
}
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
inline class InlinedComparable(val x: Int) : Comparable<InlinedComparable> {
override fun compareTo(other: InlinedComparable): Int {
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
interface Base {
fun result(): Int
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
inline class Z(val z: Int)
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
interface IFoo {
fun foo(): String
@@ -1,4 +1,5 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
abstract class GenericBase<T> {
abstract fun foo(x: T): T
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
inline class A(val s: String)
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
interface IFoo {
fun Long.foo() = bar()
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
interface IFoo {
fun foo() = bar()
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
interface IFoo<T : IFoo<T>> {
fun T.foo(): String = bar()
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
interface IFoo<T : IFoo<T>> {
fun foo(t: T): String = t.bar()
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
interface IFoo {
fun foo(): String
@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND_FIR: JVM_IR
interface IBase {
fun testDefault1() = if (this is B) this.foo() else "fail"
@@ -1,3 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,3 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,3 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
open class A : Cloneable {
+1
View File
@@ -1,3 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: NATIVE
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all-compatibility
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: ANDROID
// JVM_TARGET: 1.8
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: enable
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
@@ -1,5 +1,4 @@
// !JVM_DEFAULT_MODE: all
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: ANDROID
// JVM_TARGET: 1.8
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
package org.example
interface SomeTrait {}
@@ -1,3 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class A {
internal open val field = "F"
@@ -1,3 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR
open class A {
internal open val field = "F"
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A : Comparable<A>
class B(val x: Int) : A {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: FortyTwoExtractor.java
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// KJS_WITH_FULL_RUNTIME
// WITH_RUNTIME

Some files were not shown because too many files have changed in this diff Show More