FIR resolve: make substitution also for mapped Java type parameters
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve
|
||||
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
@@ -99,6 +100,27 @@ fun FirClass<*>.buildDefaultUseSiteMemberScope(useSiteSession: FirSession, scope
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSubstitution(
|
||||
typeParameters: List<FirTypeParameter>,
|
||||
typeArguments: Array<out ConeKotlinTypeProjection>,
|
||||
session: FirSession
|
||||
): Map<FirTypeParameterSymbol, ConeKotlinType> {
|
||||
return typeParameters.zip(typeArguments) { typeParameter, typeArgument ->
|
||||
val typeParameterSymbol = typeParameter.symbol
|
||||
typeParameterSymbol to when (typeArgument) {
|
||||
is ConeTypedProjection -> {
|
||||
typeArgument.type
|
||||
}
|
||||
else /* StarProjection */ -> {
|
||||
ConeTypeIntersector.intersectTypes(
|
||||
session.inferenceContext(),
|
||||
typeParameterSymbol.fir.bounds.map { it.coneTypeUnsafe() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
fun ConeClassLikeType.wrapSubstitutionScopeIfNeed(
|
||||
session: FirSession,
|
||||
useSiteMemberScope: FirScope,
|
||||
@@ -108,23 +130,16 @@ fun ConeClassLikeType.wrapSubstitutionScopeIfNeed(
|
||||
if (this.typeArguments.isEmpty()) return useSiteMemberScope
|
||||
return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this)) {
|
||||
val typeParameters = (declaration as? FirTypeParametersOwner)?.typeParameters.orEmpty()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val substitution = typeParameters.zip(this.typeArguments) { typeParameter, typeArgument ->
|
||||
val typeParameterSymbol = typeParameter.symbol
|
||||
typeParameterSymbol to when (typeArgument) {
|
||||
is ConeTypedProjection -> {
|
||||
typeArgument.type
|
||||
}
|
||||
else /* StarProjection */ -> {
|
||||
ConeTypeIntersector.intersectTypes(
|
||||
session.inferenceContext(),
|
||||
typeParameterSymbol.fir.bounds.map { it.coneTypeUnsafe() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}.toMap()
|
||||
|
||||
FirClassSubstitutionScope(session, useSiteMemberScope, builder, substitution)
|
||||
val originalSubstitution = createSubstitution(typeParameters, typeArguments, session)
|
||||
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(declaration.symbol.classId.asSingleFqName().toUnsafe())
|
||||
val javaClass = javaClassId?.let { session.firSymbolProvider.getClassLikeSymbolByFqName(it)?.fir } as? FirRegularClass
|
||||
if (javaClass != null) {
|
||||
val javaTypeParameters = javaClass.typeParameters
|
||||
val javaSubstitution = createSubstitution(javaTypeParameters, typeArguments, session)
|
||||
FirClassSubstitutionScope(session, useSiteMemberScope, builder, originalSubstitution + javaSubstitution)
|
||||
} else {
|
||||
FirClassSubstitutionScope(session, useSiteMemberScope, builder, originalSubstitution)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@ FILE: test.kt
|
||||
public abstract interface UseIterable : R|MyIterable<kotlin/String>| {
|
||||
public open fun test(): R|kotlin/Unit| {
|
||||
lval it: R|kotlin/collections/MutableIterator<kotlin/String>| = this@R|kotlin/collections/MutableIterable|.R|FakeOverride<kotlin/collections/MutableIterable.iterator: R|kotlin/collections/MutableIterator<kotlin/String>|>|()
|
||||
lval split: R|java/util/Spliterator<T!>| = this@R|java/lang/Iterable|.R|FakeOverride<java/lang/Iterable.spliterator: R|java/util/Spliterator<T!>|>|()
|
||||
lval split: R|java/util/Spliterator<kotlin/String!>| = this@R|java/lang/Iterable|.R|FakeOverride<java/lang/Iterable.spliterator: R|java/util/Spliterator<kotlin/String!>|>|()
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test(some: R|kotlin/collections/Iterable<kotlin/String>|): R|kotlin/Unit| {
|
||||
lval it: R|kotlin/collections/Iterator<kotlin/String>| = R|<local>/some|.R|FakeOverride<kotlin/collections/Iterable.iterator: R|kotlin/collections/Iterator<kotlin/String>|>|()
|
||||
lval split: R|java/util/Spliterator<T!>| = R|<local>/some|.R|FakeOverride<java/lang/Iterable.spliterator: R|java/util/Spliterator<T!>|>|()
|
||||
lval split: R|java/util/Spliterator<kotlin/String!>| = R|<local>/some|.R|FakeOverride<java/lang/Iterable.spliterator: R|java/util/Spliterator<kotlin/String!>|>|()
|
||||
}
|
||||
|
||||
@@ -12,10 +12,14 @@ fun test(map: MyMap) {
|
||||
// Java forEach
|
||||
map.forEach { key, value ->
|
||||
println("$key: $value")
|
||||
key.length
|
||||
value.length
|
||||
}
|
||||
// Kotlin forEach
|
||||
map.forEach { (key, value) ->
|
||||
println("$key: $value")
|
||||
key.length
|
||||
value.length
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +31,13 @@ fun test(map: MutableMap<String, String>) {
|
||||
// Java forEach
|
||||
map.forEach { key, value ->
|
||||
println("$key: $value")
|
||||
key.length
|
||||
value.length
|
||||
}
|
||||
// Kotlin forEach
|
||||
map.forEach { (key, value) ->
|
||||
println("$key: $value")
|
||||
key.length
|
||||
value.length
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -6,14 +6,18 @@ FILE: test.kt
|
||||
)
|
||||
lval otherResult: R|kotlin/String| = R|<local>/map|.R|FakeOverride<kotlin/collections/Map.getOrDefault: R|kotlin/String|>|(String(key), String(value))
|
||||
lval anotherResult: <ERROR TYPE REF: Unresolved name: replace> = R|<local>/map|.<Unresolved name: replace>#(String(key), String(value))
|
||||
R|<local>/map|.R|java/util/Map.forEach|(<L> = forEach@fun <anonymous>(key: R|K!|, value: R|V!|): R|kotlin/Unit| {
|
||||
R|<local>/map|.R|FakeOverride<java/util/Map.forEach: R|kotlin/Unit|>|(<L> = forEach@fun <anonymous>(key: R|kotlin/String!|, value: R|kotlin/String!|): R|kotlin/Unit| {
|
||||
R|kotlin/io/println|(<strcat>(R|<local>/key|.R|kotlin/Any.toString|(), String(: ), R|<local>/value|.R|kotlin/Any.toString|()))
|
||||
R|<local>/key|.R|kotlin/String.length|
|
||||
R|<local>/value|.R|kotlin/String.length|
|
||||
}
|
||||
)
|
||||
R|<local>/map|.R|kotlin/collections/forEach|<R|kotlin/String|, R|kotlin/String|>(<L> = forEach@fun <anonymous>(<destruct>: R|kotlin/collections/Map.Entry<kotlin/String, kotlin/String>|): R|kotlin/Unit| <kind=UNKNOWN> {
|
||||
lval key: R|kotlin/String| = R|<local>/<destruct>|.R|kotlin/collections/component1|<R|kotlin/String|, R|kotlin/String|>()
|
||||
lval value: R|kotlin/String| = R|<local>/<destruct>|.R|kotlin/collections/component2|<R|kotlin/String|, R|kotlin/String|>()
|
||||
R|kotlin/io/println|(<strcat>(R|<local>/key|.R|kotlin/Any.toString|(), String(: ), R|<local>/value|.R|kotlin/Any.toString|()))
|
||||
R|<local>/key|.R|kotlin/String.length|
|
||||
R|<local>/value|.R|kotlin/String.length|
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -24,14 +28,18 @@ FILE: test.kt
|
||||
)
|
||||
lval otherResult: R|kotlin/String| = R|<local>/map|.R|FakeOverride<kotlin/collections/Map.getOrDefault: R|kotlin/String|>|(String(key), String(value))
|
||||
lval anotherResult: <ERROR TYPE REF: Unresolved name: replace> = R|<local>/map|.<Unresolved name: replace>#(String(key), String(value))
|
||||
R|<local>/map|.R|java/util/Map.forEach|(<L> = forEach@fun <anonymous>(key: R|K!|, value: R|V!|): R|kotlin/Unit| {
|
||||
R|<local>/map|.R|FakeOverride<java/util/Map.forEach: R|kotlin/Unit|>|(<L> = forEach@fun <anonymous>(key: R|kotlin/String!|, value: R|kotlin/String!|): R|kotlin/Unit| {
|
||||
R|kotlin/io/println|(<strcat>(R|<local>/key|.R|kotlin/Any.toString|(), String(: ), R|<local>/value|.R|kotlin/Any.toString|()))
|
||||
R|<local>/key|.R|kotlin/String.length|
|
||||
R|<local>/value|.R|kotlin/String.length|
|
||||
}
|
||||
)
|
||||
R|<local>/map|.R|kotlin/collections/forEach|<R|kotlin/String|, R|kotlin/String|>(<L> = forEach@fun <anonymous>(<destruct>: R|kotlin/collections/Map.Entry<kotlin/String, kotlin/String>|): R|kotlin/Unit| <kind=UNKNOWN> {
|
||||
lval key: R|kotlin/String| = R|<local>/<destruct>|.R|kotlin/collections/component1|<R|kotlin/String|, R|kotlin/String|>()
|
||||
lval value: R|kotlin/String| = R|<local>/<destruct>|.R|kotlin/collections/component2|<R|kotlin/String|, R|kotlin/String|>()
|
||||
R|kotlin/io/println|(<strcat>(R|<local>/key|.R|kotlin/Any.toString|(), String(: ), R|<local>/value|.R|kotlin/Any.toString|()))
|
||||
R|<local>/key|.R|kotlin/String.length|
|
||||
R|<local>/value|.R|kotlin/String.length|
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user