TypeConstructor's equality for classes relies on FqNames
This is needed because different modules/libraries may define classes with the same FqNames, which may be identical or slightly different. Such classes must be considered equal, because your dependencies may rely on different packagings of the same codebase, and the classes there will be distinct though identical (think intellij-core vs idea-full).
This commit is contained in:
+1
-2
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.descriptors.impl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -49,7 +48,7 @@ public class ClassDescriptorImpl extends ClassDescriptorBase {
|
||||
super(LockBasedStorageManager.NO_LOCKS, containingDeclaration, name);
|
||||
this.modality = modality;
|
||||
|
||||
this.typeConstructor = new TypeConstructorImpl(this, Annotations.EMPTY, false, getName().asString(),
|
||||
this.typeConstructor = TypeConstructorImpl.createForClass(this, Annotations.EMPTY, false, getName().asString(),
|
||||
Collections.<TypeParameterDescriptor>emptyList(), supertypes);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ public class EnumEntrySyntheticClassDescriptor extends ClassDescriptorBase {
|
||||
this.kind = kind;
|
||||
|
||||
this.typeConstructor =
|
||||
new TypeConstructorImpl(this, getAnnotations(), true, "enum entry", Collections.<TypeParameterDescriptor>emptyList(),
|
||||
TypeConstructorImpl.createForClass(this, getAnnotations(), true, "enum entry", Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.singleton(supertype));
|
||||
|
||||
this.scope = new EnumEntryScope(storageManager);
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
|
||||
supertypes.add(substitutor.substitute(supertype, Variance.INVARIANT));
|
||||
}
|
||||
|
||||
typeConstructor = new TypeConstructorImpl(
|
||||
typeConstructor = TypeConstructorImpl.createForClass(
|
||||
this,
|
||||
originalTypeConstructor.getAnnotations(),
|
||||
originalTypeConstructor.isFinal(),
|
||||
|
||||
+1
-1
@@ -233,7 +233,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase implements Class
|
||||
|
||||
public void createTypeConstructor() {
|
||||
assert typeConstructor == null : typeConstructor;
|
||||
this.typeConstructor = new TypeConstructorImpl(
|
||||
this.typeConstructor = TypeConstructorImpl.createForClass(
|
||||
this,
|
||||
Annotations.EMPTY, // TODO : pass annotations from the class?
|
||||
!getModality().isOverridable(),
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public class TypeParameterDescriptorImpl extends AbstractTypeParameterDescriptor
|
||||
@Override
|
||||
protected TypeConstructor createTypeConstructor() {
|
||||
// TODO: Should we actually pass the annotations on to the type constructor?
|
||||
return new TypeConstructorImpl(
|
||||
return TypeConstructorImpl.createForTypeParameter(
|
||||
this,
|
||||
getAnnotations(),
|
||||
false,
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
|
||||
public abstract class AbstractClassTypeConstructor implements TypeConstructor {
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return hashCode(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
|
||||
public boolean equals(Object obj) {
|
||||
return equals(this, obj);
|
||||
}
|
||||
|
||||
public static boolean equals(@NotNull TypeConstructor me, Object other) {
|
||||
if (!(other instanceof TypeConstructor)) return false;
|
||||
ClassifierDescriptor myDescriptor = me.getDeclarationDescriptor();
|
||||
ClassifierDescriptor otherDescriptor = ((TypeConstructor) other).getDeclarationDescriptor();
|
||||
|
||||
if (myDescriptor == otherDescriptor) return true;
|
||||
|
||||
if (myDescriptor instanceof ClassDescriptor && otherDescriptor instanceof ClassDescriptor) {
|
||||
FqNameUnsafe otherFqName = DescriptorUtils.getFqName(otherDescriptor);
|
||||
FqNameUnsafe myFqName = DescriptorUtils.getFqName(myDescriptor);
|
||||
return myFqName.equals(otherFqName);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int hashCode(@NotNull TypeConstructor me) {
|
||||
if (me.getDeclarationDescriptor() instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) me.getDeclarationDescriptor();
|
||||
return DescriptorUtils.getFqName(classDescriptor).hashCode();
|
||||
}
|
||||
return System.identityHashCode(me);
|
||||
}
|
||||
}
|
||||
@@ -346,7 +346,7 @@ public class ErrorUtils {
|
||||
|
||||
@NotNull
|
||||
private static TypeConstructor createErrorTypeConstructorWithCustomDebugName(@NotNull String debugName) {
|
||||
return new TypeConstructorImpl(ERROR_CLASS, Annotations.EMPTY, false, debugName,
|
||||
return TypeConstructorImpl.createForClass(ERROR_CLASS, Annotations.EMPTY, false, debugName,
|
||||
Collections.<TypeParameterDescriptorImpl>emptyList(),
|
||||
Collections.singleton(KotlinBuiltIns.getInstance().getAnyType()));
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotatedImpl;
|
||||
@@ -28,16 +29,61 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TypeConstructorImpl extends AnnotatedImpl implements TypeConstructor {
|
||||
public abstract class TypeConstructorImpl extends AnnotatedImpl implements TypeConstructor {
|
||||
|
||||
@NotNull
|
||||
public static TypeConstructorImpl createForClass(
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull Annotations annotations,
|
||||
boolean isFinal,
|
||||
@NotNull String debugName,
|
||||
@NotNull List<? extends TypeParameterDescriptor> parameters,
|
||||
@NotNull Collection<JetType> supertypes
|
||||
) {
|
||||
return new TypeConstructorImpl(classDescriptor, annotations, isFinal, debugName, parameters, supertypes) {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return AbstractClassTypeConstructor.hashCode(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
|
||||
public boolean equals(Object obj) {
|
||||
return AbstractClassTypeConstructor.equals(this, obj);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TypeConstructorImpl createForTypeParameter(
|
||||
@NotNull TypeParameterDescriptor typeParameterDescriptor,
|
||||
@NotNull Annotations annotations,
|
||||
boolean isFinal,
|
||||
@NotNull String debugName,
|
||||
@NotNull List<? extends TypeParameterDescriptor> parameters,
|
||||
@NotNull Collection<JetType> supertypes
|
||||
) {
|
||||
return new TypeConstructorImpl(typeParameterDescriptor, annotations, isFinal, debugName, parameters, supertypes) {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return System.identityHashCode(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return this == obj;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private final List<TypeParameterDescriptor> parameters;
|
||||
private final Collection<JetType> supertypes;
|
||||
private final String debugName;
|
||||
private final boolean isFinal;
|
||||
|
||||
@Nullable
|
||||
private final ClassifierDescriptor classifierDescriptor;
|
||||
|
||||
public TypeConstructorImpl(
|
||||
private TypeConstructorImpl(
|
||||
@Nullable ClassifierDescriptor classifierDescriptor,
|
||||
@NotNull Annotations annotations,
|
||||
boolean isFinal,
|
||||
@@ -84,4 +130,10 @@ public class TypeConstructorImpl extends AnnotatedImpl implements TypeConstructo
|
||||
public ClassifierDescriptor getDeclarationDescriptor() {
|
||||
return classifierDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
}
|
||||
|
||||
+2
-1
@@ -181,11 +181,12 @@ public class TypeCheckingProcedure {
|
||||
|
||||
List<TypeProjection> subArguments = subtype.getArguments();
|
||||
List<TypeProjection> superArguments = supertype.getArguments();
|
||||
if (subArguments.size() != superArguments.size()) return false;
|
||||
|
||||
List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
|
||||
|
||||
TypeProjection subArgument = subArguments.get(i);
|
||||
JetType subIn = getInType(parameter, subArgument);
|
||||
JetType subOut = getOutType(parameter, subArgument);
|
||||
|
||||
Reference in New Issue
Block a user