Refactoring. Move flexible type creation to KotlinTypeFactory.

This commit is contained in:
Stanislav Erokhin
2016-05-25 13:15:13 +03:00
parent 3a451744c5
commit 957bae18be
22 changed files with 168 additions and 149 deletions
@@ -16,12 +16,11 @@
package org.jetbrains.kotlin.load.java
import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver.FlexibleJavaClassifierTypeFactory
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.TypeResolver.TypeTransformerForTests
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.*
object InternalFlexibleTypeTransformer : TypeTransformerForTests() {
// This is a "magic" classifier: when type resolver sees it in the code, e.g. ft<Foo, Foo?>, instead of creating a normal type,
@@ -35,7 +34,7 @@ object InternalFlexibleTypeTransformer : TypeTransformerForTests() {
val descriptor = kotlinType.constructor.declarationDescriptor
if (descriptor != null && FLEXIBLE_TYPE_CLASSIFIER.asSingleFqName().toUnsafe() == DescriptorUtils.getFqName(descriptor)
&& kotlinType.arguments.size == 2) {
return FlexibleJavaClassifierTypeFactory.create(kotlinType.arguments[0].type, kotlinType.arguments[1].type)
return KotlinTypeFactory.flexibleType(kotlinType.arguments[0].type.asSimpleType(), kotlinType.arguments[1].type.asSimpleType())
}
return null
}
@@ -72,7 +72,8 @@ public class SingleAbstractMethodUtils {
"' should not end with conflict";
if (FlexibleTypesKt.isNullabilityFlexible(samType)) {
return LazyJavaTypeResolver.FlexibleJavaClassifierTypeFactory.INSTANCE.create(type, TypeUtils.makeNullable(type));
SimpleType simpleType = KotlinTypeKt.asSimpleType(type);
return KotlinTypeFactory.flexibleType(simpleType, TypeUtils.makeNullable(simpleType));
}
return TypeUtils.makeNullableAsSpecified(type, samType.isMarkedNullable());
@@ -83,9 +83,8 @@ public class CommonSupertypes {
private static KotlinType findCommonSupertype(@NotNull Collection<KotlinType> types, int recursionDepth, int maxDepth) {
assert recursionDepth <= maxDepth : "Recursion depth exceeded: " + recursionDepth + " > " + maxDepth + " for types " + types;
boolean hasFlexible = false;
List<KotlinType> upper = new ArrayList<KotlinType>(types.size());
List<KotlinType> lower = new ArrayList<KotlinType>(types.size());
Set<FlexibleTypeFactory> factories = new LinkedHashSet<FlexibleTypeFactory>();
List<SimpleType> upper = new ArrayList<SimpleType>(types.size());
List<SimpleType> lower = new ArrayList<SimpleType>(types.size());
for (KotlinType type : types) {
if (FlexibleTypesKt.isFlexible(type)) {
if (DynamicTypesKt.isDynamic(type)) {
@@ -95,33 +94,33 @@ public class CommonSupertypes {
Flexibility flexibility = FlexibleTypesKt.flexibility(type);
upper.add(flexibility.getUpperBound());
lower.add(flexibility.getLowerBound());
factories.add(flexibility.getFactory());
}
else {
upper.add(type);
lower.add(type);
upper.add(KotlinTypeKt.asSimpleType(type));
lower.add(KotlinTypeKt.asSimpleType(type));
}
}
if (!hasFlexible) return commonSuperTypeForInflexible(types, recursionDepth, maxDepth);
return CollectionsKt.single(factories).create( // mixing different factories is not supported
if (!hasFlexible) return commonSuperTypeForInflexible(upper, recursionDepth, maxDepth);
return KotlinTypeFactory.flexibleType( // mixing different factories is not supported
commonSuperTypeForInflexible(lower, recursionDepth, maxDepth),
commonSuperTypeForInflexible(upper, recursionDepth, maxDepth)
);
}
@NotNull
private static KotlinType commonSuperTypeForInflexible(@NotNull Collection<KotlinType> types, int recursionDepth, int maxDepth) {
private static SimpleType commonSuperTypeForInflexible(@NotNull Collection<SimpleType> types, int recursionDepth, int maxDepth) {
assert !types.isEmpty();
Collection<KotlinType> typeSet = new HashSet<KotlinType>(types);
Collection<SimpleType> typeSet = new HashSet<SimpleType>(types);
// todo: dead code?
KotlinType bestFit = FlexibleTypesKt.singleBestRepresentative(typeSet);
if (bestFit != null) return bestFit;
if (bestFit != null) return KotlinTypeKt.asSimpleType(bestFit);
// If any of the types is nullable, the result must be nullable
// This also removed Nothing and Nothing? because they are subtypes of everything else
boolean nullable = false;
for (Iterator<KotlinType> iterator = typeSet.iterator(); iterator.hasNext();) {
for (Iterator<SimpleType> iterator = typeSet.iterator(); iterator.hasNext();) {
KotlinType type = iterator.next();
assert type != null;
assert !FlexibleTypesKt.isFlexible(type) : "Flexible type " + type + " passed to commonSuperTypeForInflexible";
@@ -146,10 +145,10 @@ public class CommonSupertypes {
}
// constructor of the supertype -> all of its instantiations occurring as supertypes
Map<TypeConstructor, Set<KotlinType>> commonSupertypes = computeCommonRawSupertypes(typeSet);
Map<TypeConstructor, Set<SimpleType>> commonSupertypes = computeCommonRawSupertypes(typeSet);
while (commonSupertypes.size() > 1) {
Set<KotlinType> merge = new HashSet<KotlinType>();
for (Set<KotlinType> supertypes : commonSupertypes.values()) {
Set<SimpleType> merge = new HashSet<SimpleType>();
for (Set<SimpleType> supertypes : commonSupertypes.values()) {
merge.addAll(supertypes);
}
commonSupertypes = computeCommonRawSupertypes(merge);
@@ -157,24 +156,24 @@ public class CommonSupertypes {
assert !commonSupertypes.isEmpty() : commonSupertypes + " <- " + types;
// constructor of the supertype -> all of its instantiations occurring as supertypes
Map.Entry<TypeConstructor, Set<KotlinType>> entry = commonSupertypes.entrySet().iterator().next();
Map.Entry<TypeConstructor, Set<SimpleType>> entry = commonSupertypes.entrySet().iterator().next();
// Reconstructing type arguments if possible
KotlinType result = computeSupertypeProjections(entry.getKey(), entry.getValue(), recursionDepth, maxDepth);
SimpleType result = computeSupertypeProjections(entry.getKey(), entry.getValue(), recursionDepth, maxDepth);
return TypeUtils.makeNullableIfNeeded(result, nullable);
}
// Raw supertypes are superclasses w/o type arguments
// @return TypeConstructor -> all instantiations of this constructor occurring as supertypes
@NotNull
private static Map<TypeConstructor, Set<KotlinType>> computeCommonRawSupertypes(@NotNull Collection<KotlinType> types) {
private static Map<TypeConstructor, Set<SimpleType>> computeCommonRawSupertypes(@NotNull Collection<SimpleType> types) {
assert !types.isEmpty();
Map<TypeConstructor, Set<KotlinType>> constructorToAllInstances = new HashMap<TypeConstructor, Set<KotlinType>>();
Map<TypeConstructor, Set<SimpleType>> constructorToAllInstances = new HashMap<TypeConstructor, Set<SimpleType>>();
Set<TypeConstructor> commonSuperclasses = null;
List<TypeConstructor> order = null;
for (KotlinType type : types) {
for (SimpleType type : types) {
Set<TypeConstructor> visited = new HashSet<TypeConstructor>();
order = topologicallySortSuperclassesAndRecordAllInstances(type, constructorToAllInstances, visited);
@@ -188,7 +187,7 @@ public class CommonSupertypes {
assert order != null;
Set<TypeConstructor> notSource = new HashSet<TypeConstructor>();
Map<TypeConstructor, Set<KotlinType>> result = new HashMap<TypeConstructor, Set<KotlinType>>();
Map<TypeConstructor, Set<SimpleType>> result = new HashMap<TypeConstructor, Set<SimpleType>>();
for (TypeConstructor superConstructor : order) {
if (!commonSuperclasses.contains(superConstructor)) {
continue;
@@ -206,7 +205,7 @@ public class CommonSupertypes {
// constructor - type constructor of a supertype to be instantiated
// types - instantiations of constructor occurring as supertypes of classes we are trying to intersect
@NotNull
private static KotlinType computeSupertypeProjections(@NotNull TypeConstructor constructor, @NotNull Set<KotlinType> types, int recursionDepth, int maxDepth) {
private static SimpleType computeSupertypeProjections(@NotNull TypeConstructor constructor, @NotNull Set<SimpleType> types, int recursionDepth, int maxDepth) {
// we assume that all the given types are applications of the same type constructor
assert !types.isEmpty();
@@ -332,42 +331,42 @@ public class CommonSupertypes {
@NotNull
public static List<TypeConstructor> topologicallySortSuperclassesAndRecordAllInstances(
@NotNull KotlinType type,
@NotNull final Map<TypeConstructor, Set<KotlinType>> constructorToAllInstances,
@NotNull SimpleType type,
@NotNull final Map<TypeConstructor, Set<SimpleType>> constructorToAllInstances,
@NotNull final Set<TypeConstructor> visited
) {
return DFS.dfs(
Collections.singletonList(type),
new DFS.Neighbors<KotlinType>() {
new DFS.Neighbors<SimpleType>() {
@NotNull
@Override
public Iterable<KotlinType> getNeighbors(KotlinType current) {
public Iterable<? extends SimpleType> getNeighbors(SimpleType current) {
TypeSubstitutor substitutor = TypeSubstitutor.create(current);
Collection<KotlinType> supertypes = current.getConstructor().getSupertypes();
List<KotlinType> result = new ArrayList<KotlinType>(supertypes.size());
List<SimpleType> result = new ArrayList<SimpleType>(supertypes.size());
for (KotlinType supertype : supertypes) {
if (visited.contains(supertype.getConstructor())) {
continue;
}
result.add(substitutor.safeSubstitute(supertype, Variance.INVARIANT));
result.add(KotlinTypeKt.asSimpleType(substitutor.safeSubstitute(supertype, Variance.INVARIANT)));
}
return result;
}
},
new DFS.Visited<KotlinType>() {
new DFS.Visited<SimpleType>() {
@Override
public boolean checkAndMarkVisited(KotlinType current) {
public boolean checkAndMarkVisited(SimpleType current) {
return visited.add(current.getConstructor());
}
},
new DFS.NodeHandlerWithListResult<KotlinType, TypeConstructor>() {
new DFS.NodeHandlerWithListResult<SimpleType, TypeConstructor>() {
@Override
public boolean beforeChildren(KotlinType current) {
public boolean beforeChildren(SimpleType current) {
TypeConstructor constructor = current.getConstructor();
Set<KotlinType> instances = constructorToAllInstances.get(constructor);
Set<SimpleType> instances = constructorToAllInstances.get(constructor);
if (instances == null) {
instances = new HashSet<KotlinType>();
instances = new HashSet<SimpleType>();
constructorToAllInstances.put(constructor, instances);
}
instances.add(current);
@@ -376,7 +375,7 @@ public class CommonSupertypes {
}
@Override
public void afterChildren(KotlinType current) {
public void afterChildren(SimpleType current) {
result.addFirst(current.getConstructor());
}
}
@@ -17,8 +17,8 @@
package org.jetbrains.kotlin.jvm.compiler
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver
import org.jetbrains.kotlin.test.KotlinTestWithEnvironmentManagement
import org.jetbrains.kotlin.types.KotlinTypeFactory
class FlexibleTypeAssertionsEnabledTest : KotlinTestWithEnvironmentManagement() {
@@ -26,8 +26,7 @@ class FlexibleTypeAssertionsEnabledTest : KotlinTestWithEnvironmentManagement()
val builtIns = DefaultBuiltIns.Instance
try {
LazyJavaTypeResolver.FlexibleJavaClassifierTypeFactory.create(
builtIns.intType, builtIns.stringType).arguments
KotlinTypeFactory.flexibleType(builtIns.intType, builtIns.stringType).arguments
} catch (e: AssertionError) {
assertEquals("Lower bound Int of a flexible type must be a subtype of the upper bound String", e.message)
return
@@ -22,10 +22,10 @@ import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor
import org.jetbrains.kotlin.load.java.components.TypeUsage
import org.jetbrains.kotlin.load.java.lazy.LazyJavaAnnotations
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.Variance
class LazyJavaTypeParameterDescriptor(
@@ -47,7 +47,7 @@ class LazyJavaTypeParameterDescriptor(
override fun resolveUpperBounds(): List<KotlinType> {
val bounds = javaTypeParameter.upperBounds
if (bounds.isEmpty()) {
return listOf(LazyJavaTypeResolver.FlexibleJavaClassifierTypeFactory.create(
return listOf(KotlinTypeFactory.flexibleType(
c.module.builtIns.anyType,
c.module.builtIns.nullableAnyType
))
@@ -56,7 +56,7 @@ class LazyJavaTypeResolver(
}
is JavaClassifierType ->
if (attr.allowFlexible && attr.howThisTypeIsUsed != SUPERTYPE)
FlexibleJavaClassifierTypeFactory.create(
KotlinTypeFactory.flexibleType(
LazyJavaClassifierType(javaType, attr.toFlexible(FLEXIBLE_LOWER_BOUND)),
LazyJavaClassifierType(javaType, attr.toFlexible(FLEXIBLE_UPPER_BOUND))
)
@@ -75,7 +75,7 @@ class LazyJavaTypeResolver(
if (primitiveType != null) {
val jetType = c.module.builtIns.getPrimitiveArrayKotlinType(primitiveType)
return@run if (attr.allowFlexible)
FlexibleJavaClassifierTypeFactory.create(jetType, TypeUtils.makeNullable(jetType))
KotlinTypeFactory.flexibleType(jetType, TypeUtils.makeNullable(jetType))
else TypeUtils.makeNullableAsSpecified(jetType, !attr.isMarkedNotNull)
}
@@ -83,7 +83,7 @@ class LazyJavaTypeResolver(
TYPE_ARGUMENT.toAttributes(attr.allowFlexible, attr.isForAnnotationParameter))
if (attr.allowFlexible) {
return@run FlexibleJavaClassifierTypeFactory.create(
return@run KotlinTypeFactory.flexibleType(
c.module.builtIns.getArrayType(INVARIANT, componentType),
TypeUtils.makeNullable(c.module.builtIns.getArrayType(OUT_VARIANCE, componentType)))
}
@@ -280,38 +280,6 @@ class LazyJavaTypeResolver(
override val isMarkedNullable: Boolean get() = nullable()
}
object FlexibleJavaClassifierTypeFactory : FlexibleTypeFactory {
override val id: String get() = "kotlin.jvm.PlatformType"
override fun create(lowerBound: KotlinType, upperBound: KotlinType): KotlinType {
if (lowerBound == upperBound) return lowerBound
return Impl(lowerBound, upperBound)
}
private class Impl(lowerBound: KotlinType, upperBound: KotlinType) :
DelegatingFlexibleType(lowerBound, upperBound, FlexibleJavaClassifierTypeFactory), CustomTypeVariable {
override val delegateType: KotlinType get() = lowerBound
override fun <T : TypeCapability> getCapability(capabilityClass: Class<T>): T? {
@Suppress("UNCHECKED_CAST")
if (capabilityClass == CustomTypeVariable::class.java) return this as T
return super.getCapability(capabilityClass)
}
override val isTypeVariable: Boolean get() = lowerBound.constructor.declarationDescriptor is TypeParameterDescriptor
&& lowerBound.constructor == upperBound.constructor
override fun substitutionResult(replacement: KotlinType): KotlinType {
return if (replacement.isFlexible()) replacement
else create(replacement, TypeUtils.makeNullable(replacement))
}
}
}
}
internal fun makeStarProjection(
@@ -91,7 +91,7 @@ internal object RawSubstitution : TypeSubstitution() {
is ClassDescriptor -> {
val lower = type.lowerIfFlexible()
val upper = type.upperIfFlexible()
LazyJavaTypeResolver.FlexibleJavaClassifierTypeFactory.create(
KotlinTypeFactory.flexibleType(
eraseInflexibleBasedOnClassDescriptor(lower, declaration, lowerTypeAttr),
eraseInflexibleBasedOnClassDescriptor(upper, declaration, upperTypeAttr)
)
@@ -100,7 +100,7 @@ internal object RawSubstitution : TypeSubstitution() {
}
}
private fun eraseInflexibleBasedOnClassDescriptor(type: KotlinType, declaration: ClassDescriptor, attr: JavaTypeAttributes): KotlinType {
private fun eraseInflexibleBasedOnClassDescriptor(type: KotlinType, declaration: ClassDescriptor, attr: JavaTypeAttributes): SimpleType {
if (KotlinBuiltIns.isArray(type)) {
val componentTypeProjection = type.arguments[0]
val arguments = listOf(
@@ -70,7 +70,7 @@ private fun KotlinType.enhancePossiblyFlexible(qualifiers: (Int) -> JavaTypeQual
val wereChanges = lowerResult.wereChanges || upperResult.wereChanges
Result(
if (wereChanges)
factory.create(lowerResult.type, upperResult.type)
KotlinTypeFactory.flexibleType(lowerResult.type.asSimpleType(), upperResult.type.asSimpleType())
else
this@enhancePossiblyFlexible,
lowerResult.subtreeSize,
@@ -228,7 +228,7 @@ internal object NotNullTypeParameterTypeCapability : CustomTypeVariable {
if (replacement.isFlexible()) {
with(replacement.flexibility()) {
return factory.create(lowerBound.prepareReplacement(), upperBound.prepareReplacement())
return KotlinTypeFactory.flexibleType(lowerBound.prepareReplacement().asSimpleType(), upperBound.prepareReplacement().asSimpleType())
}
}
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.lazy.LazyJavaPackageFragmentProvider
import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver.FlexibleJavaClassifierTypeFactory
import org.jetbrains.kotlin.serialization.deserialization.*
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.FlexibleJavaClassifierTypeFactory
// This class is needed only for easier injection: exact types of needed components are specified in the constructor here.
// Otherwise injector generator is not smart enough to deduce, for example, which package fragment provider DeserializationComponents needs
@@ -45,9 +45,9 @@ internal class UnsafeVarianceTypeSubstitution(kotlinBuiltIns: KotlinBuiltIns) :
if (unsafeVariancePaths.isEmpty()) return this
if (isFlexible()) {
return flexibility().factory.create(
lowerIfFlexible().annotatePartsWithUnsafeVariance(subPathsWithIndex(unsafeVariancePaths, 0)),
upperIfFlexible().annotatePartsWithUnsafeVariance(subPathsWithIndex(unsafeVariancePaths, 1))
return KotlinTypeFactory.flexibleType(
lowerIfFlexible().annotatePartsWithUnsafeVariance(subPathsWithIndex(unsafeVariancePaths, 0)).asSimpleType(),
upperIfFlexible().annotatePartsWithUnsafeVariance(subPathsWithIndex(unsafeVariancePaths, 1)).asSimpleType()
)
}
@@ -70,9 +70,9 @@ public abstract class KotlinBuiltIns {
private final Set<PackageFragmentDescriptor> builtInsPackageFragments;
private final Map<PrimitiveType, KotlinType> primitiveTypeToArrayKotlinType;
private final Map<KotlinType, KotlinType> primitiveKotlinTypeToKotlinArrayType;
private final Map<KotlinType, KotlinType> kotlinArrayTypeToPrimitiveKotlinType;
private final Map<PrimitiveType, SimpleType> primitiveTypeToArrayKotlinType;
private final Map<SimpleType, SimpleType> primitiveKotlinTypeToKotlinArrayType;
private final Map<SimpleType, SimpleType> kotlinArrayTypeToPrimitiveKotlinType;
private final StorageManager storageManager;
public static final FqNames FQ_NAMES = new FqNames();
@@ -108,9 +108,9 @@ public abstract class KotlinBuiltIns {
builtInsPackageFragments = new LinkedHashSet<PackageFragmentDescriptor>(packageNameToPackageFragment.values());
primitiveTypeToArrayKotlinType = new EnumMap<PrimitiveType, KotlinType>(PrimitiveType.class);
primitiveKotlinTypeToKotlinArrayType = new HashMap<KotlinType, KotlinType>();
kotlinArrayTypeToPrimitiveKotlinType = new HashMap<KotlinType, KotlinType>();
primitiveTypeToArrayKotlinType = new EnumMap<PrimitiveType, SimpleType>(PrimitiveType.class);
primitiveKotlinTypeToKotlinArrayType = new HashMap<SimpleType, SimpleType>();
kotlinArrayTypeToPrimitiveKotlinType = new HashMap<SimpleType, SimpleType>();
for (PrimitiveType primitive : PrimitiveType.values()) {
makePrimitive(primitive);
}
@@ -127,8 +127,8 @@ public abstract class KotlinBuiltIns {
}
private void makePrimitive(@NotNull PrimitiveType primitiveType) {
KotlinType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString());
KotlinType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString());
SimpleType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString());
SimpleType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString());
primitiveTypeToArrayKotlinType.put(primitiveType, arrayType);
primitiveKotlinTypeToKotlinArrayType.put(type, arrayType);
@@ -601,7 +601,7 @@ public abstract class KotlinBuiltIns {
}
@NotNull
private KotlinType getBuiltInTypeByClassName(@NotNull String classSimpleName) {
private SimpleType getBuiltInTypeByClassName(@NotNull String classSimpleName) {
return getBuiltInClassByName(classSimpleName).getDefaultType();
}
@@ -626,7 +626,7 @@ public abstract class KotlinBuiltIns {
}
@NotNull
public KotlinType getDefaultBound() {
public SimpleType getDefaultBound() {
return getNullableAnyType();
}
@@ -636,42 +636,42 @@ public abstract class KotlinBuiltIns {
}
@NotNull
public KotlinType getByteType() {
public SimpleType getByteType() {
return getPrimitiveKotlinType(BYTE);
}
@NotNull
public KotlinType getShortType() {
public SimpleType getShortType() {
return getPrimitiveKotlinType(SHORT);
}
@NotNull
public KotlinType getIntType() {
public SimpleType getIntType() {
return getPrimitiveKotlinType(INT);
}
@NotNull
public KotlinType getLongType() {
public SimpleType getLongType() {
return getPrimitiveKotlinType(LONG);
}
@NotNull
public KotlinType getFloatType() {
public SimpleType getFloatType() {
return getPrimitiveKotlinType(FLOAT);
}
@NotNull
public KotlinType getDoubleType() {
public SimpleType getDoubleType() {
return getPrimitiveKotlinType(DOUBLE);
}
@NotNull
public KotlinType getCharType() {
public SimpleType getCharType() {
return getPrimitiveKotlinType(CHAR);
}
@NotNull
public KotlinType getBooleanType() {
public SimpleType getBooleanType() {
return getPrimitiveKotlinType(BOOLEAN);
}
@@ -681,7 +681,7 @@ public abstract class KotlinBuiltIns {
}
@NotNull
public KotlinType getStringType() {
public SimpleType getStringType() {
return getString().getDefaultType();
}
@@ -701,7 +701,7 @@ public abstract class KotlinBuiltIns {
}
@NotNull
public KotlinType getPrimitiveArrayKotlinType(@NotNull PrimitiveType primitiveType) {
public SimpleType getPrimitiveArrayKotlinType(@NotNull PrimitiveType primitiveType) {
return primitiveTypeToArrayKotlinType.get(primitiveType);
}
@@ -709,8 +709,8 @@ public abstract class KotlinBuiltIns {
* @return {@code null} if not primitive
*/
@Nullable
public KotlinType getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(@NotNull KotlinType kotlinType) {
return primitiveKotlinTypeToKotlinArrayType.get(kotlinType);
public SimpleType getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(@NotNull KotlinType kotlinType) {
return primitiveKotlinTypeToKotlinArrayType.get(kotlinType); // todo unwrap
}
public static boolean isPrimitiveArray(@NotNull FqNameUnsafe arrayFqName) {
@@ -97,10 +97,9 @@ fun approximateCapturedTypes(type: KotlinType): ApproximationBounds<KotlinType>
val boundsForFlexibleLower = approximateCapturedTypes(type.lowerIfFlexible())
val boundsForFlexibleUpper = approximateCapturedTypes(type.upperIfFlexible())
val factory = type.flexibility().factory
return ApproximationBounds(
factory.create(boundsForFlexibleLower.lower.lowerIfFlexible(), boundsForFlexibleUpper.lower.upperIfFlexible()),
factory.create(boundsForFlexibleLower.upper.lowerIfFlexible(), boundsForFlexibleUpper.upper.upperIfFlexible()))
KotlinTypeFactory.flexibleType(boundsForFlexibleLower.lower.lowerIfFlexible(), boundsForFlexibleUpper.lower.upperIfFlexible()),
KotlinTypeFactory.flexibleType(boundsForFlexibleLower.upper.lowerIfFlexible(), boundsForFlexibleUpper.upper.upperIfFlexible()))
}
val typeConstructor = type.constructor
@@ -47,4 +47,10 @@ object KotlinTypeFactory {
nullable: Boolean = baseType.isMarkedNullable,
memberScope: MemberScope = baseType.memberScope
): SimpleType = simpleType(annotations, constructor, arguments, nullable, memberScope)
@JvmStatic
fun flexibleType(lowerBound: SimpleType, upperBound: SimpleType): KotlinType {
if (lowerBound == upperBound) return lowerBound
return FlexibleTypeImpl(lowerBound, upperBound)
}
}
@@ -133,6 +133,10 @@ public class TypeSubstitutor {
// The type is within the substitution range, i.e. T or T?
KotlinType type = originalProjection.getType();
if (DynamicTypesKt.isDynamic(type)) {
return originalProjection; // todo investigate
}
TypeProjection replacement = substitution.get(type);
Variance originalProjectionKind = originalProjection.getProjectionKind();
if (replacement == null && FlexibleTypesKt.isFlexible(type) && !TypeCapabilitiesKt.isCustomTypeVariable(type)) {
@@ -147,8 +151,8 @@ public class TypeSubstitutor {
originalProjectionKind == Variance.INVARIANT || originalProjectionKind == substitutedProjectionKind :
"Unexpected substituted projection kind: " + substitutedProjectionKind + "; original: " + originalProjectionKind;
KotlinType substitutedFlexibleType = flexibility.getFactory().create(
substitutedLower.getType(), substitutedUpper.getType());
KotlinType substitutedFlexibleType = KotlinTypeFactory.flexibleType(
KotlinTypeKt.asSimpleType(substitutedLower.getType()), KotlinTypeKt.asSimpleType(substitutedUpper.getType()));
return new TypeProjectionImpl(substitutedProjectionKind, substitutedFlexibleType);
}
@@ -157,6 +157,11 @@ public class TypeUtils {
return nullable ? new NullableType(type) : new NotNullType(type);
}
@NotNull
public static SimpleType makeNullableIfNeeded(@NotNull SimpleType type, boolean nullable) {
return KotlinTypeKt.asSimpleType(makeNullableIfNeeded((KotlinType) type, nullable));
}
@NotNull
public static KotlinType makeNullableIfNeeded(@NotNull KotlinType type, boolean nullable) {
if (nullable) {
@@ -32,31 +32,30 @@ class DynamicTypesAllowed: DynamicTypesSettings() {
fun KotlinType.isDynamic(): Boolean = this.getCapability(Flexibility::class.java)?.factory == DynamicTypeFactory
fun createDynamicType(builtIns: KotlinBuiltIns) = DynamicTypeFactory.create(builtIns.nothingType, builtIns.nullableAnyType)
fun createDynamicType(builtIns: KotlinBuiltIns) = DynamicType(builtIns)
class DynamicType(builtIns: KotlinBuiltIns) : DelegatingFlexibleType(builtIns.nothingType, builtIns.nullableAnyType, DynamicTypeFactory) {
override val delegateType: KotlinType get() = upperBound
override fun makeNullableAsSpecified(nullable: Boolean): KotlinType {
// Nullability has no effect on dynamics
return createDynamicType(delegateType.builtIns)
}
override val isMarkedNullable: Boolean get() = false
}
object DynamicTypeFactory : FlexibleTypeFactory {
override val id: String get() = "kotlin.DynamicType"
override fun create(lowerBound: KotlinType, upperBound: KotlinType): KotlinType {
override fun create(lowerBound: SimpleType, upperBound: SimpleType): KotlinType {
if (KotlinTypeChecker.FLEXIBLE_UNEQUAL_TO_INFLEXIBLE.equalTypes(lowerBound, lowerBound.builtIns.nothingType) &&
KotlinTypeChecker.FLEXIBLE_UNEQUAL_TO_INFLEXIBLE.equalTypes(upperBound, upperBound.builtIns.nullableAnyType)) {
return Impl(lowerBound, upperBound)
return createDynamicType(lowerBound.builtIns)
}
else {
throw IllegalStateException("Illegal type range for dynamic type: $lowerBound..$upperBound")
}
}
private class Impl(lowerBound: KotlinType, upperBound: KotlinType) :
DelegatingFlexibleType(lowerBound, upperBound, DynamicTypeFactory) {
override val delegateType: KotlinType get() = upperBound
override fun makeNullableAsSpecified(nullable: Boolean): KotlinType {
// Nullability has no effect on dynamics
return createDynamicType(delegateType.builtIns)
}
override val isMarkedNullable: Boolean get() = false
}
override val id: String get() = "kotlin.DynamicType"
}
@@ -16,26 +16,27 @@
package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
interface FlexibleTypeFactory {
val id: String
fun create(lowerBound: KotlinType, upperBound: KotlinType): KotlinType
fun create(lowerBound: SimpleType, upperBound: SimpleType): KotlinType
object ThrowException : FlexibleTypeFactory {
private fun error(): Nothing = throw IllegalArgumentException("This factory should not be used.")
override val id: String
get() = error()
override fun create(lowerBound: KotlinType, upperBound: KotlinType): KotlinType = error()
override fun create(lowerBound: SimpleType, upperBound: SimpleType): KotlinType = error()
}
}
interface Flexibility : TypeCapability, SubtypingRepresentatives {
// lowerBound is a subtype of upperBound
val lowerBound: KotlinType
val upperBound: KotlinType
val lowerBound: SimpleType
val upperBound: SimpleType
val factory: FlexibleTypeFactory
@@ -93,12 +94,12 @@ fun Collection<TypeProjection>.singleBestRepresentative(): TypeProjection? {
return TypeProjectionImpl(projectionKinds.single(), bestType)
}
fun KotlinType.lowerIfFlexible(): KotlinType = if (this.isFlexible()) this.flexibility().lowerBound else this
fun KotlinType.upperIfFlexible(): KotlinType = if (this.isFlexible()) this.flexibility().upperBound else this
fun KotlinType.lowerIfFlexible(): SimpleType = (if (this.isFlexible()) this.flexibility().lowerBound else this).asSimpleType()
fun KotlinType.upperIfFlexible(): SimpleType = (if (this.isFlexible()) this.flexibility().upperBound else this).asSimpleType()
abstract class DelegatingFlexibleType protected constructor(
override val lowerBound: KotlinType,
override val upperBound: KotlinType,
override val lowerBound: SimpleType,
override val upperBound: SimpleType,
override val factory: FlexibleTypeFactory
) : DelegatingType(), Flexibility {
companion object {
@@ -137,8 +138,7 @@ abstract class DelegatingFlexibleType protected constructor(
}
override fun makeNullableAsSpecified(nullable: Boolean): KotlinType {
return factory.create(TypeUtils.makeNullableAsSpecified(lowerBound, nullable),
TypeUtils.makeNullableAsSpecified(upperBound, nullable))
return KotlinTypeFactory.flexibleType(TypeUtils.makeNullableAsSpecified(lowerBound, nullable), TypeUtils.makeNullableAsSpecified(upperBound, nullable))
}
final override fun getDelegate(): KotlinType {
@@ -148,3 +148,37 @@ abstract class DelegatingFlexibleType protected constructor(
override fun toString() = "('$lowerBound'..'$upperBound')"
}
class FlexibleTypeImpl(lowerBound: SimpleType, upperBound: SimpleType) :
DelegatingFlexibleType(lowerBound, upperBound, FlexibleJavaClassifierTypeFactory), CustomTypeVariable {
override val delegateType: KotlinType get() = lowerBound
override fun <T : TypeCapability> getCapability(capabilityClass: Class<T>): T? {
@Suppress("UNCHECKED_CAST")
if (capabilityClass == CustomTypeVariable::class.java) return this as T
return super.getCapability(capabilityClass)
}
override val isTypeVariable: Boolean get() = lowerBound.constructor.declarationDescriptor is TypeParameterDescriptor
&& lowerBound.constructor == upperBound.constructor
override fun substitutionResult(replacement: KotlinType): KotlinType {
if (replacement.isFlexible()) {
return replacement
}
else {
val simpleType = replacement.asSimpleType()
return KotlinTypeFactory.flexibleType(simpleType, TypeUtils.makeNullable(simpleType))
}
}
}
// TODO: move Factory to descriptor.loader.java
object FlexibleJavaClassifierTypeFactory : FlexibleTypeFactory {
override fun create(lowerBound: SimpleType, upperBound: SimpleType): KotlinType
= KotlinTypeFactory.flexibleType(lowerBound, upperBound)
override val id: String get() = "kotlin.jvm.PlatformType"
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 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.
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value
import org.jetbrains.kotlin.serialization.ProtoBuf.Annotation.Argument.Value.Type
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
@@ -143,7 +144,7 @@ class AnnotationDeserializer(private val module: ModuleDescriptor, private val n
return factory.createErrorValue("Unresolved enum entry: $enumClassId.$enumEntryName")
}
private fun resolveArrayElementType(value: Value, nameResolver: NameResolver): KotlinType =
private fun resolveArrayElementType(value: Value, nameResolver: NameResolver): SimpleType =
with(builtIns) {
when (value.type) {
Type.BYTE -> getByteType()
@@ -34,6 +34,10 @@ import org.jetbrains.kotlin.types.typeUtil.*
fun KotlinType.approximateFlexibleTypes(preferNotNull: Boolean = false): KotlinType {
if (isDynamic()) return this
return approximateNonDynamicFlexibleTypes(preferNotNull)
}
private fun KotlinType.approximateNonDynamicFlexibleTypes(preferNotNull: Boolean = false): SimpleType {
if (isFlexible()) {
val flexible = flexibility()
val lowerClass = flexible.lowerBound.constructor.declarationDescriptor as? ClassDescriptor?
@@ -48,12 +52,12 @@ fun KotlinType.approximateFlexibleTypes(preferNotNull: Boolean = false): KotlinT
else
if (preferNotNull) flexible.lowerBound else flexible.upperBound
approximation = approximation.approximateFlexibleTypes()
approximation = approximation.approximateNonDynamicFlexibleTypes()
approximation = if (isAnnotatedNotNull()) approximation.makeNotNullable() else approximation
approximation = if (isAnnotatedNotNull()) TypeUtils.makeNotNullable(approximation) else approximation
if (approximation.isMarkedNullable && !flexible.lowerBound.isMarkedNullable && TypeUtils.isTypeParameter(approximation) && TypeUtils.hasNullableSuperType(approximation)) {
approximation = approximation.makeNotNullable()
approximation = TypeUtils.makeNotNullable(approximation)
}
return approximation
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.DeserializerForDecompile
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolveEverythingToKotlinAnyLocalClassifierResolver
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver.FlexibleJavaClassifierTypeFactory
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.kotlin.*
import org.jetbrains.kotlin.name.ClassId
@@ -40,6 +39,7 @@ import org.jetbrains.kotlin.serialization.deserialization.DeserializationCompone
import org.jetbrains.kotlin.serialization.deserialization.NotFoundClasses
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
import org.jetbrains.kotlin.types.FlexibleJavaClassifierTypeFactory
fun DeserializerForClassfileDecompiler(classFile: VirtualFile): DeserializerForClassfileDecompiler {
val kotlinClassHeaderInfo = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(classFile)
@@ -45,7 +45,7 @@ import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
import org.jetbrains.kotlin.types.CommonSupertypes.topologicallySortSuperclassesAndRecordAllInstances
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.identity
@@ -341,7 +341,7 @@ class ClassTranslator private constructor(
}
val sortedAllSuperTypes = topologicallySortSuperclassesAndRecordAllInstances(
descriptor.defaultType,
mutableMapOf<TypeConstructor, Set<KotlinType>>(),
mutableMapOf<TypeConstructor, Set<SimpleType>>(),
mutableSetOf<TypeConstructor>()
)
val supertypesRefs = mutableListOf<JsExpression>()
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.StarProjectionImpl
import org.jetbrains.kotlin.types.asSimpleType
import org.jetbrains.kotlin.types.typeUtil.makeNullable
private class XmlSourceElement(override val psi: PsiElement) : PsiSourceElement
@@ -109,7 +110,7 @@ private fun genProperty(
override val resourceId = id
}
val flexibleType = LazyJavaTypeResolver.FlexibleJavaClassifierTypeFactory.create(type, type.makeNullable())
val flexibleType = KotlinTypeFactory.flexibleType(type.asSimpleType(), type.makeNullable().asSimpleType())
property.setType(
flexibleType,
emptyList<TypeParameterDescriptor>(),