checkSupertypesForConsistency() moved to declarations checker

This commit is contained in:
Andrey Breslav
2014-02-25 20:46:30 +04:00
parent 131d6ddd3d
commit 0243bacab0
3 changed files with 95 additions and 93 deletions
@@ -16,20 +16,20 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.DeferredType;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lexer.JetKeywordToken;
import org.jetbrains.jet.lexer.JetTokens;
import javax.inject.Inject;
import java.util.List;
import java.util.Map;
import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE;
@@ -60,6 +60,8 @@ public class DeclarationsChecker {
checkObject((JetObjectDeclaration) classOrObject);
}
checkSupertypesForConsistency(classDescriptor);
modifiersChecker.checkModifiersForDeclaration(classOrObject, classDescriptor);
}
@@ -93,7 +95,83 @@ public class DeclarationsChecker {
trace.report(ILLEGAL_ANNOTATION_KEYWORD.on(declaration));
}
}
private void checkSupertypesForConsistency(@NotNull ClassDescriptor classDescriptor) {
Multimap<TypeConstructor, TypeProjection> multimap = SubstitutionUtils
.buildDeepSubstitutionMultimap(classDescriptor.getDefaultType());
for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) {
Collection<TypeProjection> projections = entry.getValue();
if (projections.size() > 1) {
TypeConstructor typeConstructor = entry.getKey();
DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor;
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
// Immediate arguments of supertypes cannot be projected
Set<JetType> conflictingTypes = Sets.newLinkedHashSet();
for (TypeProjection projection : projections) {
conflictingTypes.add(projection.getType());
}
switch (typeParameterDescriptor.getVariance()) {
case INVARIANT:
// Leave conflicting types as is
break;
case IN_VARIANCE:
// Filter out those who have supertypes in this set (common supertype)
Filter.REMOVE_IF_SUPERTYPE_IN_THE_SET.proceed(conflictingTypes);
break;
case OUT_VARIANCE:
// Filter out those who have subtypes in this set (common subtype)
Filter.REMOVE_IF_SUBTYPE_IN_THE_SET.proceed(conflictingTypes);
break;
}
if (conflictingTypes.size() > 1) {
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
assert containingDeclaration instanceof ClassDescriptor : containingDeclaration;
JetClassOrObject psiElement = (JetClassOrObject) BindingContextUtils
.classDescriptorToDeclaration(trace.getBindingContext(), classDescriptor);
JetDelegationSpecifierList delegationSpecifierList = psiElement.getDelegationSpecifierList();
assert delegationSpecifierList != null;
// trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + " has inconsistent values: " + conflictingTypes);
trace.report(INCONSISTENT_TYPE_PARAMETER_VALUES
.on(delegationSpecifierList, typeParameterDescriptor, (ClassDescriptor) containingDeclaration,
conflictingTypes));
}
}
}
}
private enum Filter {
REMOVE_IF_SUBTYPE_IN_THE_SET {
@Override
public boolean removeNeeded(JetType subject, JetType other) {
return JetTypeChecker.INSTANCE.isSubtypeOf(other, subject);
}
},
REMOVE_IF_SUPERTYPE_IN_THE_SET {
@Override
public boolean removeNeeded(JetType subject, JetType other) {
return JetTypeChecker.INSTANCE.isSubtypeOf(subject, other);
}
};
private void proceed(Set<JetType> conflictingTypes) {
for (Iterator<JetType> iterator = conflictingTypes.iterator(); iterator.hasNext(); ) {
JetType type = iterator.next();
for (JetType otherType : conflictingTypes) {
boolean subtypeOf = removeNeeded(type, otherType);
if (type != otherType && subtypeOf) {
iterator.remove();
break;
}
}
}
}
public abstract boolean removeNeeded(JetType subject, JetType other);
}
private void checkObject(JetObjectDeclaration declaration) {
reportErrorIfHasIllegalModifier(declaration);
}
@@ -17,7 +17,6 @@
package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
@@ -29,9 +28,11 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
import org.jetbrains.jet.lang.resolve.scopes.*;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.utils.DFS;
@@ -137,9 +138,6 @@ public class TypeHierarchyResolver {
// At this point, there are no loops in the type hierarchy
checkSupertypesForConsistency(c);
// computeSuperclasses();
checkTypesInClassHeaders(c); // Check bounds in the types used in generic bounds and supertype lists
}
@@ -333,84 +331,6 @@ public class TypeHierarchyResolver {
}
}
private void checkSupertypesForConsistency(@NotNull TopDownAnalysisContext c) {
for (MutableClassDescriptorLite mutableClassDescriptor : c.getClassesTopologicalOrder()) {
Multimap<TypeConstructor, TypeProjection> multimap = SubstitutionUtils
.buildDeepSubstitutionMultimap(mutableClassDescriptor.getDefaultType());
for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) {
Collection<TypeProjection> projections = entry.getValue();
if (projections.size() > 1) {
TypeConstructor typeConstructor = entry.getKey();
DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor;
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
// Immediate arguments of supertypes cannot be projected
Set<JetType> conflictingTypes = Sets.newLinkedHashSet();
for (TypeProjection projection : projections) {
conflictingTypes.add(projection.getType());
}
switch (typeParameterDescriptor.getVariance()) {
case INVARIANT:
// Leave conflicting types as is
break;
case IN_VARIANCE:
// Filter out those who have supertypes in this set (common supertype)
Filter.REMOVE_IF_SUPERTYPE_IN_THE_SET.proceed(conflictingTypes);
break;
case OUT_VARIANCE:
// Filter out those who have subtypes in this set (common subtype)
Filter.REMOVE_IF_SUBTYPE_IN_THE_SET.proceed(conflictingTypes);
break;
}
if (conflictingTypes.size() > 1) {
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
assert containingDeclaration instanceof ClassDescriptor : containingDeclaration;
JetClassOrObject psiElement = (JetClassOrObject) BindingContextUtils
.classDescriptorToDeclaration(trace.getBindingContext(), mutableClassDescriptor);
JetDelegationSpecifierList delegationSpecifierList = psiElement.getDelegationSpecifierList();
assert delegationSpecifierList != null;
// trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + " has inconsistent values: " + conflictingTypes);
trace.report(INCONSISTENT_TYPE_PARAMETER_VALUES
.on(delegationSpecifierList, typeParameterDescriptor, (ClassDescriptor) containingDeclaration,
conflictingTypes));
}
}
}
}
}
private enum Filter {
REMOVE_IF_SUBTYPE_IN_THE_SET {
@Override
public boolean removeNeeded(JetType subject, JetType other) {
return JetTypeChecker.INSTANCE.isSubtypeOf(other, subject);
}
},
REMOVE_IF_SUPERTYPE_IN_THE_SET {
@Override
public boolean removeNeeded(JetType subject, JetType other) {
return JetTypeChecker.INSTANCE.isSubtypeOf(subject, other);
}
};
private void proceed(Set<JetType> conflictingTypes) {
for (Iterator<JetType> iterator = conflictingTypes.iterator(); iterator.hasNext(); ) {
JetType type = iterator.next();
for (JetType otherType : conflictingTypes) {
boolean subtypeOf = removeNeeded(type, otherType);
if (type != otherType && subtypeOf) {
iterator.remove();
break;
}
}
}
}
public abstract boolean removeNeeded(JetType subject, JetType other);
}
private void checkTypesInClassHeaders(@NotNull TopDownAnalysisContext c) {
for (JetClassOrObject classOrObject : c.getClasses().keySet()) {
for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) {
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.*;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
import java.util.List;
@@ -69,9 +70,12 @@ public class MutableClassDescriptor extends MutableClassDescriptorLite implement
constructors.add(constructorDescriptor);
if (defaultType.isComputed()) {
((ConstructorDescriptorImpl) constructorDescriptor).setReturnType(getDefaultType());
}
((ConstructorDescriptorImpl) constructorDescriptor).setReturnType(new DelegatingType() {
@Override
protected JetType getDelegate() {
return getDefaultType();
}
});
if (constructorDescriptor.isPrimary()) {
setUpScopeForInitializers(constructorDescriptor);