[FIR] Check supertypes hierarchy for java classes during creation of synhtetic properies

^KT-62394 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-10-06 12:44:07 +03:00
committed by Space Team
parent 16ab36e167
commit c3f3a4192c
7 changed files with 95 additions and 20 deletions
@@ -6,13 +6,12 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.getDeprecationsProviderFromAccessors
import org.jetbrains.kotlin.fir.declarations.isHiddenEverywhereBesideSuperCalls
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol
@@ -248,7 +247,56 @@ class FirSyntheticPropertiesScope private constructor(
ProcessorAction.NEXT
}
result = result || isJavaTypeOnThePath(this.dispatchReceiverType)
return result && !isHiddenEverywhereBesideSuperCalls
}
/*
* We should check the whole hierarchy between dispatch receiver type of found getter and our dispatch receiver type, because
* synthetic properly should be created if there is a java class on this way (KT-62394)
*
* // FILE: Base.kt
* abstract class Base(private val x: String) {
* fun getFoo() = x
* }
*
* // FILE: Intermediate.java
* public class Intermediate extends Base {
* public Intermediate(String x) {
* super(x);
* }
* }
*
* // FILE: Final.kt
* class Final(x: String) : Intermediate(x)
*
* fun test(f: Final) {
* f.foo // <-------
* }
*/
private fun isJavaTypeOnThePath(baseType: ConeSimpleKotlinType?): Boolean {
val lookupTagToStop = (baseType as? ConeLookupTagBasedType)?.lookupTag ?: return false
val dispatchReceiverClass = (dispatchReceiverType as? ConeLookupTagBasedType)?.lookupTag?.toSymbol(session) ?: return false
val typeContext = session.typeContext
fun checkType(type: ConeClassLikeType): Boolean {
val state = typeContext.newTypeCheckerState(errorTypesEqualToAnything = false, stubTypesEqualToAnything = false)
if (type.toRegularClassSymbol(session)?.isJavaOrEnhancement == true) {
if (AbstractTypeChecker.isSubtypeOfClass(state, type.lookupTag, lookupTagToStop)) {
return true
}
}
return false
}
if (dispatchReceiverType is ConeClassLikeType && checkType(dispatchReceiverType)) {
return true
}
val superTypes = lookupSuperTypes(dispatchReceiverClass, lookupInterfaces = true, deep = true, session)
for (superType in superTypes) {
if (checkType(superType)) return true
}
return false
}
}
@@ -1,7 +1,5 @@
// TARGET_BACKEND: JVM_IR
// ISSUE: KT-59550
// IGNORE_BACKEND_K2: ANY
// Ignore reason: KT-62393 and KT-62394
// FILE: Intermediate.java
public class Intermediate extends Base {
public Intermediate(String foo) {
@@ -1,7 +1,5 @@
// TARGET_BACKEND: JVM_IR
// ISSUE: KT-59550
// IGNORE_BACKEND_K2: ANY
// Ignore reason: KT-62393 and KT-62394
// FILE: Intermediate.java
public class Intermediate extends Base {
@@ -0,0 +1,31 @@
// FILE: KotlinFile.kt
open class KotlinClass1 : JavaClass1() {
public fun getSomethingKotlin1(): Int = 1
}
class KotlinClass2 : JavaClass2() {
public fun getSomethingKotlin2(): Int = 1
}
fun foo(k: KotlinClass2) {
useInt(k.getSomething1())
useInt(k.something1)
useInt(k.getSomething2())
useInt(k.something2)
useInt(k.getSomethingKotlin1())
useInt(k.getSomethingKotlin2())
k.somethingKotlin1
k.<!UNRESOLVED_REFERENCE!>somethingKotlin2<!>
}
fun useInt(i: Int) {}
// FILE: JavaClass1.java
public class JavaClass1 {
public int getSomething1() { return 1; }
}
// FILE: JavaClass2.java
public class JavaClass2 extends KotlinClass1 {
public int getSomething2() { return 1; }
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// FILE: KotlinFile.kt
open class KotlinClass1 : JavaClass1() {
public fun getSomethingKotlin1(): Int = 1
+11 -6
View File
@@ -113,6 +113,15 @@ FILE fqName:<root> fileName:/kt43342.kt
CALL 'public abstract fun <get-values> (): kotlin.collections.Collection<V of kotlin.collections.Map> declared in kotlin.collections.Map' type=kotlin.collections.Collection<V of kotlin.collections.Map> origin=null
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:map type:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> visibility:private [final]' type=kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
receiver: GET_VAR '<this>: <root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> declared in <root>.ControlFlowInfo.<get-values>' type=<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
FUN FAKE_OVERRIDE name:getOrDefault visibility:public modality:OPEN <> ($this:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>, key:K of <root>.ControlFlowInfo, defaultValue:V of <root>.ControlFlowInfo) returnType:V of <root>.ControlFlowInfo [fake_override]
annotations:
SinceKotlin(version = '1.1')
PlatformDependent
overridden:
public open fun getOrDefault (key: K of kotlin.collections.Map, defaultValue: V of kotlin.collections.Map): V of kotlin.collections.Map declared in kotlin.collections.Map
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>
VALUE_PARAMETER name:key index:0 type:K of <root>.ControlFlowInfo
VALUE_PARAMETER name:defaultValue index:1 type:V of <root>.ControlFlowInfo
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.collections.Map
@@ -126,10 +135,6 @@ FILE fqName:<root> fileName:/kt43342.kt
overridden:
public open fun toString (): kotlin.String declared in kotlin.collections.Map
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN name:getOrDefault visibility:public modality:OPEN <> ($this:<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>, key:K of <root>.ControlFlowInfo, defaultValue:V of <root>.ControlFlowInfo) returnType:V of <root>.ControlFlowInfo
$this: VALUE_PARAMETER name:<this> type:<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>
VALUE_PARAMETER name:key index:0 type:K of <root>.ControlFlowInfo
VALUE_PARAMETER name:defaultValue index:1 type:V of <root>.ControlFlowInfo
CLASS CLASS name:StringFlowInfo modality:FINAL visibility:public superTypes:[<root>.ControlFlowInfo<kotlin.String, kotlin.String>]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.StringFlowInfo
CONSTRUCTOR visibility:public <> (map:kotlin.collections.Map<kotlin.String, kotlin.String>) returnType:<root>.StringFlowInfo [primary]
@@ -173,13 +178,13 @@ FILE fqName:<root> fileName:/kt43342.kt
public open fun get (key: K of <root>.ControlFlowInfo): V of <root>.ControlFlowInfo? declared in <root>.ControlFlowInfo
$this: VALUE_PARAMETER name:<this> type:<root>.ControlFlowInfo<kotlin.String, kotlin.String>
VALUE_PARAMETER name:key index:0 type:kotlin.String
FUN FAKE_OVERRIDE name:getOrDefault visibility:public modality:OPEN <> ($this:<root>.ControlFlowInfo<kotlin.String, kotlin.String>, key:kotlin.String, defaultValue:kotlin.String) returnType:kotlin.String [fake_override]
FUN FAKE_OVERRIDE name:getOrDefault visibility:public modality:OPEN <> ($this:kotlin.collections.Map<kotlin.String, kotlin.String>, key:kotlin.String, defaultValue:kotlin.String) returnType:kotlin.String [fake_override]
annotations:
SinceKotlin(version = '1.1')
PlatformDependent
overridden:
public open fun getOrDefault (key: K of <root>.ControlFlowInfo, defaultValue: V of <root>.ControlFlowInfo): V of <root>.ControlFlowInfo declared in <root>.ControlFlowInfo
$this: VALUE_PARAMETER name:<this> type:<root>.ControlFlowInfo<kotlin.String, kotlin.String>
$this: VALUE_PARAMETER name:<this> type:kotlin.collections.Map<kotlin.String, kotlin.String>
VALUE_PARAMETER name:key index:0 type:kotlin.String
VALUE_PARAMETER name:defaultValue index:1 type:kotlin.String
FUN FAKE_OVERRIDE name:isEmpty visibility:public modality:OPEN <> ($this:<root>.ControlFlowInfo<kotlin.String, kotlin.String>) returnType:kotlin.Boolean [fake_override]
@@ -45,10 +45,6 @@ open class ControlFlowInfo<K : Any?, V : Any?> : Map<K, V> {
return <this>.#map.<get-values>()
}
val map: Map<K, V>
field = map
get
}
class StringFlowInfo : ControlFlowInfo<String, String> {