From fc838dbb531acb32dc60fc572e1be0ca7e168d92 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 8 Apr 2014 18:37:02 +0400 Subject: [PATCH] Refactor ImplementationBodyCodegen.getTraitImplementations() Make it static, extract a method which finds an implementation in a trait for a fake override --- .../codegen/ImplementationBodyCodegen.java | 99 ++++++------- .../generic.kt} | 0 .../genericProperty.kt} | 0 .../box/traits/{ => withRequired}/kt1936_2.kt | 0 .../box/traits/{ => withRequired}/kt2963.kt | 0 .../box/traits/{ => withRequired}/kt3413.kt | 0 .../box/traits/{ => withRequired}/kt3429.kt | 0 .../property.kt} | 0 .../propertyViaBridge.kt} | 0 .../box/traits/{ => withRequired}/simple.kt | 0 .../super.kt} | 0 .../superViaBridge.kt} | 0 .../{ => withRequired}/traitFuncCall.kt | 0 .../bytecodeText/traitImplGeneratedOnce.kt | 15 ++ .../codegen/BytecodeTextTestGenerated.java | 5 + .../BlackBoxCodegenTestGenerated.java | 131 ++++++++++-------- 16 files changed, 145 insertions(+), 105 deletions(-) rename compiler/testData/codegen/box/traits/{withRequired.kt => withRequired/generic.kt} (100%) rename compiler/testData/codegen/box/traits/{withRequiredGenericProperty.kt => withRequired/genericProperty.kt} (100%) rename compiler/testData/codegen/box/traits/{ => withRequired}/kt1936_2.kt (100%) rename compiler/testData/codegen/box/traits/{ => withRequired}/kt2963.kt (100%) rename compiler/testData/codegen/box/traits/{ => withRequired}/kt3413.kt (100%) rename compiler/testData/codegen/box/traits/{ => withRequired}/kt3429.kt (100%) rename compiler/testData/codegen/box/traits/{withRequiredProperty.kt => withRequired/property.kt} (100%) rename compiler/testData/codegen/box/traits/{withRequiredPropertyViaBridge.kt => withRequired/propertyViaBridge.kt} (100%) rename compiler/testData/codegen/box/traits/{ => withRequired}/simple.kt (100%) rename compiler/testData/codegen/box/traits/{withRequiredSuper.kt => withRequired/super.kt} (100%) rename compiler/testData/codegen/box/traits/{withRequiredSuperViaBridge.kt => withRequired/superViaBridge.kt} (100%) rename compiler/testData/codegen/box/traits/{ => withRequired}/traitFuncCall.kt (100%) create mode 100644 compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 1e055444d87..bc3b0e1112b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -1815,58 +1815,63 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { * Return pairs of descriptors. First is member of this that should be implemented by delegating to trait, * second is member of trait that contain implementation. */ - private List> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) { - List> r = Lists.newArrayList(); + @NotNull + private static List> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) { + List> result = Lists.newArrayList(); - for (DeclarationDescriptor decl : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { - if (!(decl instanceof CallableMemberDescriptor)) { - continue; - } + for (DeclarationDescriptor declaration : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { + if (!(declaration instanceof CallableMemberDescriptor)) continue; - CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) decl; - if (callableMemberDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { - continue; - } + CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration; - if (CallResolverUtil.isOrOverridesSynthesized(callableMemberDescriptor)) { - continue; - } - - Collection overriddenDeclarations = - OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor); - - Collection filteredOverriddenDeclarations = - OverridingUtil.filterOutOverridden(Sets.newLinkedHashSet(overriddenDeclarations)); - - int count = 0; - CallableMemberDescriptor candidate = null; - - for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) { - if (isTrait(overriddenDeclaration.getContainingDeclaration()) && - overriddenDeclaration.getModality() != Modality.ABSTRACT) { - candidate = overriddenDeclaration; - count++; - } - } - if (candidate == null) { - continue; - } - - assert count == 1 : "Ambiguous overridden declaration: " + callableMemberDescriptor.getName(); - - - Collection superTypesOfSuperClass = - superClassType != null ? TypeUtils.getAllSupertypes(superClassType) : Collections.emptySet(); - ReceiverParameterDescriptor expectedThisObject = candidate.getExpectedThisObject(); - assert expectedThisObject != null; - JetType candidateType = expectedThisObject.getType(); - boolean implementedInSuperClass = superTypesOfSuperClass.contains(candidateType); - - if (!implementedInSuperClass) { - r.add(Pair.create(callableMemberDescriptor, candidate)); + CallableMemberDescriptor implementation = findTraitImplementation(callableMemberDescriptor); + if (implementation != null) { + result.add(Pair.create(callableMemberDescriptor, implementation)); } } - return r; + + return result; + } + + /** + * Given a fake override descriptor, returns an overridden non-abstract descriptor whose container is a trait + */ + @Nullable + private static CallableMemberDescriptor findTraitImplementation(@NotNull CallableMemberDescriptor descriptor) { + if (descriptor.getKind().isReal()) return null; + + if (CallResolverUtil.isOrOverridesSynthesized(descriptor)) return null; + + Collection overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor); + + Collection filteredOverriddenDeclarations = + OverridingUtil.filterOutOverridden(Sets.newLinkedHashSet(overriddenDeclarations)); + + int count = 0; + CallableMemberDescriptor implementation = null; + + for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) { + if (isTrait(overriddenDeclaration.getContainingDeclaration()) && overriddenDeclaration.getModality() != Modality.ABSTRACT) { + implementation = overriddenDeclaration; + count++; + } + } + if (implementation == null) { + return null; + } + + assert count == 1 : "Ambiguous overridden declaration: " + descriptor; + + ClassDescriptor containingClass = (ClassDescriptor) descriptor.getContainingDeclaration(); + for (JetType supertype : containingClass.getDefaultType().getConstructor().getSupertypes()) { + //noinspection ConstantConditions + if (!isTrait(supertype.getConstructor().getDeclarationDescriptor()) && + TypeUtils.getAllSupertypes(supertype).contains(implementation.getExpectedThisObject().getType())) { + return null; + } + } + + return implementation; } public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) { diff --git a/compiler/testData/codegen/box/traits/withRequired.kt b/compiler/testData/codegen/box/traits/withRequired/generic.kt similarity index 100% rename from compiler/testData/codegen/box/traits/withRequired.kt rename to compiler/testData/codegen/box/traits/withRequired/generic.kt diff --git a/compiler/testData/codegen/box/traits/withRequiredGenericProperty.kt b/compiler/testData/codegen/box/traits/withRequired/genericProperty.kt similarity index 100% rename from compiler/testData/codegen/box/traits/withRequiredGenericProperty.kt rename to compiler/testData/codegen/box/traits/withRequired/genericProperty.kt diff --git a/compiler/testData/codegen/box/traits/kt1936_2.kt b/compiler/testData/codegen/box/traits/withRequired/kt1936_2.kt similarity index 100% rename from compiler/testData/codegen/box/traits/kt1936_2.kt rename to compiler/testData/codegen/box/traits/withRequired/kt1936_2.kt diff --git a/compiler/testData/codegen/box/traits/kt2963.kt b/compiler/testData/codegen/box/traits/withRequired/kt2963.kt similarity index 100% rename from compiler/testData/codegen/box/traits/kt2963.kt rename to compiler/testData/codegen/box/traits/withRequired/kt2963.kt diff --git a/compiler/testData/codegen/box/traits/kt3413.kt b/compiler/testData/codegen/box/traits/withRequired/kt3413.kt similarity index 100% rename from compiler/testData/codegen/box/traits/kt3413.kt rename to compiler/testData/codegen/box/traits/withRequired/kt3413.kt diff --git a/compiler/testData/codegen/box/traits/kt3429.kt b/compiler/testData/codegen/box/traits/withRequired/kt3429.kt similarity index 100% rename from compiler/testData/codegen/box/traits/kt3429.kt rename to compiler/testData/codegen/box/traits/withRequired/kt3429.kt diff --git a/compiler/testData/codegen/box/traits/withRequiredProperty.kt b/compiler/testData/codegen/box/traits/withRequired/property.kt similarity index 100% rename from compiler/testData/codegen/box/traits/withRequiredProperty.kt rename to compiler/testData/codegen/box/traits/withRequired/property.kt diff --git a/compiler/testData/codegen/box/traits/withRequiredPropertyViaBridge.kt b/compiler/testData/codegen/box/traits/withRequired/propertyViaBridge.kt similarity index 100% rename from compiler/testData/codegen/box/traits/withRequiredPropertyViaBridge.kt rename to compiler/testData/codegen/box/traits/withRequired/propertyViaBridge.kt diff --git a/compiler/testData/codegen/box/traits/simple.kt b/compiler/testData/codegen/box/traits/withRequired/simple.kt similarity index 100% rename from compiler/testData/codegen/box/traits/simple.kt rename to compiler/testData/codegen/box/traits/withRequired/simple.kt diff --git a/compiler/testData/codegen/box/traits/withRequiredSuper.kt b/compiler/testData/codegen/box/traits/withRequired/super.kt similarity index 100% rename from compiler/testData/codegen/box/traits/withRequiredSuper.kt rename to compiler/testData/codegen/box/traits/withRequired/super.kt diff --git a/compiler/testData/codegen/box/traits/withRequiredSuperViaBridge.kt b/compiler/testData/codegen/box/traits/withRequired/superViaBridge.kt similarity index 100% rename from compiler/testData/codegen/box/traits/withRequiredSuperViaBridge.kt rename to compiler/testData/codegen/box/traits/withRequired/superViaBridge.kt diff --git a/compiler/testData/codegen/box/traits/traitFuncCall.kt b/compiler/testData/codegen/box/traits/withRequired/traitFuncCall.kt similarity index 100% rename from compiler/testData/codegen/box/traits/traitFuncCall.kt rename to compiler/testData/codegen/box/traits/withRequired/traitFuncCall.kt diff --git a/compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt b/compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt new file mode 100644 index 00000000000..51ce275d99e --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt @@ -0,0 +1,15 @@ +trait A { + fun foo() = 42 +} + +open class B : A + +open class C : B() + +class D : C() + +// Implementation of foo() should only be generated into B +// 1 INVOKESTATIC A\$\$TImpl.foo + +// Only two declarations should be present: in A and B +// 2 foo\(\)I diff --git a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java index 3a143a94c73..115cf10aa91 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/BytecodeTextTestGenerated.java @@ -122,6 +122,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest("compiler/testData/codegen/bytecodeText/topLevelFunWithDefaultArgs.kt"); } + @TestMetadata("traitImplGeneratedOnce.kt") + public void testTraitImplGeneratedOnce() throws Exception { + doTest("compiler/testData/codegen/bytecodeText/traitImplGeneratedOnce.kt"); + } + @TestMetadata("compiler/testData/codegen/bytecodeText/constants") public static class Constants extends AbstractBytecodeTextTest { public void testAllFilesPresentInConstants() throws Exception { diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 1f1f0be6187..a7643d4176c 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -5075,6 +5075,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } @TestMetadata("compiler/testData/codegen/box/traits") + @InnerTestClasses({Traits.WithRequired.class}) public static class Traits extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInTraits() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box/traits"), Pattern.compile("^(.+)\\.kt$"), true); @@ -5110,11 +5111,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/traits/kt1936_1.kt"); } - @TestMetadata("kt1936_2.kt") - public void testKt1936_2() throws Exception { - doTest("compiler/testData/codegen/box/traits/kt1936_2.kt"); - } - @TestMetadata("kt2260.kt") public void testKt2260() throws Exception { doTest("compiler/testData/codegen/box/traits/kt2260.kt"); @@ -5130,26 +5126,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/traits/kt2541.kt"); } - @TestMetadata("kt2963.kt") - public void testKt2963() throws Exception { - doTest("compiler/testData/codegen/box/traits/kt2963.kt"); - } - @TestMetadata("kt3315.kt") public void testKt3315() throws Exception { doTest("compiler/testData/codegen/box/traits/kt3315.kt"); } - @TestMetadata("kt3413.kt") - public void testKt3413() throws Exception { - doTest("compiler/testData/codegen/box/traits/kt3413.kt"); - } - - @TestMetadata("kt3429.kt") - public void testKt3429() throws Exception { - doTest("compiler/testData/codegen/box/traits/kt3429.kt"); - } - @TestMetadata("kt3500.kt") public void testKt3500() throws Exception { doTest("compiler/testData/codegen/box/traits/kt3500.kt"); @@ -5160,51 +5141,85 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/traits/multiple.kt"); } - @TestMetadata("simple.kt") - public void testSimple() throws Exception { - doTest("compiler/testData/codegen/box/traits/simple.kt"); - } - @TestMetadata("stdlib.kt") public void testStdlib() throws Exception { doTest("compiler/testData/codegen/box/traits/stdlib.kt"); } - @TestMetadata("traitFuncCall.kt") - public void testTraitFuncCall() throws Exception { - doTest("compiler/testData/codegen/box/traits/traitFuncCall.kt"); + @TestMetadata("compiler/testData/codegen/box/traits/withRequired") + public static class WithRequired extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInWithRequired() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box/traits/withRequired"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("generic.kt") + public void testGeneric() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/generic.kt"); + } + + @TestMetadata("genericProperty.kt") + public void testGenericProperty() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/genericProperty.kt"); + } + + @TestMetadata("kt1936_2.kt") + public void testKt1936_2() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/kt1936_2.kt"); + } + + @TestMetadata("kt2963.kt") + public void testKt2963() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/kt2963.kt"); + } + + @TestMetadata("kt3413.kt") + public void testKt3413() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/kt3413.kt"); + } + + @TestMetadata("kt3429.kt") + public void testKt3429() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/kt3429.kt"); + } + + @TestMetadata("property.kt") + public void testProperty() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/property.kt"); + } + + @TestMetadata("propertyViaBridge.kt") + public void testPropertyViaBridge() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/propertyViaBridge.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/simple.kt"); + } + + @TestMetadata("super.kt") + public void testSuper() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/super.kt"); + } + + @TestMetadata("superViaBridge.kt") + public void testSuperViaBridge() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/superViaBridge.kt"); + } + + @TestMetadata("traitFuncCall.kt") + public void testTraitFuncCall() throws Exception { + doTest("compiler/testData/codegen/box/traits/withRequired/traitFuncCall.kt"); + } + } - @TestMetadata("withRequired.kt") - public void testWithRequired() throws Exception { - doTest("compiler/testData/codegen/box/traits/withRequired.kt"); + public static Test innerSuite() { + TestSuite suite = new TestSuite("Traits"); + suite.addTestSuite(Traits.class); + suite.addTestSuite(WithRequired.class); + return suite; } - - @TestMetadata("withRequiredGenericProperty.kt") - public void testWithRequiredGenericProperty() throws Exception { - doTest("compiler/testData/codegen/box/traits/withRequiredGenericProperty.kt"); - } - - @TestMetadata("withRequiredProperty.kt") - public void testWithRequiredProperty() throws Exception { - doTest("compiler/testData/codegen/box/traits/withRequiredProperty.kt"); - } - - @TestMetadata("withRequiredPropertyViaBridge.kt") - public void testWithRequiredPropertyViaBridge() throws Exception { - doTest("compiler/testData/codegen/box/traits/withRequiredPropertyViaBridge.kt"); - } - - @TestMetadata("withRequiredSuper.kt") - public void testWithRequiredSuper() throws Exception { - doTest("compiler/testData/codegen/box/traits/withRequiredSuper.kt"); - } - - @TestMetadata("withRequiredSuperViaBridge.kt") - public void testWithRequiredSuperViaBridge() throws Exception { - doTest("compiler/testData/codegen/box/traits/withRequiredSuperViaBridge.kt"); - } - } @TestMetadata("compiler/testData/codegen/box/typeInfo") @@ -5551,7 +5566,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { suite.addTestSuite(Strings.class); suite.addTestSuite(Super.class); suite.addTestSuite(ToArray.class); - suite.addTestSuite(Traits.class); + suite.addTest(Traits.innerSuite()); suite.addTestSuite(TypeInfo.class); suite.addTestSuite(TypeMapping.class); suite.addTestSuite(UnaryOp.class);