diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java index e808f3fdc49..7879cf132ee 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java @@ -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 multimap = SubstitutionUtils + .buildDeepSubstitutionMultimap(classDescriptor.getDefaultType()); + for (Map.Entry> entry : multimap.asMap().entrySet()) { + Collection 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 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 conflictingTypes) { + for (Iterator 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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 582c412503a..529ffd0db97 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -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 multimap = SubstitutionUtils - .buildDeepSubstitutionMultimap(mutableClassDescriptor.getDefaultType()); - for (Map.Entry> entry : multimap.asMap().entrySet()) { - Collection 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 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 conflictingTypes) { - for (Iterator 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()) { diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/MutableClassDescriptor.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/MutableClassDescriptor.java index e71edc99b1d..68dfd20c657 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/MutableClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/MutableClassDescriptor.java @@ -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);