KT-3500: ClassFormatError: Duplicate method name&signature in class file && KT-3429: Traits override bug

This commit is contained in:
Mikhael Bogdanov
2013-04-16 18:32:24 +04:00
parent 3da3f94b4e
commit 57b161b08a
15 changed files with 166 additions and 30 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
@@ -55,6 +56,7 @@ import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
@@ -1298,8 +1300,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void generateTraitMethods() {
if (myClass instanceof JetClass &&
(((JetClass) myClass).isTrait() || myClass.hasModifier(JetTokens.ABSTRACT_KEYWORD))) {
if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) {
return;
}
@@ -1699,7 +1700,7 @@ 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 static List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) {
private List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) {
List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> r = Lists.newArrayList();
root:
@@ -1715,21 +1716,39 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Collection<CallableMemberDescriptor> overriddenDeclarations =
OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor);
for (CallableMemberDescriptor overriddenDeclaration : overriddenDeclarations) {
if (overriddenDeclaration.getModality() != Modality.ABSTRACT) {
if (!isInterface(overriddenDeclaration.getContainingDeclaration())) {
continue root;
}
Collection<CallableMemberDescriptor> filteredOverriddenDeclarations =
OverridingUtil.filterOverrides(Sets.newLinkedHashSet(overriddenDeclarations));
int count = 0;
CallableMemberDescriptor candidate = null;
for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) {
if (isKindOf(overriddenDeclaration.getContainingDeclaration(), ClassKind.TRAIT) &&
overriddenDeclaration.getModality() != Modality.ABSTRACT) {
candidate = overriddenDeclaration;
count++;
}
}
if (candidate == null) {
continue;
}
for (CallableMemberDescriptor overriddenDeclaration : overriddenDeclarations) {
if (overriddenDeclaration.getModality() != Modality.ABSTRACT) {
r.add(Pair.create(callableMemberDescriptor, overriddenDeclaration));
}
assert count == 1 : "Ambiguous overriden declaration: " + callableMemberDescriptor.getName();
Collection<JetType> superTypesOfSuperClass =
superClassType != null ? TypeUtils.getAllSupertypes(superClassType) : Collections.<JetType>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));
}
}
return r;
}
}
@@ -27,7 +27,7 @@ public class JvmAbi {
* This constant is used to identify binary format (class file) versions
* If you change class file metadata format and/or naming conventions, please increase this number
*/
public static final int VERSION = 4;
public static final int VERSION = 5;
public static final String TRAIT_IMPL_CLASS_NAME = "$TImpl";
public static final String TRAIT_IMPL_SUFFIX = "$" + TRAIT_IMPL_CLASS_NAME;
@@ -356,6 +356,7 @@ public interface Errors {
DiagnosticFactory1<JetSuperExpression, String> SUPER_IS_NOT_AN_EXPRESSION = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<JetSuperExpression> SUPER_NOT_AVAILABLE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetSuperExpression> SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetSuperExpression> AMBIGUOUS_SUPER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetExpression> ABSTRACT_SUPER_CALL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<JetTypeReference> NOT_A_SUPERTYPE = DiagnosticFactory0.create(ERROR);
@@ -213,6 +213,7 @@ public class DefaultErrorMessages {
MAP.put(SETTER_PARAMETER_WITH_DEFAULT_VALUE, "Setter parameters cannot have default values");
MAP.put(NO_THIS, "'this' is not defined in this context");
MAP.put(SUPER_NOT_AVAILABLE, "No supertypes are accessible in this context");
MAP.put(SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT, "Superclass is not accessible from trait");
MAP.put(AMBIGUOUS_SUPER, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super<Foo>'");
MAP.put(ABSTRACT_SUPER_CALL, "Abstract member cannot be accessed directly");
MAP.put(NOT_A_SUPERTYPE, "Not a supertype");
@@ -273,23 +273,31 @@ public class DescriptorUtils {
}
public static boolean isClassObject(@NotNull DeclarationDescriptor descriptor) {
return descriptor instanceof ClassDescriptor
&& ((ClassDescriptor) descriptor).getKind() == ClassKind.CLASS_OBJECT;
return isKindOf(descriptor, ClassKind.CLASS_OBJECT);
}
public static boolean isAnonymous(@Nullable ClassifierDescriptor descriptor) {
return descriptor instanceof ClassDescriptor
&& descriptor.getName().isSpecial() && ((ClassDescriptor)descriptor).getKind() == ClassKind.OBJECT;
return isKindOf(descriptor, ClassKind.OBJECT) && descriptor.getName().isSpecial();
}
public static boolean isEnumEntry(@NotNull DeclarationDescriptor descriptor) {
return descriptor instanceof ClassDescriptor
&& ((ClassDescriptor) descriptor).getKind() == ClassKind.ENUM_ENTRY;
return isKindOf(descriptor, ClassKind.ENUM_ENTRY);
}
public static boolean isEnumClass(@NotNull DeclarationDescriptor descriptor) {
return descriptor instanceof ClassDescriptor
&& ((ClassDescriptor) descriptor).getKind() == ClassKind.ENUM_CLASS;
return isKindOf(descriptor, ClassKind.ENUM_CLASS);
}
public static boolean isKindOf(@NotNull JetType jetType, @NotNull ClassKind classKind) {
ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
return isKindOf(descriptor, classKind);
}
public static boolean isKindOf(@Nullable DeclarationDescriptor descriptor, @NotNull ClassKind classKind) {
if (descriptor instanceof ClassDescriptor) {
return ((ClassDescriptor) descriptor).getKind() == classKind;
}
return false;
}
@NotNull
@@ -494,6 +494,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
}
if (result != null) {
if (DescriptorUtils.isKindOf(thisType, ClassKind.TRAIT)) {
if (DescriptorUtils.isKindOf(result, ClassKind.CLASS)) {
context.trace.report(SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT.on(expression));
}
}
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
if (superTypeQualifier != null) {
+2 -2
View File
@@ -1,4 +1,4 @@
WARNING: $TESTDATA_DIR$/wrongAbiVersion.kt: (3, 9) Parameter 'x' is never used
ERROR: $TESTDATA_DIR$/wrongAbiVersionLib/wrong/WrongPackage.java: (3, 1) Class 'wrong.WrongPackage' was compiled with an incompatible version of Kotlin. Its ABI version is -1, expected ABI version is 4
ERROR: $TESTDATA_DIR$/wrongAbiVersionLib/ClassWithWrongAbiVersion.java: (3, 1) Class 'ClassWithWrongAbiVersion' was compiled with an incompatible version of Kotlin. Its ABI version is -1, expected ABI version is 4
ERROR: $TESTDATA_DIR$/wrongAbiVersionLib/wrong/WrongPackage.java: (3, 1) Class 'wrong.WrongPackage' was compiled with an incompatible version of Kotlin. Its ABI version is -1, expected ABI version is 5
ERROR: $TESTDATA_DIR$/wrongAbiVersionLib/ClassWithWrongAbiVersion.java: (3, 1) Class 'ClassWithWrongAbiVersion' was compiled with an incompatible version of Kotlin. Its ABI version is -1, expected ABI version is 5
COMPILATION_ERROR
@@ -0,0 +1,21 @@
trait A<T> {
val property : T
open fun a() : T {
return property
}
}
open class B : A<Any> {
override val property: Any = "fail"
}
open class C : B(), A<Any> {
override val property: Any = "OK"
}
fun box() : String {
return C().a() as String
}
@@ -0,0 +1,17 @@
open class Base {
open fun sayHello(): String{
return "fail"
}
}
trait Trait: Base {
override fun sayHello(): String {
return "OK"
}
}
class Derived(): Base(), Trait
fun box() : String {
return Derived().sayHello()
}
@@ -0,0 +1,15 @@
trait BK {
fun foo(): String = 10.toString()
}
trait KTrait: BK {
override fun foo() = 30.toString()
}
class A : BK, KTrait {
}
fun box(): String {
return if (A().foo() == "30") "OK" else "fail"
}
@@ -1,16 +1,18 @@
open class Base {
open fun foo() { }
open fun foo() : String {
return "fail"
}
}
trait Derived : Base {
override fun foo() {
super.foo()
override fun foo() : String {
//super.foo()
return "OK"
}
}
class DerivedImpl : Derived, Base()
fun box(): String {
DerivedImpl().foo()
return "OK"
return DerivedImpl().foo()
}
@@ -1,12 +1,14 @@
open class Base {
open fun foo() { }
open fun foo2() { }
}
trait Derived : Base {
override fun foo() {
object {
fun bar() {
super<Base>@Derived.foo()
//super<Base>@Derived.foo2()
this@Derived.foo2()
}
}.bar()
}
@@ -0,0 +1,10 @@
open class A {
open fun foo() {}
}
trait ATrait : A {
override fun foo() {
<!SUPERCLASS_NOT_ACCESSIBLE_FROM_TRAIT!>super<A><!>.foo()
}
}
@@ -4352,6 +4352,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/thisAndSuper/ambigousLabelOnThis.kt");
}
@TestMetadata("notAccessibleSuperInTrait.kt")
public void testNotAccessibleSuperInTrait() throws Exception {
doTest("compiler/testData/diagnostics/tests/thisAndSuper/notAccessibleSuperInTrait.kt");
}
@TestMetadata("QualifiedThis.kt")
public void testQualifiedThis() throws Exception {
doTest("compiler/testData/diagnostics/tests/thisAndSuper/QualifiedThis.kt");
@@ -3295,11 +3295,26 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/super/innerClassLabeledSuper.kt");
}
@TestMetadata("innerClassLabeledSuper2.kt")
public void testInnerClassLabeledSuper2() throws Exception {
doTest("compiler/testData/codegen/box/super/innerClassLabeledSuper2.kt");
}
@TestMetadata("innerClassLabeledSuperProperty.kt")
public void testInnerClassLabeledSuperProperty() throws Exception {
doTest("compiler/testData/codegen/box/super/innerClassLabeledSuperProperty.kt");
}
@TestMetadata("innerClassLabeledSuperProperty2.kt")
public void testInnerClassLabeledSuperProperty2() throws Exception {
doTest("compiler/testData/codegen/box/super/innerClassLabeledSuperProperty2.kt");
}
@TestMetadata("kt3492ClassFun.kt")
public void testKt3492ClassFun() throws Exception {
doTest("compiler/testData/codegen/box/super/kt3492ClassFun.kt");
}
@TestMetadata("kt3492ClassProperty.kt")
public void testKt3492ClassProperty() throws Exception {
doTest("compiler/testData/codegen/box/super/kt3492ClassProperty.kt");
@@ -3338,6 +3353,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/traits/finalMethod.kt");
}
@TestMetadata("genericMethod.kt")
public void testGenericMethod() throws Exception {
doTest("compiler/testData/codegen/box/traits/genericMethod.kt");
}
@TestMetadata("inheritedFun.kt")
public void testInheritedFun() throws Exception {
doTest("compiler/testData/codegen/box/traits/inheritedFun.kt");
@@ -3383,6 +3403,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
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");
}
@TestMetadata("multiple.kt")
public void testMultiple() throws Exception {
doTest("compiler/testData/codegen/box/traits/multiple.kt");