Assertions for EA-33908 - SOE: TypeSubstitutor.substituteInProjection
+ toString() in substitutions, for debugging
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
+5
@@ -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 + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user