FIR: Leave functions type parameters in subsituting scope
This commit is contained in:
+8
-6
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
||||
|
||||
|
||||
abstract class ConeSubstitutor : TypeSubstitutorMarker {
|
||||
abstract fun substituteOrSelf(type: ConeKotlinType): ConeKotlinType
|
||||
open fun substituteOrSelf(type: ConeKotlinType): ConeKotlinType = substituteOrNull(type) ?: type
|
||||
abstract fun substituteOrNull(type: ConeKotlinType): ConeKotlinType?
|
||||
|
||||
object Empty : ConeSubstitutor() {
|
||||
@@ -55,10 +55,6 @@ abstract class AbstractConeSubstitutor : ConeSubstitutor() {
|
||||
return type?.withNullability(ConeNullability.NULLABLE)
|
||||
}
|
||||
|
||||
override fun substituteOrSelf(type: ConeKotlinType): ConeKotlinType {
|
||||
return substituteOrNull(type) ?: type
|
||||
}
|
||||
|
||||
override fun substituteOrNull(type: ConeKotlinType): ConeKotlinType? {
|
||||
val newType = substituteType(type)
|
||||
return (newType ?: type.substituteRecursive())
|
||||
@@ -143,8 +139,14 @@ fun substitutorByMap(substitution: Map<FirTypeParameterSymbol, ConeKotlinType>):
|
||||
return ConeSubstitutorByMap(substitution)
|
||||
}
|
||||
|
||||
class ConeSubstitutorByMap(val substitution: Map<FirTypeParameterSymbol, ConeKotlinType>) : AbstractConeSubstitutor() {
|
||||
class ChainedSubstitutor(private val first: ConeSubstitutor, private val second: ConeSubstitutor) : ConeSubstitutor() {
|
||||
override fun substituteOrNull(type: ConeKotlinType): ConeKotlinType? {
|
||||
first.substituteOrNull(type)?.let { return second.substituteOrSelf(it) }
|
||||
return second.substituteOrNull(type)
|
||||
}
|
||||
}
|
||||
|
||||
class ConeSubstitutorByMap(val substitution: Map<FirTypeParameterSymbol, ConeKotlinType>) : AbstractConeSubstitutor() {
|
||||
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
||||
if (type !is ConeTypeParameterType) return null
|
||||
return makeNullableIfNeed(type.isMarkedNullable, substitution[type.lookupTag.symbol])
|
||||
|
||||
+73
-17
@@ -9,11 +9,11 @@ import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirField
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirFieldImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirPropertyImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorWithJump
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@@ -83,6 +84,10 @@ class FirClassSubstitutionScope(
|
||||
return substitutor.substituteOrNull(this)
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.substitute(substitutor: ConeSubstitutor): ConeKotlinType? {
|
||||
return substitutor.substituteOrNull(this)
|
||||
}
|
||||
|
||||
private fun createFakeOverrideFunction(original: FirFunctionSymbol<*>): FirFunctionSymbol<*> {
|
||||
val member = when (original) {
|
||||
is FirNamedFunctionSymbol -> original.fir
|
||||
@@ -90,21 +95,66 @@ class FirClassSubstitutionScope(
|
||||
else -> throw AssertionError("Should not be here")
|
||||
}
|
||||
|
||||
val receiverType = member.receiverTypeRef?.coneTypeUnsafe<ConeKotlinType>()
|
||||
val newReceiverType = receiverType?.substitute()
|
||||
|
||||
val returnType = typeCalculator.tryCalculateReturnType(member).type
|
||||
val newReturnType = returnType.substitute()
|
||||
|
||||
val newParameterTypes = member.valueParameters.map {
|
||||
it.returnTypeRef.coneTypeUnsafe<ConeKotlinType>().substitute()
|
||||
val newTypeParameters = member.typeParameters.map { originalParameter ->
|
||||
FirTypeParameterImpl(
|
||||
originalParameter.source, originalParameter.session, originalParameter.name,
|
||||
FirTypeParameterSymbol(), originalParameter.variance, originalParameter.isReified
|
||||
).apply {
|
||||
annotations += originalParameter.annotations
|
||||
}
|
||||
}
|
||||
|
||||
if (newReceiverType == null && newReturnType == null && newParameterTypes.all { it == null }) {
|
||||
val newSubstitutor =
|
||||
if (member.typeParameters.isEmpty())
|
||||
substitutor
|
||||
else {
|
||||
val substitutionMapForNewParameters = member.typeParameters.zip(newTypeParameters).map {
|
||||
Pair(it.first.symbol, ConeTypeParameterTypeImpl(it.second.symbol.toLookupTag(), isNullable = false))
|
||||
}.toMap()
|
||||
ChainedSubstitutor(substitutor, substitutorByMap(substitutionMapForNewParameters))
|
||||
}
|
||||
|
||||
val wereChangesInTypeParameters = fillBoundsForTypeParameters(newTypeParameters, member, newSubstitutor)
|
||||
|
||||
val receiverType = member.receiverTypeRef?.coneTypeUnsafe<ConeKotlinType>()
|
||||
val newReceiverType = receiverType?.substitute(newSubstitutor)
|
||||
|
||||
val returnType = typeCalculator.tryCalculateReturnType(member).type
|
||||
val newReturnType = returnType.substitute(newSubstitutor)
|
||||
|
||||
val newParameterTypes = member.valueParameters.map {
|
||||
it.returnTypeRef.coneTypeUnsafe<ConeKotlinType>().substitute(newSubstitutor)
|
||||
}
|
||||
|
||||
if (newReceiverType == null && newReturnType == null && newParameterTypes.all { it == null } && !wereChangesInTypeParameters) {
|
||||
return original
|
||||
}
|
||||
|
||||
return createFakeOverrideFunction(session, member, original, newReceiverType, newReturnType, newParameterTypes)
|
||||
return createFakeOverrideFunction(
|
||||
session, member, original, newReceiverType, newReturnType, newParameterTypes, newTypeParameters
|
||||
)
|
||||
}
|
||||
|
||||
private fun fillBoundsForTypeParameters(
|
||||
newTypeParameters: List<FirTypeParameterImpl>,
|
||||
member: FirSimpleFunction,
|
||||
newSubstitutor: ConeSubstitutor
|
||||
): Boolean {
|
||||
var wereChangesInTypeParameters = false
|
||||
for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(member.typeParameters)) {
|
||||
for (boundTypeRef in oldTypeParameter.bounds) {
|
||||
val typeForBound = boundTypeRef.coneTypeUnsafe<ConeKotlinType>()
|
||||
val substitutedBound = typeForBound.substitute(newSubstitutor)
|
||||
if (substitutedBound == null) {
|
||||
newTypeParameter.bounds += boundTypeRef
|
||||
} else {
|
||||
newTypeParameter.bounds += FirResolvedTypeRefImpl(boundTypeRef.source, substitutedBound)
|
||||
wereChangesInTypeParameters = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wereChangesInTypeParameters
|
||||
}
|
||||
|
||||
private fun createFakeOverrideProperty(original: FirPropertySymbol): FirPropertySymbol {
|
||||
@@ -156,7 +206,8 @@ class FirClassSubstitutionScope(
|
||||
baseFunction: FirSimpleFunction,
|
||||
newReceiverType: ConeKotlinType? = null,
|
||||
newReturnType: ConeKotlinType? = null,
|
||||
newParameterTypes: List<ConeKotlinType?>? = null
|
||||
newParameterTypes: List<ConeKotlinType?>? = null,
|
||||
newTypeParameters: List<FirTypeParameter>? = null
|
||||
): FirSimpleFunction {
|
||||
return with(baseFunction) {
|
||||
// TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl
|
||||
@@ -188,6 +239,8 @@ class FirClassSubstitutionScope(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
typeParameters += newTypeParameters ?: baseFunction.typeParameters
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,10 +251,13 @@ class FirClassSubstitutionScope(
|
||||
baseSymbol: FirNamedFunctionSymbol,
|
||||
newReceiverType: ConeKotlinType? = null,
|
||||
newReturnType: ConeKotlinType? = null,
|
||||
newParameterTypes: List<ConeKotlinType?>? = null
|
||||
newParameterTypes: List<ConeKotlinType?>? = null,
|
||||
newTypeParameters: List<FirTypeParameter>? = null
|
||||
): FirNamedFunctionSymbol {
|
||||
val symbol = FirNamedFunctionSymbol(baseSymbol.callableId, true, baseSymbol)
|
||||
createFakeOverrideFunction(symbol, session, baseFunction, newReceiverType, newReturnType, newParameterTypes)
|
||||
createFakeOverrideFunction(
|
||||
symbol, session, baseFunction, newReceiverType, newReturnType, newParameterTypes, newTypeParameters
|
||||
)
|
||||
return symbol
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
interface Ext<M : Message<M>, T>
|
||||
interface Message<M : Message<M>> {
|
||||
fun <T> ext(e: Ext<M, T>): T
|
||||
}
|
||||
|
||||
class MyMessage : Message<MyMessage>
|
||||
class MyExt : Ext<MyMessage, String>
|
||||
|
||||
fun <M : Message<M>, T> Message<M>.extF(e: Ext<M, T>): T = ext(e)
|
||||
|
||||
fun foo(m: MyMessage, e: MyExt) {
|
||||
m.ext(e)
|
||||
m.extF(e)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
FILE: protobufExt.kt
|
||||
public abstract interface Ext<M : R|Message<M>|, T> : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface Message<M : R|Message<M>|> : R|kotlin/Any| {
|
||||
public abstract fun <T> ext(e: R|Ext<M, T>|): R|T|
|
||||
|
||||
}
|
||||
public final class MyMessage : R|Message<MyMessage>| {
|
||||
public constructor(): R|MyMessage| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final class MyExt : R|Ext<MyMessage, kotlin/String>| {
|
||||
public constructor(): R|MyExt| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final fun <M : R|Message<M>|, T> R|Message<M>|.extF(e: R|Ext<M, T>|): R|T| {
|
||||
^extF this@R|/Message|.R|FakeOverride</Message.ext: R|T|>|<R|T|>(R|<local>/e|)
|
||||
}
|
||||
public final fun foo(m: R|MyMessage|, e: R|MyExt|): R|kotlin/Unit| {
|
||||
R|<local>/m|.R|FakeOverride</Message.ext: R|T|>|<R|kotlin/String|>(R|<local>/e|)
|
||||
R|<local>/m|.R|/extF|<R|MyMessage|, R|kotlin/String|>(R|<local>/e|)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
interface I<F> {
|
||||
fun <T : Comparable<T>> f(t: List<T>, f: List<F>): Any// T = D, List<D> == List<D>
|
||||
}
|
||||
|
||||
abstract class Base<E> {
|
||||
fun <D : Comparable<D>> f(t: List<D>, e: List<E>) {}
|
||||
}
|
||||
|
||||
|
||||
class C : Base<String>(), I<String>
|
||||
|
||||
fun f(list: List<Int>, s: List<String>) {
|
||||
C().f(list, s)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
FILE: supertypeGenerics.kt
|
||||
public abstract interface I<F> : R|kotlin/Any| {
|
||||
public abstract fun <T : R|kotlin/Comparable<T>|> f(t: R|kotlin/collections/List<T>|, f: R|kotlin/collections/List<F>|): R|kotlin/Any|
|
||||
|
||||
}
|
||||
public abstract class Base<E> : R|kotlin/Any| {
|
||||
public constructor<E>(): R|Base<E>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun <D : R|kotlin/Comparable<D>|> f(t: R|kotlin/collections/List<D>|, e: R|kotlin/collections/List<E>|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
public final class C : R|Base<kotlin/String>|, R|I<kotlin/String>| {
|
||||
public constructor(): R|C| {
|
||||
super<R|Base<kotlin/String>|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final fun f(list: R|kotlin/collections/List<kotlin/Int>|, s: R|kotlin/collections/List<kotlin/String>|): R|kotlin/Unit| {
|
||||
R|/C.C|().R|FakeOverride</Base.f: R|kotlin/Unit|>|<R|kotlin/Int|>(R|<local>/list|, R|<local>/s|)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
class Out<out T>
|
||||
|
||||
interface X : Out<String>
|
||||
|
||||
abstract class Base<E> {
|
||||
fun <D : Out<E>> f(t: MutableList<D>, e: MutableList<E>) {}
|
||||
}
|
||||
|
||||
class C : Base<CharSequence>()
|
||||
|
||||
fun f(list: MutableList<X>, s: MutableList<CharSequence>) {
|
||||
C().f(list, s)
|
||||
C().<!INAPPLICABLE_CANDIDATE!>f<!>(s, list)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
FILE: supertypeGenericsComplex.kt
|
||||
public final class Out<out T> : R|kotlin/Any| {
|
||||
public constructor<T>(): R|Out<T>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public abstract interface X : R|Out<kotlin/String>| {
|
||||
}
|
||||
public abstract class Base<E> : R|kotlin/Any| {
|
||||
public constructor<E>(): R|Base<E>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun <D : R|Out<E>|> f(t: R|kotlin/collections/MutableList<D>|, e: R|kotlin/collections/MutableList<E>|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
public final class C : R|Base<kotlin/CharSequence>| {
|
||||
public constructor(): R|C| {
|
||||
super<R|Base<kotlin/CharSequence>|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final fun f(list: R|kotlin/collections/MutableList<X>|, s: R|kotlin/collections/MutableList<kotlin/CharSequence>|): R|kotlin/Unit| {
|
||||
R|/C.C|().R|FakeOverride</Base.f: R|kotlin/Unit|>|<R|X|>(R|<local>/list|, R|<local>/s|)
|
||||
R|/C.C|().<Inapplicable(INAPPLICABLE): [/Base.f]>#(R|<local>/s|, R|<local>/list|)
|
||||
}
|
||||
+15
@@ -825,6 +825,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/overrides/generics.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("protobufExt.kt")
|
||||
public void testProtobufExt() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/overrides/protobufExt.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/overrides/simple.kt");
|
||||
@@ -835,6 +840,16 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/overrides/simpleFakeOverride.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("supertypeGenerics.kt")
|
||||
public void testSupertypeGenerics() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/overrides/supertypeGenerics.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("supertypeGenericsComplex.kt")
|
||||
public void testSupertypeGenericsComplex() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/overrides/supertypeGenericsComplex.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("three.kt")
|
||||
public void testThree() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/overrides/three.kt");
|
||||
|
||||
+3
-2
@@ -46,12 +46,13 @@ FILE fqName:<root> fileName:/delegatedMembers.kt
|
||||
overridden:
|
||||
public abstract fun <get-bar> (): kotlin.Int declared in <root>.IBase
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.Test
|
||||
FUN FAKE_OVERRIDE name:qux visibility:public modality:ABSTRACT <> ($this:<root>.IBase, t:TT of <root>.Test, x:X of <root>.IBase.qux) returnType:kotlin.Unit [fake_override]
|
||||
FUN FAKE_OVERRIDE name:qux visibility:public modality:ABSTRACT <X> ($this:<root>.IBase, t:TT of <root>.Test, x:X of <root>.Test.qux) returnType:kotlin.Unit [fake_override]
|
||||
overridden:
|
||||
public abstract fun qux <X> (t: T of <root>.IBase, x: X of <root>.IBase.qux): kotlin.Unit declared in <root>.IBase
|
||||
TYPE_PARAMETER name:X index:0 variance: superTypes:[kotlin.Any?]
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.IBase
|
||||
VALUE_PARAMETER name:t index:0 type:TT of <root>.Test
|
||||
VALUE_PARAMETER name:x index:1 type:X of <root>.IBase.qux
|
||||
VALUE_PARAMETER name:x index:1 type:X of <root>.Test.qux
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override]
|
||||
overridden:
|
||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any
|
||||
|
||||
@@ -137,11 +137,12 @@ FILE fqName:<root> fileName:/useImportedMember.kt
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN FAKE_OVERRIDE name:fromInterface visibility:public modality:OPEN <> ($this:<root>.I, $receiver:T of <root>.I.fromInterface) returnType:T of <root>.I.fromInterface [fake_override]
|
||||
FUN FAKE_OVERRIDE name:fromInterface visibility:public modality:OPEN <T> ($this:<root>.I, $receiver:T of <root>.C.fromInterface) returnType:T of <root>.C.fromInterface [fake_override]
|
||||
overridden:
|
||||
public open fun fromInterface <T> (): T of <root>.I.fromInterface declared in <root>.I
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.I
|
||||
$receiver: VALUE_PARAMETER name:<this> type:T of <root>.I.fromInterface
|
||||
$receiver: VALUE_PARAMETER name:<this> type:T of <root>.C.fromInterface
|
||||
FUN FAKE_OVERRIDE name:genericFromSuper visibility:public modality:OPEN <> ($this:<root>.I, g:kotlin.String) returnType:kotlin.String [fake_override]
|
||||
overridden:
|
||||
public open fun genericFromSuper (g: G of <root>.I): G of <root>.I declared in <root>.I
|
||||
|
||||
Reference in New Issue
Block a user