FIR: support fake overrides for properties

This commit is contained in:
Mikhail Glukhikh
2019-08-30 13:27:10 +03:00
parent 5741ff5d86
commit 687db20029
11 changed files with 174 additions and 59 deletions
@@ -219,7 +219,7 @@ internal class Fir2IrVisitor(
}
} else if (fakeOverrideMode != FakeOverrideMode.SUBSTITUTION) {
// Trivial fake override case
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverride(session, originalFunction, functionSymbol)
val fakeOverrideSymbol = FirClassSubstitutionScope.createFakeOverrideFunction(session, originalFunction, functionSymbol)
val fakeOverrideFunction = fakeOverrideSymbol.fir
val irFunction = declarationStorage.getIrFunction(
@@ -7,9 +7,8 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirNamedFunction
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirMemberFunctionImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorWithJump
@@ -31,14 +30,15 @@ class FirClassSubstitutionScope(
substitution: Map<ConeTypeParameterSymbol, ConeKotlinType>
) : FirScope() {
private val fakeOverrides = mutableMapOf<FirFunctionSymbol<*>, FirFunctionSymbol<*>>()
private val fakeOverrideFunctions = mutableMapOf<FirFunctionSymbol<*>, FirFunctionSymbol<*>>()
private val fakeOverrideProperties = mutableMapOf<FirPropertySymbol, FirPropertySymbol>()
private val substitutor = substitutorByMap(substitution)
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
useSiteScope.processFunctionsByName(name) process@{ original ->
val function = fakeOverrides.getOrPut(original) { createFakeOverride(original) }
val function = fakeOverrideFunctions.getOrPut(original) { createFakeOverrideFunction(original) }
processor(function)
}
@@ -47,7 +47,14 @@ class FirClassSubstitutionScope(
}
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
return useSiteScope.processPropertiesByName(name, processor)
return useSiteScope.processPropertiesByName(name) process@{ original ->
if (original is FirPropertySymbol) {
val property = fakeOverrideProperties.getOrPut(original) { createFakeOverrideProperty(original) }
processor(property)
} else {
processor(original)
}
}
}
private val typeCalculator by lazy { ReturnTypeCalculatorWithJump(session, scopeSession) }
@@ -56,7 +63,7 @@ class FirClassSubstitutionScope(
return substitutor.substituteOrNull(this)
}
private fun createFakeOverride(original: FirFunctionSymbol<*>): FirFunctionSymbol<*> {
private fun createFakeOverrideFunction(original: FirFunctionSymbol<*>): FirFunctionSymbol<*> {
val member = when (original) {
is FirNamedFunctionSymbol -> original.fir
is FirConstructorSymbol -> return original
@@ -73,11 +80,23 @@ class FirClassSubstitutionScope(
it.returnTypeRef.coneTypeUnsafe<ConeKotlinType>().substitute()
}
return createFakeOverride(session, member, original, newReceiverType, newReturnType, newParameterTypes)
return createFakeOverrideFunction(session, member, original, newReceiverType, newReturnType, newParameterTypes)
}
private fun createFakeOverrideProperty(original: FirPropertySymbol): FirPropertySymbol {
val member = original.fir
val receiverType = member.receiverTypeRef?.coneTypeUnsafe<ConeKotlinType>()
val newReceiverType = receiverType?.substitute()
val returnType = typeCalculator.tryCalculateReturnType(member).type
val newReturnType = returnType.substitute()
return createFakeOverrideProperty(session, member, original, newReceiverType, newReturnType)
}
companion object {
fun createFakeOverride(
fun createFakeOverrideFunction(
session: FirSession,
baseFunction: FirNamedFunction,
baseSymbol: FirNamedFunctionSymbol,
@@ -113,6 +132,29 @@ class FirClassSubstitutionScope(
}
return symbol
}
fun createFakeOverrideProperty(
session: FirSession,
baseProperty: FirProperty,
baseSymbol: FirPropertySymbol,
newReceiverType: ConeKotlinType? = null,
newReturnType: ConeKotlinType? = null
): FirPropertySymbol {
val symbol = FirPropertySymbol(baseSymbol.callableId, true, baseSymbol)
with(baseProperty) {
FirMemberPropertyImpl(
session,
psi, symbol, name,
baseProperty.receiverTypeRef?.withReplacedConeType(newReceiverType),
baseProperty.returnTypeRef.withReplacedConeType(newReturnType),
isVar, initializer = null, delegate = null
).apply {
resolvePhase = baseProperty.resolvePhase
status = baseProperty.status as FirDeclarationStatusImpl
}
}
return symbol
}
}
}
@@ -0,0 +1,7 @@
abstract class Base<T>(val x: T) {
abstract fun foo(): T
}
class Derived<T>(x: T) : Base<T>(x) {
override fun foo(): T = x
}
@@ -0,0 +1,22 @@
FILE: genericPropertyAccess.kt
public abstract class Base<T> : R|kotlin/Any| {
public constructor<T>(x: R|T|): R|Base<T>| {
super<R|kotlin/Any|>()
}
public final val x: R|T| = R|<local>/x|
public get(): R|T|
public abstract fun foo(): R|T|
}
public final class Derived<T> : R|Base<T>| {
public constructor<T>(x: R|T|): R|Derived<T>| {
super<R|Base<T>|>(R|<local>/x|)
}
public final override fun foo(): R|T| {
^foo this@R|/Base|.R|/Base.x|
}
}
+2 -2
View File
@@ -53,8 +53,8 @@ FILE: problems.kt
}
}
public final val xx: <ERROR TYPE REF: Inapplicable(WRONG_RECEIVER): [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]> = R|/Derived.Derived|().R|/Base.x|.<Inapplicable(WRONG_RECEIVER): [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]>#(Int(1))
public get(): <ERROR TYPE REF: Inapplicable(WRONG_RECEIVER): [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]>
public final val xx: R|kotlin/Int| = R|/Derived.Derived|().R|/Base.x|.R|kotlin/Int.plus|(Int(1))
public get(): R|kotlin/Int|
public final val t: R|kotlin/Nothing| = throw R|java/lang/AssertionError.AssertionError|(String())
public get(): R|kotlin/Nothing|
public abstract interface A : R|kotlin/Any| {
@@ -287,6 +287,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/expresssions/dispatchReceiver.kt");
}
@TestMetadata("genericPropertyAccess.kt")
public void testGenericPropertyAccess() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/genericPropertyAccess.kt");
}
@TestMetadata("importedReceiver.kt")
public void testImportedReceiver() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/importedReceiver.kt");
@@ -24,31 +24,73 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.name.Name
class FirMemberPropertyImpl(
session: FirSession,
psi: PsiElement?,
override val symbol: FirPropertySymbol,
name: Name,
visibility: Visibility,
modality: Modality?,
isExpect: Boolean,
isActual: Boolean,
isOverride: Boolean,
isConst: Boolean,
isLateInit: Boolean,
receiverTypeRef: FirTypeRef?,
returnTypeRef: FirTypeRef,
override val isVar: Boolean,
override var initializer: FirExpression?,
class FirMemberPropertyImpl : FirAbstractCallableMember<FirProperty>, FirProperty, FirModifiableAccessorsOwner {
override val symbol: FirPropertySymbol
override val isVar: Boolean
override var initializer: FirExpression?
override var delegate: FirExpression?
) : FirAbstractCallableMember<FirProperty>(
session, psi, name, visibility, modality, isExpect, isActual, isOverride, receiverTypeRef, returnTypeRef
), FirProperty, FirModifiableAccessorsOwner {
// TODO: backing field may not exist
override val backingFieldSymbol = FirBackingFieldSymbol(symbol.callableId)
override val delegateFieldSymbol: FirDelegateFieldSymbol<FirProperty>? =
delegate?.let { FirDelegateFieldSymbol(symbol.callableId) }
private fun bindSymbols(symbol: FirPropertySymbol) {
symbol.bind(this)
backingFieldSymbol.bind(this)
delegateFieldSymbol?.bind(this)
}
constructor(
session: FirSession,
psi: PsiElement?,
symbol: FirPropertySymbol,
name: Name,
receiverTypeRef: FirTypeRef?,
returnTypeRef: FirTypeRef,
isVar: Boolean,
initializer: FirExpression?,
delegate: FirExpression?
) : super(session, psi, name, receiverTypeRef, returnTypeRef) {
this.isVar = isVar
this.initializer = initializer
this.delegate = delegate
this.symbol = symbol
this.backingFieldSymbol = FirBackingFieldSymbol(symbol.callableId)
this.delegateFieldSymbol = delegate?.let { FirDelegateFieldSymbol(symbol.callableId) }
bindSymbols(symbol)
}
constructor(
session: FirSession,
psi: PsiElement?,
symbol: FirPropertySymbol,
name: Name,
visibility: Visibility,
modality: Modality?,
isExpect: Boolean,
isActual: Boolean,
isOverride: Boolean,
isConst: Boolean,
isLateInit: Boolean,
receiverTypeRef: FirTypeRef?,
returnTypeRef: FirTypeRef,
isVar: Boolean,
initializer: FirExpression?,
delegate: FirExpression?
) : super(
session, psi, name, visibility, modality, isExpect, isActual, isOverride, receiverTypeRef, returnTypeRef
) {
this.isVar = isVar
this.initializer = initializer
this.delegate = delegate
status.isConst = isConst
status.isLateInit = isLateInit
this.symbol = symbol
this.backingFieldSymbol = FirBackingFieldSymbol(symbol.callableId)
this.delegateFieldSymbol = delegate?.let { FirDelegateFieldSymbol(symbol.callableId) }
bindSymbols(symbol)
}
// TODO: backing field may not exist
override val backingFieldSymbol: FirBackingFieldSymbol
override val delegateFieldSymbol: FirDelegateFieldSymbol<FirProperty>?
override var getter: FirPropertyAccessor? = null
@@ -56,14 +98,6 @@ class FirMemberPropertyImpl(
override var controlFlowGraphReference: FirControlFlowGraphReference = FirEmptyControlFlowGraphReference()
init {
symbol.bind(this)
backingFieldSymbol.bind(this)
delegateFieldSymbol?.bind(this)
status.isConst = isConst
status.isLateInit = isLateInit
}
override fun <D> transformChildrenWithoutAccessors(transformer: FirTransformer<D>, data: D) {
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data)
@@ -20,7 +20,12 @@ open class FirVariableSymbol<D : FirVariable<D>>(override val callableId: Callab
constructor(name: Name) : this(CallableId(name)) // TODO?
}
open class FirPropertySymbol(callableId: CallableId) : ConePropertySymbol, FirVariableSymbol<FirProperty>(callableId)
open class FirPropertySymbol(
callableId: CallableId,
val isFakeOverride: Boolean = false,
// Actual for fake override only
val overriddenSymbol: FirPropertySymbol? = null
) : ConePropertySymbol, FirVariableSymbol<FirProperty>(callableId)
class FirBackingFieldSymbol(callableId: CallableId) : FirVariableSymbol<FirProperty>(callableId)
@@ -77,7 +77,7 @@ FILE fqName:<root> fileName:/thisOfGenericOuterClass.kt
PROPERTY name:xx visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:xx type:IrErrorType visibility:private [final]
EXPRESSION_BODY
ERROR_CALL 'Unresolved reference: <Inapplicable(WRONG_RECEIVER): [kotlin/plus]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Ambiguity: plus, [kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus, kotlin/Int.plus]>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Unresolved name: y>#' type=IrErrorType
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-xx> visibility:public modality:FINAL <> ($this:<root>.test.<no name provided>) returnType:IrErrorType
correspondingProperty: PROPERTY name:xx visibility:public modality:FINAL [val]
+4 -3
View File
@@ -23,6 +23,7 @@ FILE fqName:<root> fileName:/builtinMap.kt
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (it:java.util.LinkedHashMap<K1 of <root>.plus, V1 of <root>.plus>) returnType:kotlin.Unit
VALUE_PARAMETER name:it index:0 type:java.util.LinkedHashMap<K1 of <root>.plus, V1 of <root>.plus>
BLOCK_BODY
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [java/util/HashMap.put]>#' type=IrErrorType
ERROR_CALL 'No getter found for R|kotlin/Pair.first|' type=A of kotlin.Pair
ERROR_CALL 'No getter found for R|kotlin/Pair.second|' type=B of kotlin.Pair
CALL 'public open fun put (<anonymous Java parameter>: K1 of <root>.plus, <anonymous Java parameter>: V1 of <root>.plus): V1 of <root>.plus declared in java.util.HashMap' type=V1 of <root>.plus origin=null
$this: GET_VAR '<this>: java.util.HashMap declared in java.util.HashMap' type=java.util.HashMap<*, *> origin=null
<anonymous Java parameter>: ERROR_CALL 'No getter found for R|kotlin/Pair.first|' type=K1 of <root>.plus
<anonymous Java parameter>: ERROR_CALL 'No getter found for R|kotlin/Pair.second|' type=V1 of <root>.plus
@@ -94,14 +94,13 @@ FILE fqName:<root> fileName:/localVariableOfIntersectionType_NI.kt
VALUE_PARAMETER name:b index:1 type:<root>.In<<root>.IB>
VALUE_PARAMETER name:z index:2 type:<root>.Z
BLOCK_BODY
ERROR_CALL 'Unresolved reference: <Unresolved name: foo>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Unresolved name: bar>#' type=IrErrorType
VAR name:t type:T of <root>.Inv [val]
CALL 'public abstract fun <get-t> (): T of <root>.Inv declared in <root>.Inv' type=T of <root>.Inv origin=null
$this: CALL 'public abstract fun create <T> (x: <root>.In<T of <root>.Z.create>, y: <root>.In<T of <root>.Z.create>): <root>.Inv<T of <root>.Z.create> declared in <root>.Z' type=<root>.Inv<<root>.IA> origin=null
<T>: <none>
$this: GET_VAR 'z: <root>.Z declared in <root>.test' type=<root>.Z origin=null
x: GET_VAR 'a: <root>.In<<root>.IA> declared in <root>.test' type=<root>.In<<root>.IA> origin=null
y: GET_VAR 'b: <root>.In<<root>.IB> declared in <root>.test' type=<root>.In<<root>.IB> origin=null
ERROR_CALL 'Unresolved reference: <Unresolved name: foo>#' type=IrErrorType
ERROR_CALL 'Unresolved reference: <Unresolved name: bar>#' type=IrErrorType
CALL 'public abstract fun foo (): kotlin.Unit declared in <root>.IA' type=kotlin.Unit origin=null
$this: ERROR_CALL 'No getter found for R|/Inv.t|' type=<root>.IA
CALL 'public abstract fun bar (): kotlin.Unit declared in <root>.IB' type=kotlin.Unit origin=null
$this: ERROR_CALL 'No getter found for R|/Inv.t|' type=<root>.IA
VAR name:t type:<root>.IA [val]
ERROR_CALL 'No getter found for R|/Inv.t|' type=<root>.IA
CALL 'public abstract fun foo (): kotlin.Unit declared in <root>.IA' type=kotlin.Unit origin=null
$this: GET_VAR 'val t: <root>.IA [val] declared in <root>.test' type=<root>.IA origin=null
CALL 'public abstract fun bar (): kotlin.Unit declared in <root>.IB' type=kotlin.Unit origin=null
$this: GET_VAR 'val t: <root>.IA [val] declared in <root>.test' type=<root>.IA origin=null