From a66f44e4f5f9920787b71703c854c2ed995ffeff Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 21 May 2014 18:24:03 +0400 Subject: [PATCH] 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). --- .../lazy/descriptors/LazyClassDescriptor.java | 3 +- .../differentGenericArguments.kt | 29 +++++++ .../differentGenericArgumentsReversed.kt | 29 +++++++ .../duplicateClass/duplicateClass.kt | 32 ++++++++ .../duplicateClass/duplicateNestedClasses.kt | 68 ++++++++++++++++ .../duplicateClass/duplicateSuperClass.kt | 30 ++++++++ .../genericArgumentNumberMismatch.kt | 30 ++++++++ .../duplicateClass/genericSuperClass.kt | 42 ++++++++++ .../inTheSameModuleWithUsage.kt | 23 ++++++ ...nTheSameModuleWithUsageNoTypeAnnotation.kt | 23 ++++++ .../multimodule/duplicateClass/members.kt | 38 +++++++++ .../sameClassNameDifferentPackages.kt | 21 +++++ .../duplicateClass/sameGenericArguments.kt | 29 +++++++ .../checkers/JetDiagnosticsTestGenerated.java | 77 ++++++++++++++++++- .../descriptors/LazyJavaClassDescriptor.kt | 3 +- .../descriptors/impl/ClassDescriptorImpl.java | 3 +- .../EnumEntrySyntheticClassDescriptor.java | 2 +- .../impl/LazySubstitutingClassDescriptor.java | 2 +- .../impl/MutableClassDescriptor.java | 2 +- .../impl/TypeParameterDescriptorImpl.java | 2 +- .../types/AbstractClassTypeConstructor.java | 60 +++++++++++++++ .../jetbrains/jet/lang/types/ErrorUtils.java | 2 +- .../jet/lang/types/TypeConstructorImpl.java | 58 +++++++++++++- .../types/checker/TypeCheckingProcedure.java | 3 +- .../DeserializedClassDescriptor.java | 3 +- 25 files changed, 599 insertions(+), 15 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArguments.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/differentGenericArgumentsReversed.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateClass.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateNestedClasses.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/duplicateSuperClass.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericArgumentNumberMismatch.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/genericSuperClass.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsage.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/inTheSameModuleWithUsageNoTypeAnnotation.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/members.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameClassNameDifferentPackages.kt create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateClass/sameGenericArguments.kt create mode 100644 core/descriptors/src/org/jetbrains/jet/lang/types/AbstractClassTypeConstructor.java 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;