From fb958897a92dd974bf183f6b26b62ff48e8d8b87 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 21 Jul 2014 22:10:53 +0400 Subject: [PATCH] Introduce kotlin.Cloneable - Cloneable is a trait with a single protected member 'clone', which is mapped to java.lang.Cloneable on JVM - 'clone' is non-abstract to be able to call 'super.clone()' in the implementations. Also if you need your class to be Cloneable, most of the time inheriting from Cloneable and calling 'super.clone()' will work - hack 'super.clone()' in JVM intrinsics and TImpl delegation generation - make arrays Cloneable, handle 'clone()' calls in the intrinsic #KT-4890 Fixed --- .../codegen/ImplementationBodyCodegen.java | 12 +++- .../jet/codegen/intrinsics/Clone.java | 65 +++++++++++++++++++ .../codegen/intrinsics/IntrinsicMethods.java | 5 ++ compiler/testData/builtin-classes.txt | 31 ++++++--- .../testData/codegen/box/classes/kt2288.kt | 2 +- .../objectMethods/cloneCallsConstructor.kt | 11 ++++ .../objectMethods/cloneCallsSuper.kt | 11 ++++ .../cloneCallsSuperAndModifies.kt | 16 +++++ .../javaInterop/objectMethods/cloneHashSet.kt | 12 ++++ .../objectMethods/cloneHierarchy.kt | 32 +++++++++ .../cloneableClassWithoutClone.kt | 11 ++++ .../boxWithStdlib/arrays/cloneArray.kt | 17 +++++ .../arrays/clonePrimitiveArrays.kt | 37 +++++++++++ .../GenericInterfaceParametersWithBounds.txt | 4 +- .../MethodTypePOneUpperBound.txt | 2 +- .../MethodTypePTwoUpperBounds.txt | 2 +- .../MethodWithTypeParameters.txt | 2 +- .../error/MissingUpperBound.txt | 2 +- .../WrongTypeParameterBoundStructure1.txt | 2 +- .../WrongTypeParameterBoundStructure2.java | 2 +- .../WrongTypeParameterBoundStructure2.txt | 2 +- .../propagation/typeParameter/TwoBounds.txt | 4 +- .../typeParameter/TwoTypeParameters.txt | 4 +- .../BlackBoxCodegenTestGenerated.java | 56 +++++++++++++++- ...lackBoxWithStdlibCodegenTestGenerated.java | 10 +++ core/builtins/native/kotlin/Array.kt | 4 +- core/builtins/native/kotlin/Arrays.kt | 32 ++++++--- core/builtins/native/kotlin/Cloneable.kt | 21 ++++++ .../mapping/JavaToKotlinClassMapBuilder.java | 1 + .../jet/lang/types/lang/KotlinBuiltIns.java | 10 +++ .../jet/generators/builtins/arrays.kt | 4 +- .../conflictingSubstitutions1.html | 2 +- .../conflictingSubstitutions2.html | 2 +- 33 files changed, 392 insertions(+), 38 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Clone.java create mode 100644 compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsConstructor.kt create mode 100644 compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuper.kt create mode 100644 compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuperAndModifies.kt create mode 100644 compiler/testData/codegen/box/javaInterop/objectMethods/cloneHashSet.kt create mode 100644 compiler/testData/codegen/box/javaInterop/objectMethods/cloneHierarchy.kt create mode 100644 compiler/testData/codegen/box/javaInterop/objectMethods/cloneableClassWithoutClone.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/arrays/cloneArray.kt create mode 100644 compiler/testData/codegen/boxWithStdlib/arrays/clonePrimitiveArrays.kt create mode 100644 core/builtins/native/kotlin/Cloneable.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 6410c478cfb..16991bbb30f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -1505,7 +1505,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { DeclarationDescriptor containingDeclaration = traitFun.getContainingDeclaration(); if (!DescriptorUtils.isTrait(containingDeclaration)) return; - Type traitImplType = typeMapper.mapTraitImpl((ClassDescriptor) containingDeclaration); + ClassDescriptor containingTrait = (ClassDescriptor) containingDeclaration; + Type traitImplType = typeMapper.mapTraitImpl(containingTrait); Method traitMethod = typeMapper.mapSignature(traitFun.getOriginal(), OwnerKind.TRAIT_IMPL).getAsmMethod(); @@ -1522,7 +1523,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { reg += argTypes[i].getSize(); } - iv.invokestatic(traitImplType.getInternalName(), traitMethod.getName(), traitMethod.getDescriptor()); + if (KotlinBuiltIns.getInstance().isCloneable(containingTrait) && traitMethod.getName().equals("clone")) { + // A special hack for Cloneable: there's no kotlin/Cloneable$$TImpl class at runtime, + // and its 'clone' method is actually located in java/lang/Object + iv.invokespecial("java/lang/Object", "clone", "()Ljava/lang/Object;", false); + } + else { + iv.invokestatic(traitImplType.getInternalName(), traitMethod.getName(), traitMethod.getDescriptor()); + } Type returnType = signature.getReturnType(); StackValue.onStack(traitMethod.getReturnType()).put(returnType, iv); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Clone.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Clone.java new file mode 100644 index 00000000000..229a899b6e1 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/Clone.java @@ -0,0 +1,65 @@ +/* + * 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.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.StackValue; +import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetSuperExpression; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; +import org.jetbrains.org.objectweb.asm.Type; +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; + +import java.util.List; + +import static org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage.getResolvedCallWithAssert; +import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; + +public class Clone extends IntrinsicMethod { + @NotNull + @Override + protected Type generateImpl( + @NotNull ExpressionCodegen codegen, + @NotNull InstructionAdapter v, + @NotNull Type returnType, + @Nullable PsiElement element, + @Nullable List arguments, + @Nullable StackValue receiver + ) { + ResolvedCall resolvedCall = getResolvedCallWithAssert(((JetElement) element), codegen.getBindingContext()); + StackValue.receiver(resolvedCall, receiver, codegen, null).put(OBJECT_TYPE, v); + if (isSuperCall(resolvedCall)) { + v.invokespecial("java/lang/Object", "clone", "()Ljava/lang/Object;", false); + } + else { + v.invokevirtual("java/lang/Object", "clone", "()Ljava/lang/Object;", false); + } + return OBJECT_TYPE; + } + + private static boolean isSuperCall(@NotNull ResolvedCall resolvedCall) { + ReceiverValue thisObject = resolvedCall.getThisObject(); + return thisObject instanceof ExpressionReceiver && + ((ExpressionReceiver) thisObject).getExpression() instanceof JetSuperExpression; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 50bcb93347c..25864f197be 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -61,6 +61,7 @@ public class IntrinsicMethods { private static final EnumValues ENUM_VALUES = new EnumValues(); private static final EnumValueOf ENUM_VALUE_OF = new EnumValueOf(); private static final ToString TO_STRING = new ToString(); + private static final Clone CLONE = new Clone(); private static final FqNameUnsafe KOTLIN_ANY_FQ_NAME = DescriptorUtils.getFqName(KotlinBuiltIns.getInstance().getAny()); private static final FqNameUnsafe KOTLIN_STRING_FQ_NAME = DescriptorUtils.getFqName(KotlinBuiltIns.getInstance().getString()); @@ -121,6 +122,8 @@ public class IntrinsicMethods { declareIntrinsicFunction("CharSequence", "get", 1, new StringGetChar()); declareIntrinsicFunction("String", "get", 1, new StringGetChar()); + declareIntrinsicFunction("Cloneable", "clone", 0, CLONE); + intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_ANY_FQ_NAME, "toString", 0, TO_STRING); intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_ANY_FQ_NAME, "equals", 1, EQUALS); intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KOTLIN_ANY_FQ_NAME, "identityEquals", 1, IDENTITY_EQUALS); @@ -148,6 +151,7 @@ public class IntrinsicMethods { declareIntrinsicProperty("Array", "indices", ARRAY_INDICES); declareIntrinsicFunction("Array", "set", 2, ARRAY_SET); declareIntrinsicFunction("Array", "get", 1, ARRAY_GET); + declareIntrinsicFunction("Array", "clone", 0, CLONE); declareIterator("Array"); } @@ -157,6 +161,7 @@ public class IntrinsicMethods { declareIntrinsicProperty(arrayTypeName, "indices", ARRAY_INDICES); declareIntrinsicFunction(arrayTypeName, "set", 2, ARRAY_SET); declareIntrinsicFunction(arrayTypeName, "get", 1, ARRAY_GET); + declareIntrinsicFunction(arrayTypeName, "clone", 0, CLONE); declareIterator(arrayTypeName); } diff --git a/compiler/testData/builtin-classes.txt b/compiler/testData/builtin-classes.txt index 5f9938510fd..d5a5cdb94ef 100644 --- a/compiler/testData/builtin-classes.txt +++ b/compiler/testData/builtin-classes.txt @@ -13,12 +13,13 @@ public open class Any { /*primary*/ public constructor Any() } -public final class Array { +public final class Array : kotlin.Cloneable { /*primary*/ public constructor Array(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1) public final val indices: kotlin.IntRange public final fun (): kotlin.IntRange public final val size: kotlin.Int public final fun (): kotlin.Int + public open override /*1*/ fun clone(): kotlin.Array public final fun get(/*0*/ index: kotlin.Int): T public final fun iterator(): kotlin.Iterator public final fun set(/*0*/ index: kotlin.Int, /*1*/ value: T): kotlin.Unit @@ -33,12 +34,13 @@ public final class Boolean : kotlin.Comparable { public final fun xor(/*0*/ other: kotlin.Boolean): kotlin.Boolean } -public final class BooleanArray { +public final class BooleanArray : kotlin.Cloneable { /*primary*/ public constructor BooleanArray(/*0*/ size: kotlin.Int) public final val indices: kotlin.IntRange public final fun (): kotlin.IntRange public final val size: kotlin.Int public final fun (): kotlin.Int + public open override /*1*/ fun clone(): kotlin.BooleanArray public final fun get(/*0*/ index: kotlin.Int): kotlin.Boolean public final fun iterator(): kotlin.BooleanIterator public final fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Boolean): kotlin.Unit @@ -115,12 +117,13 @@ public final class Byte : kotlin.Number, kotlin.Comparable { public open override /*1*/ fun toShort(): kotlin.Short } -public final class ByteArray { +public final class ByteArray : kotlin.Cloneable { /*primary*/ public constructor ByteArray(/*0*/ size: kotlin.Int) public final val indices: kotlin.IntRange public final fun (): kotlin.IntRange public final val size: kotlin.Int public final fun (): kotlin.Int + public open override /*1*/ fun clone(): kotlin.ByteArray public final fun get(/*0*/ index: kotlin.Int): kotlin.Byte public final fun iterator(): kotlin.ByteIterator public final fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Byte): kotlin.Unit @@ -235,12 +238,13 @@ public final class Char : kotlin.Comparable { public final fun toShort(): kotlin.Short } -public final class CharArray { +public final class CharArray : kotlin.Cloneable { /*primary*/ public constructor CharArray(/*0*/ size: kotlin.Int) public final val indices: kotlin.IntRange public final fun (): kotlin.IntRange public final val size: kotlin.Int public final fun (): kotlin.Int + public open override /*1*/ fun clone(): kotlin.CharArray public final fun get(/*0*/ index: kotlin.Int): kotlin.Char public final fun iterator(): kotlin.CharIterator public final fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Char): kotlin.Unit @@ -307,6 +311,10 @@ public trait CharSequence { public abstract fun get(/*0*/ index: kotlin.Int): kotlin.Char } +public trait Cloneable { + protected open fun clone(): kotlin.Any +} + public trait Collection : kotlin.Iterable { public abstract fun contains(/*0*/ o: kotlin.Any?): kotlin.Boolean public abstract fun containsAll(/*0*/ c: kotlin.Collection): kotlin.Boolean @@ -382,12 +390,13 @@ public final class Double : kotlin.Number, kotlin.Comparable { public open override /*1*/ fun toShort(): kotlin.Short } -public final class DoubleArray { +public final class DoubleArray : kotlin.Cloneable { /*primary*/ public constructor DoubleArray(/*0*/ size: kotlin.Int) public final val indices: kotlin.IntRange public final fun (): kotlin.IntRange public final val size: kotlin.Int public final fun (): kotlin.Int + public open override /*1*/ fun clone(): kotlin.DoubleArray public final fun get(/*0*/ index: kotlin.Int): kotlin.Double public final fun iterator(): kotlin.DoubleIterator public final fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Double): kotlin.Unit @@ -607,12 +616,13 @@ public final class Float : kotlin.Number, kotlin.Comparable { public open override /*1*/ fun toShort(): kotlin.Short } -public final class FloatArray { +public final class FloatArray : kotlin.Cloneable { /*primary*/ public constructor FloatArray(/*0*/ size: kotlin.Int) public final val indices: kotlin.IntRange public final fun (): kotlin.IntRange public final val size: kotlin.Int public final fun (): kotlin.Int + public open override /*1*/ fun clone(): kotlin.FloatArray public final fun get(/*0*/ index: kotlin.Int): kotlin.Float public final fun iterator(): kotlin.FloatIterator public final fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Float): kotlin.Unit @@ -905,12 +915,13 @@ public final class Int : kotlin.Number, kotlin.Comparable { public final fun xor(/*0*/ other: kotlin.Int): kotlin.Int } -public final class IntArray { +public final class IntArray : kotlin.Cloneable { /*primary*/ public constructor IntArray(/*0*/ size: kotlin.Int) public final val indices: kotlin.IntRange public final fun (): kotlin.IntRange public final val size: kotlin.Int public final fun (): kotlin.Int + public open override /*1*/ fun clone(): kotlin.IntArray public final fun get(/*0*/ index: kotlin.Int): kotlin.Int public final fun iterator(): kotlin.IntIterator public final fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Int): kotlin.Unit @@ -1074,12 +1085,13 @@ public final class Long : kotlin.Number, kotlin.Comparable { public final fun xor(/*0*/ other: kotlin.Long): kotlin.Long } -public final class LongArray { +public final class LongArray : kotlin.Cloneable { /*primary*/ public constructor LongArray(/*0*/ size: kotlin.Int) public final val indices: kotlin.IntRange public final fun (): kotlin.IntRange public final val size: kotlin.Int public final fun (): kotlin.Int + public open override /*1*/ fun clone(): kotlin.LongArray public final fun get(/*0*/ index: kotlin.Int): kotlin.Long public final fun iterator(): kotlin.LongIterator public final fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Long): kotlin.Unit @@ -1378,12 +1390,13 @@ public final class Short : kotlin.Number, kotlin.Comparable { public open override /*1*/ fun toShort(): kotlin.Short } -public final class ShortArray { +public final class ShortArray : kotlin.Cloneable { /*primary*/ public constructor ShortArray(/*0*/ size: kotlin.Int) public final val indices: kotlin.IntRange public final fun (): kotlin.IntRange public final val size: kotlin.Int public final fun (): kotlin.Int + public open override /*1*/ fun clone(): kotlin.ShortArray public final fun get(/*0*/ index: kotlin.Int): kotlin.Short public final fun iterator(): kotlin.ShortIterator public final fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Short): kotlin.Unit diff --git a/compiler/testData/codegen/box/classes/kt2288.kt b/compiler/testData/codegen/box/classes/kt2288.kt index cbd3385265b..5aa04a53b0a 100644 --- a/compiler/testData/codegen/box/classes/kt2288.kt +++ b/compiler/testData/codegen/box/classes/kt2288.kt @@ -1,6 +1,6 @@ public open class Test(): java.util.RandomAccess, Cloneable, java.io.Serializable { - public fun clone(): Test = Test() // Override 'clone()' with more precise type 'Test' + public override fun clone(): Test = Test() // Override 'clone()' with more precise type 'Test' public override fun toString() = "OK" } diff --git a/compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsConstructor.kt b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsConstructor.kt new file mode 100644 index 00000000000..b1fa6ed8434 --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsConstructor.kt @@ -0,0 +1,11 @@ +data class A(var x: Int) : Cloneable { + public override fun clone(): A = A(x) +} + +fun box(): String { + val a = A(42) + val b = a.clone() + if (b != a) return "Fail equals" + if (b identityEquals a) return "Fail identity" + return "OK" +} diff --git a/compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuper.kt b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuper.kt new file mode 100644 index 00000000000..d225016bc2a --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuper.kt @@ -0,0 +1,11 @@ +data class A(var x: Int) : Cloneable { + public override fun clone(): A = super.clone() as A +} + +fun box(): String { + val a = A(42) + val b = a.clone() + if (a != b) return "Fail equals" + if (a identityEquals b) return "Fail identity" + return "OK" +} diff --git a/compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuperAndModifies.kt b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuperAndModifies.kt new file mode 100644 index 00000000000..f9ed0541f5e --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuperAndModifies.kt @@ -0,0 +1,16 @@ +data class A(var x: Int) : Cloneable { + public override fun clone(): A { + val result = super.clone() as A + result.x = 239 + return result + } +} + +fun box(): String { + val a = A(42) + val b = a.clone() + if (a == b) return "Fail: $a == $b" + if (a identityEquals b) return "Fail: $a identityEquals $b" + if (b.x != 239) return "Fail: b.x = ${b.x}" + return "OK" +} diff --git a/compiler/testData/codegen/box/javaInterop/objectMethods/cloneHashSet.kt b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneHashSet.kt new file mode 100644 index 00000000000..8b912dde27f --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneHashSet.kt @@ -0,0 +1,12 @@ +import java.util.HashSet + +fun box(): String { + val a = HashSet() + a.add("live") + a.add("long") + a.add("prosper") + val b = a.clone() + if (a != b) return "Fail equals" + if (a identityEquals b) return "Fail identity" + return "OK" +} diff --git a/compiler/testData/codegen/box/javaInterop/objectMethods/cloneHierarchy.kt b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneHierarchy.kt new file mode 100644 index 00000000000..59ebd371d4d --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneHierarchy.kt @@ -0,0 +1,32 @@ +import java.util.ArrayList + +open class A : Cloneable { + public override fun clone(): A = super.clone() as A +} + +open class B(var s: String) : A() { + override fun clone(): B = super.clone() as B +} + +open class C(s: String, var l: ArrayList): B(s) { + override fun clone(): C { + val result = super.clone() as C + result.l = l.clone() as ArrayList + return result + } +} + +fun box(): String { + val l = ArrayList() + l.add(true) + + val c = C("OK", l) + val d = c.clone() + + if (c.s != d.s) return "Fail s: ${d.s}" + if (c.l != d.l) return "Fail l: ${d.l}" + if (c.l identityEquals d.l) return "Fail list identity" + if (c identityEquals d) return "Fail identity" + + return "OK" +} diff --git a/compiler/testData/codegen/box/javaInterop/objectMethods/cloneableClassWithoutClone.kt b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneableClassWithoutClone.kt new file mode 100644 index 00000000000..0c5115e23a7 --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/objectMethods/cloneableClassWithoutClone.kt @@ -0,0 +1,11 @@ +data class A(val s: String) : Cloneable { + fun externalClone(): A = clone() as A +} + +fun box(): String { + val a = A("OK") + val b = a.externalClone() + if (a != b) return "Fail equals" + if (a identityEquals b) return "Fail identity" + return b.s +} diff --git a/compiler/testData/codegen/boxWithStdlib/arrays/cloneArray.kt b/compiler/testData/codegen/boxWithStdlib/arrays/cloneArray.kt new file mode 100644 index 00000000000..656b19794e3 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/arrays/cloneArray.kt @@ -0,0 +1,17 @@ +import java.util.Arrays.equals + +fun box(): String { + val s = array("live", "long") + val t = s.clone() + t : Array + if (!equals(s, t)) return "Fail string" + if (s identityEquals t) return "Fail string identity" + + val ss = array(s, s) + val tt = ss.clone() + tt : Array> + if (!equals(ss, tt)) return "Fail string[]" + if (ss identityEquals tt) return "Fail string[] identity" + + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/arrays/clonePrimitiveArrays.kt b/compiler/testData/codegen/boxWithStdlib/arrays/clonePrimitiveArrays.kt new file mode 100644 index 00000000000..413033f31cf --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/arrays/clonePrimitiveArrays.kt @@ -0,0 +1,37 @@ +import java.util.Arrays.equals + +fun box(): String { + val i = intArray(1, 2) + if (!equals(i, i.clone())) return "Fail int" + if (i.clone() identityEquals i) return "Fail int identity" + + val j = longArray(1L, 2L) + if (!equals(j, j.clone())) return "Fail long" + if (j.clone() identityEquals j) return "Fail long identity" + + val s = shortArray(1.toShort(), 2.toShort()) + if (!equals(s, s.clone())) return "Fail short" + if (s.clone() identityEquals s) return "Fail short identity" + + val b = byteArray(1.toByte(), 2.toByte()) + if (!equals(b, b.clone())) return "Fail byte" + if (b.clone() identityEquals b) return "Fail byte identity" + + val c = charArray('a', 'b') + if (!equals(c, c.clone())) return "Fail char" + if (c.clone() identityEquals c) return "Fail char identity" + + val d = doubleArray(1.0, -1.0) + if (!equals(d, d.clone())) return "Fail double" + if (d.clone() identityEquals d) return "Fail double identity" + + val f = floatArray(1f, -1f) + if (!equals(f, f.clone())) return "Fail float" + if (f.clone() identityEquals f) return "Fail float identity" + + val z = booleanArray(true, false) + if (!equals(z, z.clone())) return "Fail boolean" + if (z.clone() identityEquals z) return "Fail boolean identity" + + return "OK" +} diff --git a/compiler/testData/loadJava/compiledJava/sam/GenericInterfaceParametersWithBounds.txt b/compiler/testData/loadJava/compiledJava/sam/GenericInterfaceParametersWithBounds.txt index 33cc5556db6..844834a8316 100644 --- a/compiler/testData/loadJava/compiledJava/sam/GenericInterfaceParametersWithBounds.txt +++ b/compiler/testData/loadJava/compiledJava/sam/GenericInterfaceParametersWithBounds.txt @@ -1,7 +1,7 @@ package test -public /*synthesized*/ fun ?, /*1*/ B : kotlin.List?> GenericInterfaceParametersWithBounds(/*0*/ function: (kotlin.Array?, B?) -> kotlin.Unit): test.GenericInterfaceParametersWithBounds where A : java.lang.Cloneable? +public /*synthesized*/ fun ?, /*1*/ B : kotlin.List?> GenericInterfaceParametersWithBounds(/*0*/ function: (kotlin.Array?, B?) -> kotlin.Unit): test.GenericInterfaceParametersWithBounds where A : kotlin.Cloneable? -public trait GenericInterfaceParametersWithBounds?, /*1*/ B : kotlin.List?> where A : java.lang.Cloneable? { +public trait GenericInterfaceParametersWithBounds?, /*1*/ B : kotlin.List?> where A : kotlin.Cloneable? { public abstract fun method(/*0*/ p0: kotlin.Array?, /*1*/ p1: B?): kotlin.Unit } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/MethodTypePOneUpperBound.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/MethodTypePOneUpperBound.txt index e16b6d36e18..e60e910fb46 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/MethodTypePOneUpperBound.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/MethodTypePOneUpperBound.txt @@ -2,5 +2,5 @@ package test public open class MethodTypePOneUpperBound { public constructor MethodTypePOneUpperBound() - public open fun bar(): kotlin.Unit + public open fun bar(): kotlin.Unit } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/MethodTypePTwoUpperBounds.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/MethodTypePTwoUpperBounds.txt index da9a0129e27..f17d46f2b20 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/MethodTypePTwoUpperBounds.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/MethodTypePTwoUpperBounds.txt @@ -2,5 +2,5 @@ package test public open class MethodTypePTwoUpperBounds { public constructor MethodTypePTwoUpperBounds() - public open fun foo(): kotlin.Unit where T : java.lang.Runnable? + public open fun foo(): kotlin.Unit where T : java.lang.Runnable? } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/MethodWithTypeParameters.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/MethodWithTypeParameters.txt index f5426a90bb6..b82685a7bc8 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/MethodWithTypeParameters.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/MethodWithTypeParameters.txt @@ -2,5 +2,5 @@ package test public open class MethodWithTypeParameters { public constructor MethodWithTypeParameters() - public open fun foo(/*0*/ a: A, /*1*/ b: kotlin.List, /*2*/ c: kotlin.MutableList): kotlin.Unit where B : kotlin.List + public open fun foo(/*0*/ a: A, /*1*/ b: kotlin.List, /*2*/ c: kotlin.MutableList): kotlin.Unit where B : kotlin.List } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/MissingUpperBound.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/MissingUpperBound.txt index 000e64ee276..989185d4f9e 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/MissingUpperBound.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/MissingUpperBound.txt @@ -2,5 +2,5 @@ package test public open class MissingUpperBound { public constructor MissingUpperBound() - public open fun foo(): kotlin.String? where A : java.lang.Cloneable? + public open fun foo(): kotlin.String? where A : kotlin.Cloneable? } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure1.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure1.txt index 492924b65f4..6ebf0f583fa 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure1.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure1.txt @@ -2,5 +2,5 @@ package test public open class WrongTypeParameterBoundStructure1 { public constructor WrongTypeParameterBoundStructure1() - public open fun foo(/*0*/ p0: A?, /*1*/ p1: kotlin.List?): kotlin.Unit where B : kotlin.List? + public open fun foo(/*0*/ p0: A?, /*1*/ p1: kotlin.List?): kotlin.Unit where B : kotlin.List? } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure2.java b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure2.java index 7d2e669b6d7..eaff297d920 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure2.java +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure2.java @@ -6,7 +6,7 @@ import jet.runtime.typeinfo.KotlinSignature; import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError; public class WrongTypeParameterBoundStructure2 { - @ExpectLoadError("'kotlin.List?' type in method signature has 1 type arguments, while 'List' in alternative signature has 0 of them") + @ExpectLoadError("'kotlin.List?' type in method signature has 1 type arguments, while 'List' in alternative signature has 0 of them") @KotlinSignature("fun foo(a : A, b : List) where B : List") public > void foo(A a, List b) { } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure2.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure2.txt index 5d2c7e53930..d4b9db26d72 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure2.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/error/WrongTypeParameterBoundStructure2.txt @@ -2,5 +2,5 @@ package test public open class WrongTypeParameterBoundStructure2 { public constructor WrongTypeParameterBoundStructure2() - public open fun foo(/*0*/ p0: A?, /*1*/ p1: kotlin.List?): kotlin.Unit where B : kotlin.List? + public open fun foo(/*0*/ p0: A?, /*1*/ p1: kotlin.List?): kotlin.Unit where B : kotlin.List? } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/typeParameter/TwoBounds.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/typeParameter/TwoBounds.txt index 912ed04a8bb..088088c39b9 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/typeParameter/TwoBounds.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/typeParameter/TwoBounds.txt @@ -3,10 +3,10 @@ package test public trait TwoBounds { public trait Sub : test.TwoBounds.Super { - public abstract override /*1*/ fun foo(/*0*/ a: B): kotlin.Unit where B : java.lang.Cloneable + public abstract override /*1*/ fun foo(/*0*/ a: B): kotlin.Unit where B : kotlin.Cloneable } public trait Super { - public abstract fun foo(/*0*/ a: A): kotlin.Unit where A : java.lang.Cloneable + public abstract fun foo(/*0*/ a: A): kotlin.Unit where A : kotlin.Cloneable } } diff --git a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/typeParameter/TwoTypeParameters.txt b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/typeParameter/TwoTypeParameters.txt index 4e824b9b925..6e9f31a72a9 100644 --- a/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/typeParameter/TwoTypeParameters.txt +++ b/compiler/testData/loadJava/compiledJavaCompareWithKotlin/kotlinSignature/propagation/typeParameter/TwoTypeParameters.txt @@ -3,10 +3,10 @@ package test public trait TwoTypeParameters { public trait Sub : test.TwoTypeParameters.Super { - public abstract override /*1*/ fun foo(/*0*/ a: B, /*1*/ b: A): kotlin.Unit + public abstract override /*1*/ fun foo(/*0*/ a: B, /*1*/ b: A): kotlin.Unit } public trait Super { - public abstract fun foo(/*0*/ a: A, /*1*/ b: B): kotlin.Unit + public abstract fun foo(/*0*/ a: A, /*1*/ b: B): kotlin.Unit } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 683c65b6b78..78066c76dd7 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.generated.AbstractBlackBoxCodegenTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/box") -@InnerTestClasses({BlackBoxCodegenTestGenerated.Arrays.class, BlackBoxCodegenTestGenerated.BinaryOp.class, BlackBoxCodegenTestGenerated.Bridges.class, BlackBoxCodegenTestGenerated.BuiltinStubMethods.class, BlackBoxCodegenTestGenerated.Casts.class, BlackBoxCodegenTestGenerated.Classes.class, BlackBoxCodegenTestGenerated.Closures.class, BlackBoxCodegenTestGenerated.Constants.class, BlackBoxCodegenTestGenerated.ControlStructures.class, BlackBoxCodegenTestGenerated.DefaultArguments.class, BlackBoxCodegenTestGenerated.DelegatedProperty.class, BlackBoxCodegenTestGenerated.Elvis.class, BlackBoxCodegenTestGenerated.Enum.class, BlackBoxCodegenTestGenerated.ExclExcl.class, BlackBoxCodegenTestGenerated.ExtensionFunctions.class, BlackBoxCodegenTestGenerated.ExtensionProperties.class, BlackBoxCodegenTestGenerated.FakeOverride.class, BlackBoxCodegenTestGenerated.FieldRename.class, BlackBoxCodegenTestGenerated.Finally.class, BlackBoxCodegenTestGenerated.Functions.class, BlackBoxCodegenTestGenerated.InnerNested.class, BlackBoxCodegenTestGenerated.Instructions.class, BlackBoxCodegenTestGenerated.Intrinsics.class, BlackBoxCodegenTestGenerated.Labels.class, BlackBoxCodegenTestGenerated.LocalClasses.class, BlackBoxCodegenTestGenerated.MultiDecl.class, BlackBoxCodegenTestGenerated.Objects.class, BlackBoxCodegenTestGenerated.OperatorConventions.class, BlackBoxCodegenTestGenerated.Package.class, BlackBoxCodegenTestGenerated.PrimitiveTypes.class, BlackBoxCodegenTestGenerated.Properties.class, BlackBoxCodegenTestGenerated.Reflection.class, BlackBoxCodegenTestGenerated.Regressions.class, BlackBoxCodegenTestGenerated.SafeCall.class, BlackBoxCodegenTestGenerated.SamConstructors.class, BlackBoxCodegenTestGenerated.Strings.class, BlackBoxCodegenTestGenerated.Super.class, BlackBoxCodegenTestGenerated.SuperConstructorCall.class, BlackBoxCodegenTestGenerated.ToArray.class, BlackBoxCodegenTestGenerated.Traits.class, BlackBoxCodegenTestGenerated.TypeInfo.class, BlackBoxCodegenTestGenerated.TypeMapping.class, BlackBoxCodegenTestGenerated.UnaryOp.class, BlackBoxCodegenTestGenerated.Unit.class, BlackBoxCodegenTestGenerated.Vararg.class, BlackBoxCodegenTestGenerated.When.class}) +@InnerTestClasses({BlackBoxCodegenTestGenerated.Arrays.class, BlackBoxCodegenTestGenerated.BinaryOp.class, BlackBoxCodegenTestGenerated.Bridges.class, BlackBoxCodegenTestGenerated.BuiltinStubMethods.class, BlackBoxCodegenTestGenerated.Casts.class, BlackBoxCodegenTestGenerated.Classes.class, BlackBoxCodegenTestGenerated.Closures.class, BlackBoxCodegenTestGenerated.Constants.class, BlackBoxCodegenTestGenerated.ControlStructures.class, BlackBoxCodegenTestGenerated.DefaultArguments.class, BlackBoxCodegenTestGenerated.DelegatedProperty.class, BlackBoxCodegenTestGenerated.Elvis.class, BlackBoxCodegenTestGenerated.Enum.class, BlackBoxCodegenTestGenerated.ExclExcl.class, BlackBoxCodegenTestGenerated.ExtensionFunctions.class, BlackBoxCodegenTestGenerated.ExtensionProperties.class, BlackBoxCodegenTestGenerated.FakeOverride.class, BlackBoxCodegenTestGenerated.FieldRename.class, BlackBoxCodegenTestGenerated.Finally.class, BlackBoxCodegenTestGenerated.Functions.class, BlackBoxCodegenTestGenerated.InnerNested.class, BlackBoxCodegenTestGenerated.Instructions.class, BlackBoxCodegenTestGenerated.Intrinsics.class, BlackBoxCodegenTestGenerated.JavaInterop.class, BlackBoxCodegenTestGenerated.Labels.class, BlackBoxCodegenTestGenerated.LocalClasses.class, BlackBoxCodegenTestGenerated.MultiDecl.class, BlackBoxCodegenTestGenerated.Objects.class, BlackBoxCodegenTestGenerated.OperatorConventions.class, BlackBoxCodegenTestGenerated.Package.class, BlackBoxCodegenTestGenerated.PrimitiveTypes.class, BlackBoxCodegenTestGenerated.Properties.class, BlackBoxCodegenTestGenerated.Reflection.class, BlackBoxCodegenTestGenerated.Regressions.class, BlackBoxCodegenTestGenerated.SafeCall.class, BlackBoxCodegenTestGenerated.SamConstructors.class, BlackBoxCodegenTestGenerated.Strings.class, BlackBoxCodegenTestGenerated.Super.class, BlackBoxCodegenTestGenerated.SuperConstructorCall.class, BlackBoxCodegenTestGenerated.ToArray.class, BlackBoxCodegenTestGenerated.Traits.class, BlackBoxCodegenTestGenerated.TypeInfo.class, BlackBoxCodegenTestGenerated.TypeMapping.class, BlackBoxCodegenTestGenerated.UnaryOp.class, BlackBoxCodegenTestGenerated.Unit.class, BlackBoxCodegenTestGenerated.Vararg.class, BlackBoxCodegenTestGenerated.When.class}) public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInBox() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box"), Pattern.compile("^(.+)\\.kt$"), true); @@ -3142,6 +3142,59 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } + @TestMetadata("compiler/testData/codegen/box/javaInterop") + @InnerTestClasses({JavaInterop.ObjectMethods.class}) + public static class JavaInterop extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInJavaInterop() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box/javaInterop"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("compiler/testData/codegen/box/javaInterop/objectMethods") + public static class ObjectMethods extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInObjectMethods() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box/javaInterop/objectMethods"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("cloneCallsConstructor.kt") + public void testCloneCallsConstructor() throws Exception { + doTest("compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsConstructor.kt"); + } + + @TestMetadata("cloneCallsSuper.kt") + public void testCloneCallsSuper() throws Exception { + doTest("compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuper.kt"); + } + + @TestMetadata("cloneCallsSuperAndModifies.kt") + public void testCloneCallsSuperAndModifies() throws Exception { + doTest("compiler/testData/codegen/box/javaInterop/objectMethods/cloneCallsSuperAndModifies.kt"); + } + + @TestMetadata("cloneHashSet.kt") + public void testCloneHashSet() throws Exception { + doTest("compiler/testData/codegen/box/javaInterop/objectMethods/cloneHashSet.kt"); + } + + @TestMetadata("cloneHierarchy.kt") + public void testCloneHierarchy() throws Exception { + doTest("compiler/testData/codegen/box/javaInterop/objectMethods/cloneHierarchy.kt"); + } + + @TestMetadata("cloneableClassWithoutClone.kt") + public void testCloneableClassWithoutClone() throws Exception { + doTest("compiler/testData/codegen/box/javaInterop/objectMethods/cloneableClassWithoutClone.kt"); + } + + } + + public static Test innerSuite() { + TestSuite suite = new TestSuite("JavaInterop"); + suite.addTestSuite(JavaInterop.class); + suite.addTestSuite(ObjectMethods.class); + return suite; + } + } + @TestMetadata("compiler/testData/codegen/box/labels") public static class Labels extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInLabels() throws Exception { @@ -5394,6 +5447,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { suite.addTestSuite(InnerNested.class); suite.addTest(Instructions.innerSuite()); suite.addTestSuite(Intrinsics.class); + suite.addTest(JavaInterop.innerSuite()); suite.addTestSuite(Labels.class); suite.addTestSuite(LocalClasses.class); suite.addTest(MultiDecl.innerSuite()); diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 5f2d399e55e..6590b774d59 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -91,6 +91,16 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/boxWithStdlib/arrays"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("cloneArray.kt") + public void testCloneArray() throws Exception { + doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/arrays/cloneArray.kt"); + } + + @TestMetadata("clonePrimitiveArrays.kt") + public void testClonePrimitiveArrays() throws Exception { + doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/arrays/clonePrimitiveArrays.kt"); + } + @TestMetadata("kt3771.kt") public void testKt3771() throws Exception { doTestWithStdlib("compiler/testData/codegen/boxWithStdlib/arrays/kt3771.kt"); diff --git a/core/builtins/native/kotlin/Array.kt b/core/builtins/native/kotlin/Array.kt index 4ed8a5dc7f5..42b10ed4c94 100644 --- a/core/builtins/native/kotlin/Array.kt +++ b/core/builtins/native/kotlin/Array.kt @@ -16,11 +16,13 @@ package kotlin -public class Array(public val size: Int, init: (Int) -> T) { +public class Array(public val size: Int, init: (Int) -> T) : Cloneable { public fun get(index: Int): T public fun set(index: Int, value: T): Unit public fun iterator(): Iterator public val indices: IntRange + + public override fun clone(): Array } diff --git a/core/builtins/native/kotlin/Arrays.kt b/core/builtins/native/kotlin/Arrays.kt index 3090550d74f..9c4604819a2 100644 --- a/core/builtins/native/kotlin/Arrays.kt +++ b/core/builtins/native/kotlin/Arrays.kt @@ -18,75 +18,91 @@ package kotlin -public class ByteArray(public val size: Int) { +public class ByteArray(public val size: Int) : Cloneable { public fun get(index: Int): Byte public fun set(index: Int, value: Byte): Unit public fun iterator(): ByteIterator public val indices: IntRange + + public override fun clone(): ByteArray } -public class CharArray(public val size: Int) { +public class CharArray(public val size: Int) : Cloneable { public fun get(index: Int): Char public fun set(index: Int, value: Char): Unit public fun iterator(): CharIterator public val indices: IntRange + + public override fun clone(): CharArray } -public class ShortArray(public val size: Int) { +public class ShortArray(public val size: Int) : Cloneable { public fun get(index: Int): Short public fun set(index: Int, value: Short): Unit public fun iterator(): ShortIterator public val indices: IntRange + + public override fun clone(): ShortArray } -public class IntArray(public val size: Int) { +public class IntArray(public val size: Int) : Cloneable { public fun get(index: Int): Int public fun set(index: Int, value: Int): Unit public fun iterator(): IntIterator public val indices: IntRange + + public override fun clone(): IntArray } -public class LongArray(public val size: Int) { +public class LongArray(public val size: Int) : Cloneable { public fun get(index: Int): Long public fun set(index: Int, value: Long): Unit public fun iterator(): LongIterator public val indices: IntRange + + public override fun clone(): LongArray } -public class FloatArray(public val size: Int) { +public class FloatArray(public val size: Int) : Cloneable { public fun get(index: Int): Float public fun set(index: Int, value: Float): Unit public fun iterator(): FloatIterator public val indices: IntRange + + public override fun clone(): FloatArray } -public class DoubleArray(public val size: Int) { +public class DoubleArray(public val size: Int) : Cloneable { public fun get(index: Int): Double public fun set(index: Int, value: Double): Unit public fun iterator(): DoubleIterator public val indices: IntRange + + public override fun clone(): DoubleArray } -public class BooleanArray(public val size: Int) { +public class BooleanArray(public val size: Int) : Cloneable { public fun get(index: Int): Boolean public fun set(index: Int, value: Boolean): Unit public fun iterator(): BooleanIterator public val indices: IntRange + + public override fun clone(): BooleanArray } diff --git a/core/builtins/native/kotlin/Cloneable.kt b/core/builtins/native/kotlin/Cloneable.kt new file mode 100644 index 00000000000..0929e1e6455 --- /dev/null +++ b/core/builtins/native/kotlin/Cloneable.kt @@ -0,0 +1,21 @@ +/* + * 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 kotlin + +public trait Cloneable { + protected fun clone(): Any { /* intrinsic */ } +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/mapping/JavaToKotlinClassMapBuilder.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/mapping/JavaToKotlinClassMapBuilder.java index fffdfc45c4d..6786d357ab0 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/mapping/JavaToKotlinClassMapBuilder.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/mapping/JavaToKotlinClassMapBuilder.java @@ -38,6 +38,7 @@ public abstract class JavaToKotlinClassMapBuilder { register(String.class, kotlinBuiltIns.getString()); register(CharSequence.class, kotlinBuiltIns.getCharSequence()); register(Throwable.class, kotlinBuiltIns.getThrowable()); + register(Cloneable.class, kotlinBuiltIns.getCloneable()); register(Number.class, kotlinBuiltIns.getNumber()); register(Comparable.class, kotlinBuiltIns.getComparable()); register(Enum.class, kotlinBuiltIns.getEnum()); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java index 892d60c30b3..22b4cbc53a9 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java @@ -138,6 +138,7 @@ public class KotlinBuiltIns { private static class FqNames { public final FqNameUnsafe any = fqName("Any"); public final FqNameUnsafe nothing = fqName("Nothing"); + public final FqNameUnsafe cloneable = fqName("Cloneable"); public final FqNameUnsafe suppress = fqName("suppress"); public final ImmutableSet functionClasses = computeIndexedFqNames("Function", FUNCTION_TRAIT_COUNT); @@ -300,6 +301,11 @@ public class KotlinBuiltIns { return getBuiltInClassByName("Throwable"); } + @NotNull + public ClassDescriptor getCloneable() { + return getBuiltInClassByName("Cloneable"); + } + @NotNull public ClassDescriptor getDataClassAnnotation() { return getBuiltInClassByName("data"); @@ -841,6 +847,10 @@ public class KotlinBuiltIns { return !(type instanceof PackageType) && getStringType().equals(type); } + public boolean isCloneable(@NotNull ClassDescriptor descriptor) { + return fqNames.cloneable.equals(DescriptorUtils.getFqName(descriptor)); + } + public boolean isData(@NotNull ClassDescriptor classDescriptor) { return containsAnnotation(classDescriptor, getDataClassAnnotation()); } diff --git a/generators/src/org/jetbrains/jet/generators/builtins/arrays.kt b/generators/src/org/jetbrains/jet/generators/builtins/arrays.kt index 5c55665edac..9ac46f55810 100644 --- a/generators/src/org/jetbrains/jet/generators/builtins/arrays.kt +++ b/generators/src/org/jetbrains/jet/generators/builtins/arrays.kt @@ -26,13 +26,15 @@ class GenerateArrays(out: PrintWriter) : BuiltInsSourceGenerator(out) { override fun generateBody() { for (kind in PrimitiveType.values()) { val s = kind.capitalized - out.println("public class ${s}Array(public val size: Int) {") + out.println("public class ${s}Array(public val size: Int) : Cloneable {") out.println(" public fun get(index: Int): $s") out.println(" public fun set(index: Int, value: $s): Unit") out.println() out.println(" public fun iterator(): ${s}Iterator") out.println() out.println(" public val indices: IntRange") + out.println() + out.println(" public override fun clone(): ${s}Array") out.println("}") out.println() } diff --git a/idea/testData/diagnosticMessage/conflictingSubstitutions1.html b/idea/testData/diagnosticMessage/conflictingSubstitutions1.html index ca36f85d8a8..f8038e2adc1 100644 --- a/idea/testData/diagnosticMessage/conflictingSubstitutions1.html +++ b/idea/testData/diagnosticMessage/conflictingSubstitutions1.html @@ -4,7 +4,7 @@ Type inference failed: Cannot infer type parameter T in - + diff --git a/idea/testData/diagnosticMessage/conflictingSubstitutions2.html b/idea/testData/diagnosticMessage/conflictingSubstitutions2.html index c1e2155fcac..2032183caa6 100644 --- a/idea/testData/diagnosticMessage/conflictingSubstitutions2.html +++ b/idea/testData/diagnosticMessage/conflictingSubstitutions2.html @@ -4,7 +4,7 @@ Type inference failed: Cannot infer type parameter T in
fun <`T, E : java.lang.Cloneable> writeToMyListfun <`T, E : kotlin.Cloneable> writeToMyList ( l: MyList<`in T>, t: T
- +
constructor Cons<`T, E : java.lang.Cloneable>constructor Cons<`T, E : kotlin.Cloneable> ( l: MyList<`in T>, t: T