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