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
|
package org.jetbrains.kotlin.fir.resolve
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
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(
|
fun ConeClassLikeType.wrapSubstitutionScopeIfNeed(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
useSiteMemberScope: FirScope,
|
useSiteMemberScope: FirScope,
|
||||||
@@ -108,23 +130,16 @@ fun ConeClassLikeType.wrapSubstitutionScopeIfNeed(
|
|||||||
if (this.typeArguments.isEmpty()) return useSiteMemberScope
|
if (this.typeArguments.isEmpty()) return useSiteMemberScope
|
||||||
return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this)) {
|
return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this)) {
|
||||||
val typeParameters = (declaration as? FirTypeParametersOwner)?.typeParameters.orEmpty()
|
val typeParameters = (declaration as? FirTypeParametersOwner)?.typeParameters.orEmpty()
|
||||||
@Suppress("UNCHECKED_CAST")
|
val originalSubstitution = createSubstitution(typeParameters, typeArguments, session)
|
||||||
val substitution = typeParameters.zip(this.typeArguments) { typeParameter, typeArgument ->
|
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(declaration.symbol.classId.asSingleFqName().toUnsafe())
|
||||||
val typeParameterSymbol = typeParameter.symbol
|
val javaClass = javaClassId?.let { session.firSymbolProvider.getClassLikeSymbolByFqName(it)?.fir } as? FirRegularClass
|
||||||
typeParameterSymbol to when (typeArgument) {
|
if (javaClass != null) {
|
||||||
is ConeTypedProjection -> {
|
val javaTypeParameters = javaClass.typeParameters
|
||||||
typeArgument.type
|
val javaSubstitution = createSubstitution(javaTypeParameters, typeArguments, session)
|
||||||
}
|
FirClassSubstitutionScope(session, useSiteMemberScope, builder, originalSubstitution + javaSubstitution)
|
||||||
else /* StarProjection */ -> {
|
} else {
|
||||||
ConeTypeIntersector.intersectTypes(
|
FirClassSubstitutionScope(session, useSiteMemberScope, builder, originalSubstitution)
|
||||||
session.inferenceContext(),
|
}
|
||||||
typeParameterSymbol.fir.bounds.map { it.coneTypeUnsafe() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.toMap()
|
|
||||||
|
|
||||||
FirClassSubstitutionScope(session, useSiteMemberScope, builder, substitution)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ FILE: test.kt
|
|||||||
public abstract interface UseIterable : R|MyIterable<kotlin/String>| {
|
public abstract interface UseIterable : R|MyIterable<kotlin/String>| {
|
||||||
public open fun test(): R|kotlin/Unit| {
|
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 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| {
|
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 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
|
// Java forEach
|
||||||
map.forEach { key, value ->
|
map.forEach { key, value ->
|
||||||
println("$key: $value")
|
println("$key: $value")
|
||||||
|
key.length
|
||||||
|
value.length
|
||||||
}
|
}
|
||||||
// Kotlin forEach
|
// Kotlin forEach
|
||||||
map.forEach { (key, value) ->
|
map.forEach { (key, value) ->
|
||||||
println("$key: $value")
|
println("$key: $value")
|
||||||
|
key.length
|
||||||
|
value.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,9 +31,13 @@ fun test(map: MutableMap<String, String>) {
|
|||||||
// Java forEach
|
// Java forEach
|
||||||
map.forEach { key, value ->
|
map.forEach { key, value ->
|
||||||
println("$key: $value")
|
println("$key: $value")
|
||||||
|
key.length
|
||||||
|
value.length
|
||||||
}
|
}
|
||||||
// Kotlin forEach
|
// Kotlin forEach
|
||||||
map.forEach { (key, value) ->
|
map.forEach { (key, value) ->
|
||||||
println("$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 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))
|
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|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> {
|
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 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|>()
|
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|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 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))
|
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|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> {
|
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 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|>()
|
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|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