diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt index fc5782771fb..c7ca16ea193 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/LazyJavaTypeResolver.kt @@ -260,83 +260,7 @@ class LazyJavaTypeResolver( } override fun computeCustomSubstitution() = if (isRaw()) RawSubstitution else null - - private object RawSubstitution : TypeSubstitution() { - override fun get(key: JetType) = TypeProjectionImpl(eraseType(key)) - - private val lowerTypeAttr = MEMBER_SIGNATURE_INVARIANT.toAttributes().toFlexible(FLEXIBLE_LOWER_BOUND) - private val upperTypeAttr = MEMBER_SIGNATURE_INVARIANT.toAttributes().toFlexible(FLEXIBLE_UPPER_BOUND) - - private fun eraseType(type: JetType): JetType { - val declaration = type.constructor.declarationDescriptor - return when (declaration) { - is TypeParameterDescriptor -> eraseType(declaration.getErasedUpperBound()) - is ClassDescriptor -> { - val lower = type.lowerIfFlexible() - val upper = type.upperIfFlexible() - FlexibleJavaClassifierTypeCapabilities.create( - eraseInflexibleBasedOnClassDescriptor(lower, declaration, lowerTypeAttr), - eraseInflexibleBasedOnClassDescriptor(upper, declaration, upperTypeAttr) - ) - } - else -> error("Unexpected declaration kind: $declaration") - } - } - - private fun eraseInflexibleBasedOnClassDescriptor(type: JetType, declaration: ClassDescriptor, attr: JavaTypeAttributes): JetType { - if (KotlinBuiltIns.isArray(type)) { - val componentTypeProjection = type.arguments[0] - val arguments = listOf( - TypeProjectionImpl(componentTypeProjection.projectionKind, eraseType(componentTypeProjection.type)) - ) - return JetTypeImpl.create( - type.annotations, type.constructor, type.isMarkedNullable, arguments, - (type.constructor.declarationDescriptor as ClassDescriptor).getMemberScope(arguments) - ) - } - - val constructor = type.constructor - return JetTypeImpl.create( - type.annotations, constructor, type.isMarkedNullable, - type.constructor.parameters.map { - parameter -> computeProjection(parameter, attr) - }, - RawSubstitution, - declaration.getMemberScope(RawSubstitution) - ) - } - - fun computeProjection( - parameter: TypeParameterDescriptor, - attr: JavaTypeAttributes, - erasedUpperBound: JetType = parameter.getErasedUpperBound() - ) = when (attr.flexibility) { - // Raw(List) => (List..List<*>) - // Raw(Enum) => (Enum>..Enum>) - // In the last case upper bound is equal to star projection `Enum<*>`, - // but we want to keep matching tree structure of flexible bounds (at least they should have the same size) - FLEXIBLE_LOWER_BOUND -> TypeProjectionImpl( - // T : String -> String - // in T : String -> String - // T : Enum -> Enum<*> - Variance.INVARIANT, erasedUpperBound - ) - FLEXIBLE_UPPER_BOUND, INFLEXIBLE -> { - if (!parameter.variance.allowsOutPosition) - // in T -> Comparable - TypeProjectionImpl(Variance.INVARIANT, parameter.lowerBounds.first()) - else if (erasedUpperBound.constructor.parameters.isNotEmpty()) - // T : Enum -> out Enum<*> - TypeProjectionImpl(Variance.OUT_VARIANCE, erasedUpperBound) - else - // T : String -> * - makeStarProjection(parameter, attr) - } - } - - override fun isEmpty() = false - } - + private val nullable = c.storageManager.createLazyValue l@ { when (attr.flexibility) { FLEXIBLE_LOWER_BOUND -> return@l false diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/RawType.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/RawType.kt new file mode 100644 index 00000000000..0cdefef7246 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/types/RawType.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.load.java.lazy.types + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.load.java.components.TypeUsage +import org.jetbrains.kotlin.types.* + +private object RawSubstitution : TypeSubstitution() { + override fun get(key: JetType) = TypeProjectionImpl(eraseType(key)) + + private val lowerTypeAttr = TypeUsage.MEMBER_SIGNATURE_INVARIANT.toAttributes().toFlexible(JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND) + private val upperTypeAttr = TypeUsage.MEMBER_SIGNATURE_INVARIANT.toAttributes().toFlexible(JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND) + + private fun eraseType(type: JetType): JetType { + val declaration = type.constructor.declarationDescriptor + return when (declaration) { + is TypeParameterDescriptor -> eraseType(declaration.getErasedUpperBound()) + is ClassDescriptor -> { + val lower = type.lowerIfFlexible() + val upper = type.upperIfFlexible() + LazyJavaTypeResolver.FlexibleJavaClassifierTypeCapabilities.create( + eraseInflexibleBasedOnClassDescriptor(lower, declaration, lowerTypeAttr), + eraseInflexibleBasedOnClassDescriptor(upper, declaration, upperTypeAttr) + ) + } + else -> error("Unexpected declaration kind: $declaration") + } + } + + private fun eraseInflexibleBasedOnClassDescriptor(type: JetType, declaration: ClassDescriptor, attr: JavaTypeAttributes): JetType { + if (KotlinBuiltIns.isArray(type)) { + val componentTypeProjection = type.arguments[0] + val arguments = listOf( + TypeProjectionImpl(componentTypeProjection.projectionKind, eraseType(componentTypeProjection.type)) + ) + return JetTypeImpl.create( + type.annotations, type.constructor, type.isMarkedNullable, arguments, + (type.constructor.declarationDescriptor as ClassDescriptor).getMemberScope(arguments) + ) + } + + val constructor = type.constructor + return JetTypeImpl.create( + type.annotations, constructor, type.isMarkedNullable, + type.constructor.parameters.map { + parameter -> + computeProjection(parameter, attr) + }, + RawSubstitution, + declaration.getMemberScope(RawSubstitution) + ) + } + + fun computeProjection( + parameter: TypeParameterDescriptor, + attr: JavaTypeAttributes, + erasedUpperBound: JetType = parameter.getErasedUpperBound() + ) = when (attr.flexibility) { + // Raw(List) => (List..List<*>) + // Raw(Enum) => (Enum>..Enum>) + // In the last case upper bound is equal to star projection `Enum<*>`, + // but we want to keep matching tree structure of flexible bounds (at least they should have the same size) + JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND -> TypeProjectionImpl( + // T : String -> String + // in T : String -> String + // T : Enum -> Enum<*> + Variance.INVARIANT, erasedUpperBound + ) + JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND, JavaTypeFlexibility.INFLEXIBLE -> { + if (!parameter.variance.allowsOutPosition) + // in T -> Comparable + TypeProjectionImpl(Variance.INVARIANT, parameter.lowerBounds.first()) + else if (erasedUpperBound.constructor.parameters.isNotEmpty()) + // T : Enum -> out Enum<*> + TypeProjectionImpl(Variance.OUT_VARIANCE, erasedUpperBound) + else + // T : String -> * + makeStarProjection(parameter, attr) + } + } + + override fun isEmpty() = false +}