Assertions for EA-33908 - SOE: TypeSubstitutor.substituteInProjection

+ toString() in substitutions, for debugging
This commit is contained in:
Andrey Breslav
2012-03-16 19:23:14 +04:00
parent 3d9b115f90
commit 6232e45c10
5 changed files with 82 additions and 9 deletions
@@ -44,6 +44,11 @@ public class FunctionDescriptorUtil {
public boolean isEmpty() { public boolean isEmpty() {
return false; return false;
} }
@Override
public String toString() {
return "FunctionDescriptorUtil.MAKE_TYPE_PARAMETERS_FRESH";
}
}); });
public static Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) { public static Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) {
@@ -490,6 +490,11 @@ public class ConstraintSystemWithPriorities implements ConstraintSystem {
public boolean isEmpty() { public boolean isEmpty() {
return false; return false;
} }
@Override
public String toString() {
return unknownTypes.toString();
}
}); });
private SolutionStatus status; private SolutionStatus status;
@@ -44,4 +44,13 @@ public class CompositeTypeSubstitution implements TypeSubstitutor.TypeSubstituti
} }
return true; return true;
} }
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (TypeSubstitutor.TypeSubstitution substitution : inner) {
builder.append(substitution).append(" * ");
}
return builder.toString();
}
} }
@@ -50,6 +50,11 @@ public class DescriptorSubstitutor {
public boolean isEmpty() { public boolean isEmpty() {
return originalSubstitutor.isEmpty() && mutableSubstitution.isEmpty(); return originalSubstitutor.isEmpty() && mutableSubstitution.isEmpty();
} }
@Override
public String toString() {
return "DescriptorSubstitutor.substituteTypeParameters(" + mutableSubstitution + " / " + originalSubstitutor.getSubstitution() + ")";
}
}); });
for (TypeParameterDescriptor descriptor : typeParameters) { for (TypeParameterDescriptor descriptor : typeParameters) {
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.types; package org.jetbrains.jet.lang.types;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.openapi.progress.ProcessCanceledException;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
@@ -29,6 +30,8 @@ import java.util.*;
*/ */
public class TypeSubstitutor { public class TypeSubstitutor {
private static final int MAX_RECURSION_DEPTH = 100;
public static TypeSubstitutor makeConstantSubstitutor(Collection<TypeParameterDescriptor> typeParameterDescriptors, JetType type) { public static TypeSubstitutor makeConstantSubstitutor(Collection<TypeParameterDescriptor> typeParameterDescriptors, JetType type) {
final Set<TypeConstructor> constructors = Sets.newHashSet(); final Set<TypeConstructor> constructors = Sets.newHashSet();
for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) { for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) {
@@ -49,6 +52,11 @@ public class TypeSubstitutor {
public boolean isEmpty() { public boolean isEmpty() {
return false; return false;
} }
@Override
public String toString() {
return "TypeConstructor.makeConstantSubstitutor(" + constructors + " -> " + projection + ")";
}
}); });
} }
@@ -63,6 +71,11 @@ public class TypeSubstitutor {
public boolean isEmpty() { public boolean isEmpty() {
return true; return true;
} }
@Override
public String toString() {
return "Empty TypeSubstitution";
}
}; };
@Nullable @Nullable
@@ -86,6 +99,11 @@ public class TypeSubstitutor {
public boolean isEmpty() { public boolean isEmpty() {
return substitutionContext.isEmpty(); return substitutionContext.isEmpty();
} }
@Override
public String toString() {
return substitutionContext.toString();
}
} }
public static final TypeSubstitutor EMPTY = create(TypeSubstitution.EMPTY); public static final TypeSubstitutor EMPTY = create(TypeSubstitution.EMPTY);
@@ -170,12 +188,12 @@ public class TypeSubstitutor {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) constructor.getDeclarationDescriptor(); TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) constructor.getDeclarationDescriptor();
TypeProjection result = substitutionResult(typeParameterDescriptor, howThisTypeIsUsed, Variance.INVARIANT, value); TypeProjection result = substitutionResult(typeParameterDescriptor, howThisTypeIsUsed, Variance.INVARIANT, value, 0);
return TypeUtils.makeNullableIfNeeded(result.getType(), type.isNullable()); return TypeUtils.makeNullableIfNeeded(result.getType(), type.isNullable());
} }
return specializeType(type, howThisTypeIsUsed); return specializeType(type, howThisTypeIsUsed, 0);
} }
private TypeProjection getValueWithCorrectNullability(TypeSubstitution substitution, JetType type) { private TypeProjection getValueWithCorrectNullability(TypeSubstitution substitution, JetType type) {
@@ -190,7 +208,8 @@ public class TypeSubstitutor {
return new TypeProjection(value.getProjectionKind(), TypeUtils.makeNullable(value.getType())); return new TypeProjection(value.getProjectionKind(), TypeUtils.makeNullable(value.getType()));
} }
private JetType specializeType(JetType subjectType, Variance callSiteVariance) throws SubstitutionException { private JetType specializeType(JetType subjectType, Variance callSiteVariance, int recursionDepth) throws SubstitutionException {
assertRecursionDepth(recursionDepth, subjectType, substitution);
if (ErrorUtils.isErrorType(subjectType)) return subjectType; if (ErrorUtils.isErrorType(subjectType)) return subjectType;
List<TypeProjection> newArguments = new ArrayList<TypeProjection>(); List<TypeProjection> newArguments = new ArrayList<TypeProjection>();
@@ -202,7 +221,7 @@ public class TypeSubstitutor {
substitution, substitution,
argument, argument,
parameterDescriptor, parameterDescriptor,
callSiteVariance)); callSiteVariance, recursionDepth + 1));
} }
return new JetTypeImpl( return new JetTypeImpl(
subjectType.getAnnotations(), subjectType.getAnnotations(),
@@ -217,7 +236,10 @@ public class TypeSubstitutor {
@NotNull TypeSubstitution substitutionContext, @NotNull TypeSubstitution substitutionContext,
@NotNull TypeProjection passedProjection, @NotNull TypeProjection passedProjection,
@NotNull TypeParameterDescriptor correspondingTypeParameter, @NotNull TypeParameterDescriptor correspondingTypeParameter,
@NotNull Variance contextCallSiteVariance) throws SubstitutionException { @NotNull Variance contextCallSiteVariance,
int recursionDepth) throws SubstitutionException {
assertRecursionDepth(recursionDepth, correspondingTypeParameter, passedProjection, substitution);
JetType typeToSubstituteIn = passedProjection.getType(); JetType typeToSubstituteIn = passedProjection.getType();
if (ErrorUtils.isErrorType(typeToSubstituteIn)) return passedProjection; if (ErrorUtils.isErrorType(typeToSubstituteIn)) return passedProjection;
@@ -235,20 +257,23 @@ public class TypeSubstitutor {
return TypeUtils.makeStarProjection(correspondingTypeParameter); return TypeUtils.makeStarProjection(correspondingTypeParameter);
} }
return substitutionResult(correspondingTypeParameter, effectiveContextVariance, passedProjectionKind, projectionValue); return substitutionResult(correspondingTypeParameter, effectiveContextVariance, passedProjectionKind, projectionValue, recursionDepth + 1);
} }
return new TypeProjection( return new TypeProjection(
passedProjectionKind, passedProjectionKind,
specializeType( specializeType(
typeToSubstituteIn, typeToSubstituteIn,
effectiveContextVariance)); effectiveContextVariance, recursionDepth + 1));
} }
private TypeProjection substitutionResult( private TypeProjection substitutionResult(
TypeParameterDescriptor correspondingTypeParameter, TypeParameterDescriptor correspondingTypeParameter,
Variance effectiveContextVariance, Variance effectiveContextVariance,
Variance passedProjectionKind, Variance passedProjectionKind,
TypeProjection value) throws SubstitutionException { TypeProjection value,
int recursionDepth) throws SubstitutionException {
assertRecursionDepth(recursionDepth, correspondingTypeParameter, value, substitution);
Variance projectionKindValue = value.getProjectionKind(); Variance projectionKindValue = value.getProjectionKind();
JetType typeValue = value.getType(); JetType typeValue = value.getType();
Variance effectiveProjectionKindValue = asymmetricOr(passedProjectionKind, projectionKindValue); Variance effectiveProjectionKindValue = asymmetricOr(passedProjectionKind, projectionKindValue);
@@ -285,7 +310,7 @@ public class TypeSubstitutor {
// throw new SubstitutionException(""); // TODO : error message // throw new SubstitutionException(""); // TODO : error message
// } // }
// //
return new TypeProjection(effectiveProjectionKindValue, specializeType(effectiveTypeValue, effectiveContextVariance)); return new TypeProjection(effectiveProjectionKindValue, specializeType(effectiveTypeValue, effectiveContextVariance, recursionDepth + 1));
} }
private static Variance asymmetricOr(Variance a, Variance b) { private static Variance asymmetricOr(Variance a, Variance b) {
@@ -300,4 +325,28 @@ public class TypeSubstitutor {
} }
throw new IllegalStateException(declarationSiteVariance.toString()); throw new IllegalStateException(declarationSiteVariance.toString());
} }
private static void assertRecursionDepth(int recursionDepth, TypeParameterDescriptor parameter, TypeProjection value, TypeSubstitution substitution) {
if (recursionDepth > MAX_RECURSION_DEPTH) {
throw new IllegalStateException("Recursion too deep. Most likely infinite loop while substituting " + safeToString(value) + " for " + safeToString(parameter) + "; substitution: " + safeToString(substitution));
}
}
private static void assertRecursionDepth(int recursionDepth, JetType type, TypeSubstitution substitution) {
if (recursionDepth > MAX_RECURSION_DEPTH) {
throw new IllegalStateException("Recursion too deep. Most likely infinite loop while substituting " + safeToString(type) + "; substitution: " + safeToString(substitution));
}
}
private static String safeToString(Object o) {
try {
return o.toString();
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Throwable e) {
return "[Exception while computing toString(): " + e + "]";
}
}
} }