FIR Java types: handle wildcard types correctly

Related to KT-29937, KT-29218
This commit is contained in:
Mikhail Glukhikh
2019-02-28 12:59:18 +03:00
parent 6c79b184c0
commit 226cf8e42c
11 changed files with 43 additions and 20 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.java
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.fir.java.types.FirJavaTypeRef
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.constructType
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTagImpl
@@ -31,7 +33,7 @@ import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.Variance.*
internal val JavaModifierListOwner.modality: Modality
get() = when {
@@ -123,7 +125,13 @@ internal fun JavaType.toConeKotlinTypeWithNullability(session: FirSession, isNul
internal fun JavaClassifierType.toConeKotlinTypeWithNullability(session: FirSession, isNullable: Boolean): ConeLookupTagBasedType {
return when (val classifier = classifier) {
is JavaClass -> {
classifier.classId!!.toConeKotlinType(typeArguments.map { it.toConeProjection(session) }.toTypedArray(), isNullable)
val classId = classifier.classId!!
val symbol = session.service<FirSymbolProvider>().getClassLikeSymbolByFqName(classId) as? FirClassSymbol
symbol?.constructType(
typeArguments.mapIndexed { index, argument ->
argument.toConeProjection(session, symbol.fir.typeParameters.getOrNull(index))
}.toTypedArray(), isNullable
) ?: ConeClassErrorType("Symbol not found, for `$classId`")
}
is JavaTypeParameter -> {
// TODO: it's unclear how to identify type parameter by the symbol
@@ -137,7 +145,7 @@ internal fun JavaClassifierType.toConeKotlinTypeWithNullability(session: FirSess
internal fun createTypeParameterSymbol(session: FirSession, name: Name): FirTypeParameterSymbol {
val firSymbol = FirTypeParameterSymbol()
FirTypeParameterImpl(session, null, firSymbol, name, variance = Variance.INVARIANT, isReified = false)
FirTypeParameterImpl(session, null, firSymbol, name, variance = INVARIANT, isReified = false)
return firSymbol
}
@@ -164,11 +172,26 @@ internal fun FirAbstractAnnotatedElement.addAnnotationsFrom(javaAnnotationOwner:
}
}
private fun JavaType.toConeProjection(session: FirSession): ConeKotlinTypeProjection {
if (this is JavaClassifierType) {
return toConeKotlinTypeWithNullability(session, isNullable = false)
private fun JavaType.toConeProjection(session: FirSession, boundTypeParameter: FirTypeParameter?): ConeKotlinTypeProjection {
return when (this) {
is JavaWildcardType -> {
val bound = this.bound
val argumentVariance = if (isExtends) OUT_VARIANCE else IN_VARIANCE
val parameterVariance = boundTypeParameter?.variance ?: INVARIANT
if (bound == null || parameterVariance != INVARIANT && parameterVariance != argumentVariance) {
ConeStarProjection
} else {
val boundType = bound.toConeKotlinTypeWithNullability(session, isNullable = false)
if (argumentVariance == OUT_VARIANCE) {
ConeKotlinTypeProjectionOut(boundType)
} else {
ConeKotlinTypeProjectionIn(boundType)
}
}
}
is JavaClassifierType -> toConeKotlinTypeWithNullability(session, isNullable = false)
else -> ConeClassErrorType("Unexpected type argument: $this")
}
return ConeClassErrorType("Unexpected type argument: $this")
}
private fun JavaAnnotationArgument.toFirExpression(session: FirSession): FirExpression {
@@ -1,6 +1,6 @@
public abstract interface RemoveRedundantProjectionKind : R|java/lang/Object| {
public abstract operator function f(collection: R|ft<java/util/Collection<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends CharSequence>, java/util/Collection<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends CharSequence>?>|!): R|kotlin/Unit|
public abstract operator function f(collection: R|ft<java/util/Collection<out java/lang/CharSequence>, java/util/Collection<out java/lang/CharSequence>?>|!): R|kotlin/Unit|
public abstract operator function f(comparator: R|ft<java/lang/Comparable<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super CharSequence>, java/lang/Comparable<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super CharSequence>?>|!): R|kotlin/Unit|
public abstract operator function f(comparator: R|ft<java/lang/Comparable<in java/lang/CharSequence>, java/lang/Comparable<in java/lang/CharSequence>?>|!): R|kotlin/Unit|
}
@@ -1,6 +1,6 @@
public final class UnboundWildcard : R|java/lang/Object| {
public final operator function foo(): R|ft<test/UnboundWildcard.MyClass<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:?>, test/UnboundWildcard.MyClass<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:?>?>|!
public final operator function foo(): R|ft<test/UnboundWildcard.MyClass<*>, test/UnboundWildcard.MyClass<*>?>|!
public final operator function collection(): R|ft<java/util/Collection<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:?>, java/util/Collection<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:?>?>|!
public final operator function collection(): R|ft<java/util/Collection<*>, java/util/Collection<*>?>|!
}
@@ -1,4 +1,4 @@
public open class WildcardBounds : R|java/lang/Object| {
public/*package*/ open operator function foo(x: R|ft<test/WildcardBounds.A<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends CharSequence>, test/WildcardBounds.A<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends CharSequence>?>|!, y: R|ft<test/WildcardBounds.A<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super String>, test/WildcardBounds.A<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super String>?>|!): R|kotlin/Unit|
public/*package*/ open operator function foo(x: R|ft<test/WildcardBounds.A<out java/lang/CharSequence>, test/WildcardBounds.A<out java/lang/CharSequence>?>|!, y: R|ft<test/WildcardBounds.A<in java/lang/String>, test/WildcardBounds.A<in java/lang/String>?>|!): R|kotlin/Unit|
}
@@ -1,5 +1,5 @@
public open class MethodWithMappedClasses : R|java/lang/Object| {
public open operator function copy(dest: R|ft<java/util/List<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super T>, java/util/List<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super T>?>|!, src: R|ft<kotlin/collections/MutableList<ft<T, T?>>, kotlin/collections/List<ft<T, T?>>>|): R|kotlin/Unit|
public open operator function copy(dest: R|ft<java/util/List<in T>, java/util/List<in T>?>|!, src: R|ft<kotlin/collections/MutableList<ft<T, T?>>, kotlin/collections/List<ft<T, T?>>>|): R|kotlin/Unit|
public open operator function copyMap(dest: R|ft<kotlin/collections/MutableMap<ft<java/lang/String, java/lang/String?>, *>, kotlin/collections/Map<ft<java/lang/String, java/lang/String?>, *>>|, src: R|ft<kotlin/collections/MutableMap<ft<java/lang/String, java/lang/String?>, ft<T, T?>>, kotlin/collections/Map<ft<java/lang/String, java/lang/String?>, ft<T, T?>>>|): R|kotlin/Unit|
@@ -1,4 +1,4 @@
public open class MethodWithTypeParameters : R|java/lang/Object| {
public open operator function foo(a: R|ft<A, A?>|!, b: R|ft<java/util/List<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends B>, java/util/List<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends B>?>|!, list: R|ft<java/util/List<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super String>, java/util/List<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super String>?>|!): R|kotlin/Unit|
public open operator function foo(a: R|ft<A, A?>|!, b: R|ft<java/util/List<out B>, java/util/List<out B>?>|!, list: R|ft<java/util/List<in java/lang/String>, java/util/List<in java/lang/String>?>|!): R|kotlin/Unit|
}
@@ -1,4 +1,4 @@
public final class StarProjection : R|java/lang/Object| {
public final operator function foo(): R|ft<test/StarProjection.MyClass<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:?>, test/StarProjection.MyClass<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:?>?>|!
public final operator function foo(): R|ft<test/StarProjection.MyClass<*>, test/StarProjection.MyClass<*>?>|!
}
@@ -1,4 +1,4 @@
public open class WrongTypeParameterBoundStructure1 : R|java/lang/Object| {
public open operator function foo(a: R|ft<A, A?>|!, b: R|ft<java/util/List<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends B>, java/util/List<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends B>?>|!): R|kotlin/Unit|
public open operator function foo(a: R|ft<A, A?>|!, b: R|ft<java/util/List<out B>, java/util/List<out B>?>|!): R|kotlin/Unit|
}
@@ -1,4 +1,4 @@
public open class Max : R|java/lang/Object| {
public open operator function max(coll: R|ft<java/util/Collection<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends T>, java/util/Collection<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends T>?>|!): R|ft<T, T?>|!
public open operator function max(coll: R|ft<java/util/Collection<out T>, java/util/Collection<out T>?>|!): R|ft<T, T?>|!
}
@@ -1,6 +1,6 @@
public abstract interface ReadOnlyExtendsWildcard : R|java/lang/Object| {
public abstract operator function bar(): R|kotlin/Unit|
public abstract operator function foo(@R|kotlin/annotations/jvm/ReadOnly|() x: R|ft<kotlin/collections/List<*>, java/util/List<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? extends CharSequence>?>|!, @R|org/jetbrains/annotations/NotNull|() y: R|ft<kotlin/Comparable<*>, kotlin/Comparable<*>>|): R|kotlin/Unit|
public abstract operator function foo(@R|kotlin/annotations/jvm/ReadOnly|() x: R|ft<kotlin/collections/List<*>, java/util/List<out java/lang/CharSequence>?>|!, @R|org/jetbrains/annotations/NotNull|() y: R|ft<kotlin/Comparable<*>, kotlin/Comparable<*>>|): R|kotlin/Unit|
}
@@ -3,8 +3,8 @@ public open class NonTrivialFunctionType : R|java/lang/Object| {
public open operator function foo(comparator: R|ft<java/util/Comparator<ft<java/lang/String, java/lang/String?>>, java/util/Comparator<ft<java/lang/String, java/lang/String?>>>|): R|kotlin/Unit|
public open operator function wildcardUnbound(comparator: R|ft<java/util/Comparator<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:?>, java/util/Comparator<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:?>?>|!): R|kotlin/Unit|
public open operator function wildcardUnbound(comparator: R|ft<java/util/Comparator<*>, java/util/Comparator<*>?>|!): R|kotlin/Unit|
public open operator function wildcardBound(comparator: R|ft<java/util/Comparator<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super CharSequence>, java/util/Comparator<class error: Unexpected type argument: JavaWildcardTypeImpl: PsiType:? super CharSequence>?>|!): R|kotlin/Unit|
public open operator function wildcardBound(comparator: R|ft<java/util/Comparator<in java/lang/CharSequence>, java/util/Comparator<in java/lang/CharSequence>?>|!): R|kotlin/Unit|
}