diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassDescriptor.java index ae5cc4e1e2b..cffa635f470 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -45,6 +45,7 @@ import org.jetbrains.jet.lang.resolve.lazy.data.SyntheticClassObjectInfo; import org.jetbrains.jet.lang.resolve.lazy.declarations.ClassMemberDeclarationProvider; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.*; +import org.jetbrains.jet.lang.types.AbstractClassTypeConstructor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeConstructor; import org.jetbrains.jet.lang.types.TypeUtils; @@ -468,7 +469,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes } } - private class LazyClassTypeConstructor implements LazyEntity, TypeConstructor { + private class LazyClassTypeConstructor extends AbstractClassTypeConstructor implements LazyEntity { private final NotNullLazyValue supertypes = resolveSession.getStorageManager().createLazyValueWithPostCompute( new Function0() { @Override diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArguments.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArguments.kt new file mode 100644 index 00000000000..870ae8c7e67 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArguments.kt @@ -0,0 +1,29 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// MODULE: m1 +// FILE: a.kt + +package p + +public class A +public class M1 { + public val a: A = A() +} + +// MODULE: m2 +// FILE: b.kt + +package p + +public class A + +public fun foo(a: A) { +} + +// MODULE: m3(m1, m2) +// FILE: b.kt + +import p.* + +fun test() { + foo(M1().a) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArgumentsReversed.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArgumentsReversed.kt new file mode 100644 index 00000000000..11acbc81740 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArgumentsReversed.kt @@ -0,0 +1,29 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// MODULE: m1 +// FILE: a.kt + +package p + +public class A +public class M1 { + public val a: A = A() +} + +// MODULE: m2 +// FILE: b.kt + +package p + +public class A + +public fun foo(a: A) { +} + +// MODULE: m3(m1, m2) +// FILE: b.kt + +import p.* + +fun test() { + foo(M1().a) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateClass.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateClass.kt new file mode 100644 index 00000000000..28bed038c27 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateClass.kt @@ -0,0 +1,32 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// MODULE: m1 +// FILE: a.kt + +package p + +public class A +public class B { + public val a: A = A() +} + +// MODULE: m2 +// FILE: b.kt + +package p + +public class A { + val x = 1 +} + +public fun foo(a: A) { + a.x + 1 +} + +// MODULE: m3(m1, m2) +// FILE: b.kt + +import p.* + +fun test() { + foo(B().a) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.kt new file mode 100644 index 00000000000..6b34d04d70b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.kt @@ -0,0 +1,68 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// MODULE: m1 +// FILE: a.kt + +package p + +public class A { + public class B + public object C + class object { + public class D { + public object E + } + public class G + } + + public inner class F +} + +public class M1 { + public val a: A = A() + public val b: A.B = A.B() + public val c: A.C = A.C + public val d: A.D = A.D() + public val e: A.D.E = A.D.E + public val f: A.F = A().F() + public val g: A.G = A.G() +} + +// MODULE: m2 +// FILE: b.kt + +package p + +public class A { + public class B + public class C + class object { + public class D { + public class E + } + } + public class G + public inner class F +} + +public fun a(p: A) {} +public fun b(p: A.B) {} +public fun c(p: A.C) {} +public fun d(p: A.D) {} +public fun e(p: A.D.E) {} +public fun f(p: A.F) {} +public fun g(p: A.G) {} + +// MODULE: m3(m1, m2) +// FILE: b.kt + +import p.* + +fun test(m1: M1) { + a(m1.a) + b(m1.b) + c(m1.c) + d(m1.d) + e(m1.e) + f(m1.f) + g(m1.g) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateSuperClass.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateSuperClass.kt new file mode 100644 index 00000000000..1c7c0c25f5f --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateSuperClass.kt @@ -0,0 +1,30 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// MODULE: m1 +// FILE: a.kt + +package p + +public trait A +public class B : A +public class M1 { + public val b: B = B() +} + +// MODULE: m2 +// FILE: b.kt + +package p + +public trait A + +public fun foo(a: A) { +} + +// MODULE: m3(m1, m2) +// FILE: b.kt + +import p.* + +fun test() { + foo(M1().b) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericArgumentNumberMismatch.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericArgumentNumberMismatch.kt new file mode 100644 index 00000000000..93bf4dbcf6b --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericArgumentNumberMismatch.kt @@ -0,0 +1,30 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// MODULE: m1 +// FILE: a.kt + +package p + +public class A +public class M1 { + public val a: A = A() +} + +// MODULE: m2 +// FILE: b.kt + +package p + +public class A + +public fun foo(a: A) { +} + +// MODULE: m3(m1, m2) +// FILE: b.kt + +import p.* + +fun test() { + foo(M1().a) + foo(1) // error type on the declaration site +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericSuperClass.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericSuperClass.kt new file mode 100644 index 00000000000..f314f262fbb --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericSuperClass.kt @@ -0,0 +1,42 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// MODULE: m1 +// FILE: a.kt + +package p + +public trait A +public trait C +public trait D +public class B : A, C, D +public class M1 { + public val b: B = B() +} + +// MODULE: m2 +// FILE: b.kt + +package p + +public trait A +public trait C +public trait D + +public fun a(a: A) { +} + +public fun c(c: C) { +} + +public fun d(d: D) { +} + +// MODULE: m3(m1, m2) +// FILE: b.kt + +import p.* + +fun test() { + a(M1().b) // Type arguments do not match + c(M1().b) // Type arguments do not match + d(M1().b) // Type arguments do match +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsage.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsage.kt new file mode 100644 index 00000000000..20f29622e77 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsage.kt @@ -0,0 +1,23 @@ +// MODULE: m1 +// FILE: a.kt + +package p + +public class A +public class B { + public val a: A = A() +} + +// MODULE: m2(m1) +// FILE: b.kt + +package p + +class A { + fun foo() {} +} + +fun test() { + val a: A = B().a + a.foo() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsageNoTypeAnnotation.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsageNoTypeAnnotation.kt new file mode 100644 index 00000000000..77d666b823c --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsageNoTypeAnnotation.kt @@ -0,0 +1,23 @@ +// MODULE: m1 +// FILE: a.kt + +package p + +public class A +public class B { + public val a: A = A() +} + +// MODULE: m2(m1) +// FILE: b.kt + +package p + +class A { + fun foo() {} +} + +fun test() { + val a = B().a + a.foo() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/members.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/members.kt new file mode 100644 index 00000000000..88a98399c37 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/members.kt @@ -0,0 +1,38 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// MODULE: m1 +// FILE: a.kt + +package p + +public class A { + public fun m1() {} +} +public class M1 { + public val a: A = A() +} + +// MODULE: m2 +// FILE: b.kt + +package p + +public class A { + public fun m2() {} +} + +public class M2 { + public val a: A = A() +} + +// MODULE: m3(m1, m2) +// FILE: b.kt + +import p.* + +fun test(a: A) { + a.m1() + + M1().a.m1() + + M2().a.m2() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameClassNameDifferentPackages.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameClassNameDifferentPackages.kt new file mode 100644 index 00000000000..1f2f734b1b4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameClassNameDifferentPackages.kt @@ -0,0 +1,21 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// MODULE: m1 +// FILE: a.kt + +package p + +public class A +public class B { + public val a: A = A() +} + +// MODULE: m2(m1) +// FILE: b.kt + +import p.* + +class A + +fun test() { + val a: A = B().a +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameGenericArguments.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameGenericArguments.kt new file mode 100644 index 00000000000..bc4cf46afd4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameGenericArguments.kt @@ -0,0 +1,29 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// MODULE: m1 +// FILE: a.kt + +package p + +public class A +public class M1 { + public val a: A = A() +} + +// MODULE: m2 +// FILE: b.kt + +package p + +public class A + +public fun foo(a: A) { +} + +// MODULE: m3(m1, m2) +// FILE: b.kt + +import p.* + +fun test() { + foo(M1().a) +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index d412a22b57f..03e627b09ee 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -4687,6 +4687,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { } @TestMetadata("compiler/testData/diagnostics/tests/multimodule") + @InnerTestClasses({Multimodule.DuplicateClass.class}) public static class Multimodule extends AbstractJetDiagnosticsTest { public void testAllFilesPresentInMultimodule() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/diagnostics/tests/multimodule"), Pattern.compile("^(.+)\\.kt$"), true); @@ -4702,6 +4703,80 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/multimodule/packagePrivate.kt"); } + @TestMetadata("compiler/testData/diagnostics/tests/multimodule/duplicateClass") + public static class DuplicateClass extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInDuplicateClass() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/diagnostics/tests/multimodule/duplicateClass"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("differentGenericArguments.kt") + public void testDifferentGenericArguments() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArguments.kt"); + } + + @TestMetadata("differentGenericArgumentsReversed.kt") + public void testDifferentGenericArgumentsReversed() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArgumentsReversed.kt"); + } + + @TestMetadata("duplicateClass.kt") + public void testDuplicateClass() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateClass.kt"); + } + + @TestMetadata("duplicateNestedClasses.kt") + public void testDuplicateNestedClasses() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.kt"); + } + + @TestMetadata("duplicateSuperClass.kt") + public void testDuplicateSuperClass() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateSuperClass.kt"); + } + + @TestMetadata("genericArgumentNumberMismatch.kt") + public void testGenericArgumentNumberMismatch() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericArgumentNumberMismatch.kt"); + } + + @TestMetadata("genericSuperClass.kt") + public void testGenericSuperClass() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericSuperClass.kt"); + } + + @TestMetadata("inTheSameModuleWithUsage.kt") + public void testInTheSameModuleWithUsage() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsage.kt"); + } + + @TestMetadata("inTheSameModuleWithUsageNoTypeAnnotation.kt") + public void testInTheSameModuleWithUsageNoTypeAnnotation() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsageNoTypeAnnotation.kt"); + } + + @TestMetadata("members.kt") + public void testMembers() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/members.kt"); + } + + @TestMetadata("sameClassNameDifferentPackages.kt") + public void testSameClassNameDifferentPackages() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameClassNameDifferentPackages.kt"); + } + + @TestMetadata("sameGenericArguments.kt") + public void testSameGenericArguments() throws Exception { + doTest("compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameGenericArguments.kt"); + } + + } + + public static Test innerSuite() { + TestSuite suite = new TestSuite("Multimodule"); + suite.addTestSuite(Multimodule.class); + suite.addTestSuite(DuplicateClass.class); + return suite; + } } @TestMetadata("compiler/testData/diagnostics/tests/namedArguments") @@ -7094,7 +7169,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { suite.addTest(Jdk_annotations.innerSuite()); suite.addTestSuite(Labels.class); suite.addTestSuite(Library.class); - suite.addTestSuite(Multimodule.class); + suite.addTest(Multimodule.innerSuite()); suite.addTestSuite(NamedArguments.class); suite.addTestSuite(NullabilityAndAutoCasts.class); suite.addTestSuite(NullableTypes.class); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt index 98ec7170d66..434c5fee2d2 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -52,6 +52,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassStaticsPackageFragmentDescriptor import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor import org.jetbrains.jet.lang.resolve.name.SpecialNames +import org.jetbrains.jet.lang.types.AbstractClassTypeConstructor class LazyJavaClassDescriptor( private val outerC: LazyJavaResolverContextWithTypes, @@ -188,7 +189,7 @@ class LazyJavaClassDescriptor( override fun toString() = "lazy java class $fqName" - private inner class LazyJavaClassTypeConstructor : TypeConstructor { + private inner class LazyJavaClassTypeConstructor : AbstractClassTypeConstructor() { private val _parameters = c.storageManager.createLazyValue { jClass.getTypeParameters().map({ diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/ClassDescriptorImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/ClassDescriptorImpl.java index 80cbc747718..3a4ae06b174 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/ClassDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/ClassDescriptorImpl.java @@ -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.emptyList(), supertypes); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/EnumEntrySyntheticClassDescriptor.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/EnumEntrySyntheticClassDescriptor.java index 45e18ce222d..fea9979947a 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/EnumEntrySyntheticClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/EnumEntrySyntheticClassDescriptor.java @@ -78,7 +78,7 @@ public class EnumEntrySyntheticClassDescriptor extends ClassDescriptorBase { this.kind = kind; this.typeConstructor = - new TypeConstructorImpl(this, getAnnotations(), true, "enum entry", Collections.emptyList(), + TypeConstructorImpl.createForClass(this, getAnnotations(), true, "enum entry", Collections.emptyList(), Collections.singleton(supertype)); this.scope = new EnumEntryScope(storageManager); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/LazySubstitutingClassDescriptor.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/LazySubstitutingClassDescriptor.java index d22b04a647f..517ea33b9ac 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/LazySubstitutingClassDescriptor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/LazySubstitutingClassDescriptor.java @@ -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(), 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 06e2de8e105..caa0d911e75 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 @@ -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(), diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/TypeParameterDescriptorImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/TypeParameterDescriptorImpl.java index dce70e7c15d..b3fc54f1877 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/TypeParameterDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/TypeParameterDescriptorImpl.java @@ -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, diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/AbstractClassTypeConstructor.java b/core/descriptors/src/org/jetbrains/jet/lang/types/AbstractClassTypeConstructor.java new file mode 100644 index 00000000000..81a30ff3347 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/AbstractClassTypeConstructor.java @@ -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); + } +} diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/types/ErrorUtils.java index 247cad592c8..a9fa993b949 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -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.emptyList(), Collections.singleton(KotlinBuiltIns.getInstance().getAnyType())); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeConstructorImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeConstructorImpl.java index 40bb7152c57..3c9842980d6 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeConstructorImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeConstructorImpl.java @@ -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 parameters, + @NotNull Collection 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 parameters, + @NotNull Collection 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 parameters; private final Collection 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); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java index cc31f6eb55e..cbeb22a6d00 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java @@ -181,11 +181,12 @@ public class TypeCheckingProcedure { List subArguments = subtype.getArguments(); List superArguments = supertype.getArguments(); + if (subArguments.size() != superArguments.size()) return false; + List 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); diff --git a/core/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java b/core/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java index 5c0ad9bce65..5b0abdc45c7 100644 --- a/core/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java +++ b/core/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedClassDescriptor.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.OverridingUtil; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.types.AbstractClassTypeConstructor; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeConstructor; @@ -329,7 +330,7 @@ public class DeserializedClassDescriptor extends AbstractClassDescriptor impleme return "deserialized class " + getName().toString(); } - private class DeserializedClassTypeConstructor implements TypeConstructor { + private class DeserializedClassTypeConstructor extends AbstractClassTypeConstructor { private final Collection supertypes = computeSuperTypes(); private final List parameters;