From 035d6156a7662eca752ebb58536dcfbcec7a101d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 13 Oct 2016 11:53:18 +0300 Subject: [PATCH] Drop Cloneable in JS, synthesize it at compile-time on JVM Use the same approach that is used for creating function type classes (Function{0,1,...}) + add Cloneable to supertypes of Array and primitive arrays #KT-5537 Fixed --- .../resolve/jvm/platform/JvmPlatform.kt | 5 +- .../builtin-classes/default/kotlin.txt | 31 ++--- .../testData/builtin-classes/java6/kotlin.txt | 18 +-- .../testData/builtin-classes/java8/kotlin.txt | 18 +-- .../builtin-classes/newMethods/kotlin.txt | 18 +-- .../codegen/box/arrays/arraysAreCloneable.kt | 25 ++++ .../supertypes/builtInClassSupertypes.kt | 4 +- .../builtins/arraysAreCloneable.kt | 25 ++++ .../builtins/arraysAreCloneable.txt | 4 + .../ir/IrBlackBoxCodegenTestGenerated.java | 6 + .../DiagnosticsTestWithStdLibGenerated.java | 15 +++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 + core/builtins/native/kotlin/Array.kt | 7 +- core/builtins/native/kotlin/Arrays.kt | 32 ++--- core/builtins/native/kotlin/Cloneable.kt | 27 ---- .../kotlin/builtins/CloneableClassScope.kt | 90 +++++++++++++ .../JvmBuiltInClassDescriptorFactory.kt | 62 +++++++++ .../kotlin/load/kotlin/JvmBuiltInsSettings.kt | 120 +++++++++++------- .../jetbrains/kotlin/platform/JvmBuiltIns.kt | 4 + .../kotlin/builtins/KotlinBuiltIns.java | 13 +- .../kotlin/generators/builtins/arrays.kt | 4 +- .../navigation/findDecompiledDeclaration.kt | 7 +- .../basic/extensionFunForArray.kt | 4 +- .../basic/extensionFunForArray.kt.after | 4 +- 24 files changed, 376 insertions(+), 173 deletions(-) create mode 100644 compiler/testData/codegen/box/arrays/arraysAreCloneable.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/builtins/arraysAreCloneable.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/builtins/arraysAreCloneable.txt delete mode 100644 core/builtins/native/kotlin/Cloneable.kt create mode 100644 core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/CloneableClassScope.kt create mode 100644 core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/JvmBuiltInClassDescriptorFactory.kt diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatform.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatform.kt index 303cf9bfdef..7d18b8be21b 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatform.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatform.kt @@ -16,13 +16,14 @@ package org.jetbrains.kotlin.resolve.jvm.platform -import org.jetbrains.kotlin.builtins.DefaultBuiltIns +import org.jetbrains.kotlin.platform.JvmBuiltIns import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.ImportPath import org.jetbrains.kotlin.resolve.PlatformConfigurator import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.storage.LockBasedStorageManager import java.util.* object JvmPlatform : TargetPlatform("JVM") { @@ -39,7 +40,7 @@ object JvmPlatform : TargetPlatform("JVM") { } } - val builtIns = DefaultBuiltIns.Instance + val builtIns = JvmBuiltIns(LockBasedStorageManager.NO_LOCKS) for (builtinPackageFragment in builtIns.builtInsPackageFragments) { addAllClassifiersFromScope(builtinPackageFragment.getMemberScope()) } diff --git a/compiler/testData/builtin-classes/default/kotlin.txt b/compiler/testData/builtin-classes/default/kotlin.txt index 8164c551dea..6897bf0788f 100644 --- a/compiler/testData/builtin-classes/default/kotlin.txt +++ b/compiler/testData/builtin-classes/default/kotlin.txt @@ -21,11 +21,10 @@ public open class Any { /*primary*/ public constructor Any() } -public final class Array : kotlin.Cloneable { +public final class Array { public constructor Array(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> T) public final val size: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ fun clone(): kotlin.Array public final operator fun get(/*0*/ index: kotlin.Int): T public final operator fun iterator(): kotlin.collections.Iterator public final operator fun set(/*0*/ index: kotlin.Int, /*1*/ value: T): kotlin.Unit @@ -40,12 +39,11 @@ public final class Boolean : kotlin.Comparable { public final infix fun xor(/*0*/ other: kotlin.Boolean): kotlin.Boolean } -public final class BooleanArray : kotlin.Cloneable { +public final class BooleanArray { /*primary*/ public constructor BooleanArray(/*0*/ size: kotlin.Int) public constructor BooleanArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Boolean) public final val size: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ fun clone(): kotlin.BooleanArray public final operator fun get(/*0*/ index: kotlin.Int): kotlin.Boolean public final operator fun iterator(): kotlin.collections.BooleanIterator public final operator fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Boolean): kotlin.Unit @@ -114,12 +112,11 @@ public final class Byte : kotlin.Number, kotlin.Comparable { } } -public final class ByteArray : kotlin.Cloneable { +public final class ByteArray { /*primary*/ public constructor ByteArray(/*0*/ size: kotlin.Int) public constructor ByteArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Byte) public final val size: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ fun clone(): kotlin.ByteArray public final operator fun get(/*0*/ index: kotlin.Int): kotlin.Byte public final operator fun iterator(): kotlin.collections.ByteIterator public final operator fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Byte): kotlin.Unit @@ -159,12 +156,11 @@ public final class Char : kotlin.Comparable { } } -public final class CharArray : kotlin.Cloneable { +public final class CharArray { /*primary*/ public constructor CharArray(/*0*/ size: kotlin.Int) public constructor CharArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Char) public final val size: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ fun clone(): kotlin.CharArray public final operator fun get(/*0*/ index: kotlin.Int): kotlin.Char public final operator fun iterator(): kotlin.collections.CharIterator public final operator fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Char): kotlin.Unit @@ -177,10 +173,6 @@ public interface CharSequence { public abstract fun subSequence(/*0*/ startIndex: kotlin.Int, /*1*/ endIndex: kotlin.Int): kotlin.CharSequence } -public interface Cloneable { - protected open fun clone(): kotlin.Any -} - public interface Comparable { public abstract operator fun compareTo(/*0*/ other: T): kotlin.Int } @@ -280,12 +272,11 @@ public final class Double : kotlin.Number, kotlin.Comparable { } } -public final class DoubleArray : kotlin.Cloneable { +public final class DoubleArray { /*primary*/ public constructor DoubleArray(/*0*/ size: kotlin.Int) public constructor DoubleArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Double) public final val size: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ fun clone(): kotlin.DoubleArray public final operator fun get(/*0*/ index: kotlin.Int): kotlin.Double public final operator fun iterator(): kotlin.collections.DoubleIterator public final operator fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Double): kotlin.Unit @@ -374,12 +365,11 @@ public final class Float : kotlin.Number, kotlin.Comparable { } } -public final class FloatArray : kotlin.Cloneable { +public final class FloatArray { /*primary*/ public constructor FloatArray(/*0*/ size: kotlin.Int) public constructor FloatArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Float) public final val size: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ fun clone(): kotlin.FloatArray public final operator fun get(/*0*/ index: kotlin.Int): kotlin.Float public final operator fun iterator(): kotlin.collections.FloatIterator public final operator fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Float): kotlin.Unit @@ -458,12 +448,11 @@ public final class Int : kotlin.Number, kotlin.Comparable { } } -public final class IntArray : kotlin.Cloneable { +public final class IntArray { /*primary*/ public constructor IntArray(/*0*/ size: kotlin.Int) public constructor IntArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Int) public final val size: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ fun clone(): kotlin.IntArray public final operator fun get(/*0*/ index: kotlin.Int): kotlin.Int public final operator fun iterator(): kotlin.collections.IntIterator public final operator fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Int): kotlin.Unit @@ -539,12 +528,11 @@ public final class Long : kotlin.Number, kotlin.Comparable { } } -public final class LongArray : kotlin.Cloneable { +public final class LongArray { /*primary*/ public constructor LongArray(/*0*/ size: kotlin.Int) public constructor LongArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Long) public final val size: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ fun clone(): kotlin.LongArray public final operator fun get(/*0*/ index: kotlin.Int): kotlin.Long public final operator fun iterator(): kotlin.collections.LongIterator public final operator fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Long): kotlin.Unit @@ -642,12 +630,11 @@ public final class Short : kotlin.Number, kotlin.Comparable { } } -public final class ShortArray : kotlin.Cloneable { +public final class ShortArray { /*primary*/ public constructor ShortArray(/*0*/ size: kotlin.Int) public constructor ShortArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Short) public final val size: kotlin.Int public final fun (): kotlin.Int - public open override /*1*/ fun clone(): kotlin.ShortArray public final operator fun get(/*0*/ index: kotlin.Int): kotlin.Short public final operator fun iterator(): kotlin.collections.ShortIterator public final operator fun set(/*0*/ index: kotlin.Int, /*1*/ value: kotlin.Short): kotlin.Unit diff --git a/compiler/testData/builtin-classes/java6/kotlin.txt b/compiler/testData/builtin-classes/java6/kotlin.txt index 8f3f6916938..2e9bc8b559e 100644 --- a/compiler/testData/builtin-classes/java6/kotlin.txt +++ b/compiler/testData/builtin-classes/java6/kotlin.txt @@ -21,7 +21,7 @@ public open class Any { /*primary*/ public constructor Any() } -public final class Array : kotlin.Cloneable, java.io.Serializable { +public final class Array : kotlin.Any, kotlin.Cloneable, java.io.Serializable { public constructor Array(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> T) public final val size: kotlin.Int public final fun (): kotlin.Int @@ -40,7 +40,7 @@ public final class Boolean : kotlin.Comparable, java.io.Serializ public final infix fun xor(/*0*/ other: kotlin.Boolean): kotlin.Boolean } -public final class BooleanArray : kotlin.Cloneable, java.io.Serializable { +public final class BooleanArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor BooleanArray(/*0*/ size: kotlin.Int) public constructor BooleanArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Boolean) public final val size: kotlin.Int @@ -114,7 +114,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io } } -public final class ByteArray : kotlin.Cloneable, java.io.Serializable { +public final class ByteArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor ByteArray(/*0*/ size: kotlin.Int) public constructor ByteArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Byte) public final val size: kotlin.Int @@ -159,7 +159,7 @@ public final class Char : kotlin.Comparable, java.io.Serializable { } } -public final class CharArray : kotlin.Cloneable, java.io.Serializable { +public final class CharArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor CharArray(/*0*/ size: kotlin.Int) public constructor CharArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Char) public final val size: kotlin.Int @@ -282,7 +282,7 @@ public final class Double : kotlin.Number, kotlin.Comparable, jav } } -public final class DoubleArray : kotlin.Cloneable, java.io.Serializable { +public final class DoubleArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor DoubleArray(/*0*/ size: kotlin.Int) public constructor DoubleArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Double) public final val size: kotlin.Int @@ -378,7 +378,7 @@ public final class Float : kotlin.Number, kotlin.Comparable, java. } } -public final class FloatArray : kotlin.Cloneable, java.io.Serializable { +public final class FloatArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor FloatArray(/*0*/ size: kotlin.Int) public constructor FloatArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Float) public final val size: kotlin.Int @@ -462,7 +462,7 @@ public final class Int : kotlin.Number, kotlin.Comparable, java.io.S } } -public final class IntArray : kotlin.Cloneable, java.io.Serializable { +public final class IntArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor IntArray(/*0*/ size: kotlin.Int) public constructor IntArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Int) public final val size: kotlin.Int @@ -543,7 +543,7 @@ public final class Long : kotlin.Number, kotlin.Comparable, java.io } } -public final class LongArray : kotlin.Cloneable, java.io.Serializable { +public final class LongArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor LongArray(/*0*/ size: kotlin.Int) public constructor LongArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Long) public final val size: kotlin.Int @@ -646,7 +646,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. } } -public final class ShortArray : kotlin.Cloneable, java.io.Serializable { +public final class ShortArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor ShortArray(/*0*/ size: kotlin.Int) public constructor ShortArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Short) public final val size: kotlin.Int diff --git a/compiler/testData/builtin-classes/java8/kotlin.txt b/compiler/testData/builtin-classes/java8/kotlin.txt index 35c39569c54..f019d7a0d39 100644 --- a/compiler/testData/builtin-classes/java8/kotlin.txt +++ b/compiler/testData/builtin-classes/java8/kotlin.txt @@ -21,7 +21,7 @@ public open class Any { /*primary*/ public constructor Any() } -public final class Array : kotlin.Cloneable, java.io.Serializable { +public final class Array : kotlin.Any, kotlin.Cloneable, java.io.Serializable { public constructor Array(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> T) public final val size: kotlin.Int public final fun (): kotlin.Int @@ -40,7 +40,7 @@ public final class Boolean : kotlin.Comparable, java.io.Serializ public final infix fun xor(/*0*/ other: kotlin.Boolean): kotlin.Boolean } -public final class BooleanArray : kotlin.Cloneable, java.io.Serializable { +public final class BooleanArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor BooleanArray(/*0*/ size: kotlin.Int) public constructor BooleanArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Boolean) public final val size: kotlin.Int @@ -114,7 +114,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io } } -public final class ByteArray : kotlin.Cloneable, java.io.Serializable { +public final class ByteArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor ByteArray(/*0*/ size: kotlin.Int) public constructor ByteArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Byte) public final val size: kotlin.Int @@ -159,7 +159,7 @@ public final class Char : kotlin.Comparable, java.io.Serializable { } } -public final class CharArray : kotlin.Cloneable, java.io.Serializable { +public final class CharArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor CharArray(/*0*/ size: kotlin.Int) public constructor CharArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Char) public final val size: kotlin.Int @@ -284,7 +284,7 @@ public final class Double : kotlin.Number, kotlin.Comparable, jav } } -public final class DoubleArray : kotlin.Cloneable, java.io.Serializable { +public final class DoubleArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor DoubleArray(/*0*/ size: kotlin.Int) public constructor DoubleArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Double) public final val size: kotlin.Int @@ -380,7 +380,7 @@ public final class Float : kotlin.Number, kotlin.Comparable, java. } } -public final class FloatArray : kotlin.Cloneable, java.io.Serializable { +public final class FloatArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor FloatArray(/*0*/ size: kotlin.Int) public constructor FloatArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Float) public final val size: kotlin.Int @@ -464,7 +464,7 @@ public final class Int : kotlin.Number, kotlin.Comparable, java.io.S } } -public final class IntArray : kotlin.Cloneable, java.io.Serializable { +public final class IntArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor IntArray(/*0*/ size: kotlin.Int) public constructor IntArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Int) public final val size: kotlin.Int @@ -545,7 +545,7 @@ public final class Long : kotlin.Number, kotlin.Comparable, java.io } } -public final class LongArray : kotlin.Cloneable, java.io.Serializable { +public final class LongArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor LongArray(/*0*/ size: kotlin.Int) public constructor LongArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Long) public final val size: kotlin.Int @@ -648,7 +648,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. } } -public final class ShortArray : kotlin.Cloneable, java.io.Serializable { +public final class ShortArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor ShortArray(/*0*/ size: kotlin.Int) public constructor ShortArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Short) public final val size: kotlin.Int diff --git a/compiler/testData/builtin-classes/newMethods/kotlin.txt b/compiler/testData/builtin-classes/newMethods/kotlin.txt index 607d78f9a87..abdfdf6bf37 100644 --- a/compiler/testData/builtin-classes/newMethods/kotlin.txt +++ b/compiler/testData/builtin-classes/newMethods/kotlin.txt @@ -21,7 +21,7 @@ public open class Any { /*primary*/ public constructor Any() } -public final class Array : kotlin.Cloneable, java.io.Serializable { +public final class Array : kotlin.Any, kotlin.Cloneable, java.io.Serializable { public constructor Array(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> T) public final val size: kotlin.Int public final fun (): kotlin.Int @@ -40,7 +40,7 @@ public final class Boolean : kotlin.Comparable, java.io.Serializ public final infix fun xor(/*0*/ other: kotlin.Boolean): kotlin.Boolean } -public final class BooleanArray : kotlin.Cloneable, java.io.Serializable { +public final class BooleanArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor BooleanArray(/*0*/ size: kotlin.Int) public constructor BooleanArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Boolean) public final val size: kotlin.Int @@ -114,7 +114,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable, java.io } } -public final class ByteArray : kotlin.Cloneable, java.io.Serializable { +public final class ByteArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor ByteArray(/*0*/ size: kotlin.Int) public constructor ByteArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Byte) public final val size: kotlin.Int @@ -159,7 +159,7 @@ public final class Char : kotlin.Comparable, java.io.Serializable { } } -public final class CharArray : kotlin.Cloneable, java.io.Serializable { +public final class CharArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor CharArray(/*0*/ size: kotlin.Int) public constructor CharArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Char) public final val size: kotlin.Int @@ -282,7 +282,7 @@ public final class Double : kotlin.Number, kotlin.Comparable, jav } } -public final class DoubleArray : kotlin.Cloneable, java.io.Serializable { +public final class DoubleArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor DoubleArray(/*0*/ size: kotlin.Int) public constructor DoubleArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Double) public final val size: kotlin.Int @@ -378,7 +378,7 @@ public final class Float : kotlin.Number, kotlin.Comparable, java. } } -public final class FloatArray : kotlin.Cloneable, java.io.Serializable { +public final class FloatArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor FloatArray(/*0*/ size: kotlin.Int) public constructor FloatArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Float) public final val size: kotlin.Int @@ -462,7 +462,7 @@ public final class Int : kotlin.Number, kotlin.Comparable, java.io.S } } -public final class IntArray : kotlin.Cloneable, java.io.Serializable { +public final class IntArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor IntArray(/*0*/ size: kotlin.Int) public constructor IntArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Int) public final val size: kotlin.Int @@ -543,7 +543,7 @@ public final class Long : kotlin.Number, kotlin.Comparable, java.io } } -public final class LongArray : kotlin.Cloneable, java.io.Serializable { +public final class LongArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor LongArray(/*0*/ size: kotlin.Int) public constructor LongArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Long) public final val size: kotlin.Int @@ -646,7 +646,7 @@ public final class Short : kotlin.Number, kotlin.Comparable, java. } } -public final class ShortArray : kotlin.Cloneable, java.io.Serializable { +public final class ShortArray : kotlin.Any, kotlin.Cloneable, java.io.Serializable { /*primary*/ public constructor ShortArray(/*0*/ size: kotlin.Int) public constructor ShortArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Short) public final val size: kotlin.Int diff --git a/compiler/testData/codegen/box/arrays/arraysAreCloneable.kt b/compiler/testData/codegen/box/arrays/arraysAreCloneable.kt new file mode 100644 index 00000000000..b58bfa5765d --- /dev/null +++ b/compiler/testData/codegen/box/arrays/arraysAreCloneable.kt @@ -0,0 +1,25 @@ +fun foo(x: Cloneable) = x + +fun box(): String { + foo(arrayOf("")) + foo(intArrayOf()) + foo(longArrayOf()) + foo(shortArrayOf()) + foo(byteArrayOf()) + foo(charArrayOf()) + foo(doubleArrayOf()) + foo(floatArrayOf()) + foo(booleanArrayOf()) + + arrayOf("").clone() + intArrayOf().clone() + longArrayOf().clone() + shortArrayOf().clone() + byteArrayOf().clone() + charArrayOf().clone() + doubleArrayOf().clone() + floatArrayOf().clone() + booleanArrayOf().clone() + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/supertypes/builtInClassSupertypes.kt b/compiler/testData/codegen/box/reflection/supertypes/builtInClassSupertypes.kt index 5150914adea..bfadfc799a7 100644 --- a/compiler/testData/codegen/box/reflection/supertypes/builtInClassSupertypes.kt +++ b/compiler/testData/codegen/box/reflection/supertypes/builtInClassSupertypes.kt @@ -35,8 +35,8 @@ fun box(): String { check(::number, ::comparableOfInt, ::serializable) checkAll(::number, ::comparableOfInt, ::serializable, ::any) - check>(::cloneable, ::serializable) - checkAll>(::cloneable, ::serializable, ::any) + check>(::any, ::cloneable, ::serializable) + checkAll>(::any, ::cloneable, ::serializable) return "OK" } diff --git a/compiler/testData/diagnostics/testsWithStdLib/builtins/arraysAreCloneable.kt b/compiler/testData/diagnostics/testsWithStdLib/builtins/arraysAreCloneable.kt new file mode 100644 index 00000000000..8059c4900ae --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/builtins/arraysAreCloneable.kt @@ -0,0 +1,25 @@ +// !CHECK_TYPE + +fun foo(x: Cloneable) = x + +fun test() { + foo(arrayOf("")) + foo(intArrayOf()) + foo(longArrayOf()) + foo(shortArrayOf()) + foo(byteArrayOf()) + foo(charArrayOf()) + foo(doubleArrayOf()) + foo(floatArrayOf()) + foo(booleanArrayOf()) + + arrayOf("").clone() checkType { _>() } + intArrayOf().clone() checkType { _() } + longArrayOf().clone() checkType { _() } + shortArrayOf().clone() checkType { _() } + byteArrayOf().clone() checkType { _() } + charArrayOf().clone() checkType { _() } + doubleArrayOf().clone() checkType { _() } + floatArrayOf().clone() checkType { _() } + booleanArrayOf().clone() checkType { _() } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/builtins/arraysAreCloneable.txt b/compiler/testData/diagnostics/testsWithStdLib/builtins/arraysAreCloneable.txt new file mode 100644 index 00000000000..fa61e217610 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/builtins/arraysAreCloneable.txt @@ -0,0 +1,4 @@ +package + +public fun foo(/*0*/ x: kotlin.Cloneable): kotlin.Cloneable +public fun test(): kotlin.Unit diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 74363bd5e89..859beec20cb 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -298,6 +298,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("arraysAreCloneable.kt") + public void testArraysAreCloneable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arraysAreCloneable.kt"); + doTest(fileName); + } + @TestMetadata("cloneArray.kt") public void testCloneArray() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/cloneArray.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 12ccf2c41fc..89ad6077186 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -656,6 +656,21 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW } } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/builtins") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Builtins extends AbstractDiagnosticsTestWithStdLib { + public void testAllFilesPresentInBuiltins() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/builtins"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("arraysAreCloneable.kt") + public void testArraysAreCloneable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/builtins/arraysAreCloneable.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/testsWithStdLib/cast") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 787fdade409..a8b3e0a685b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -298,6 +298,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("arraysAreCloneable.kt") + public void testArraysAreCloneable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/arraysAreCloneable.kt"); + doTest(fileName); + } + @TestMetadata("cloneArray.kt") public void testCloneArray() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/cloneArray.kt"); diff --git a/core/builtins/native/kotlin/Array.kt b/core/builtins/native/kotlin/Array.kt index ec7b9191508..e17b97b0b34 100644 --- a/core/builtins/native/kotlin/Array.kt +++ b/core/builtins/native/kotlin/Array.kt @@ -23,7 +23,7 @@ package kotlin * See [Kotlin language documentation](http://kotlinlang.org/docs/reference/basic-types.html#arrays) * for more information on arrays. */ -public class Array : Cloneable { +public class Array { /** * Creates a new array with the specified [size], where each element is calculated by calling the specified * [init] function. The [init] function returns an array element given its index. @@ -57,9 +57,4 @@ public class Array : Cloneable { * Creates an iterator for iterating over the elements of the array. */ public operator fun iterator(): Iterator - - /** - * Creates a shallow copy of the array. - */ - public override fun clone(): Array } diff --git a/core/builtins/native/kotlin/Arrays.kt b/core/builtins/native/kotlin/Arrays.kt index 4d889cde5a5..0e35139a7b2 100644 --- a/core/builtins/native/kotlin/Arrays.kt +++ b/core/builtins/native/kotlin/Arrays.kt @@ -22,7 +22,7 @@ package kotlin * An array of bytes. When targeting the JVM, instances of this class are represented as `byte[]`. * @constructor Creates a new array of the specified [size], with all elements initialized to zero. */ -public class ByteArray(size: Int) : Cloneable { +public class ByteArray(size: Int) { /** * Creates a new array of the specified [size], where each element is calculated by calling the specified * [init] function. The [init] function returns an array element given its index. @@ -39,15 +39,13 @@ public class ByteArray(size: Int) : Cloneable { /** Creates an iterator over the elements of the array. */ public operator fun iterator(): ByteIterator - - public override fun clone(): ByteArray } /** * An array of chars. When targeting the JVM, instances of this class are represented as `char[]`. * @constructor Creates a new array of the specified [size], with all elements initialized to zero. */ -public class CharArray(size: Int) : Cloneable { +public class CharArray(size: Int) { /** * Creates a new array of the specified [size], where each element is calculated by calling the specified * [init] function. The [init] function returns an array element given its index. @@ -64,15 +62,13 @@ public class CharArray(size: Int) : Cloneable { /** Creates an iterator over the elements of the array. */ public operator fun iterator(): CharIterator - - public override fun clone(): CharArray } /** * An array of shorts. When targeting the JVM, instances of this class are represented as `short[]`. * @constructor Creates a new array of the specified [size], with all elements initialized to zero. */ -public class ShortArray(size: Int) : Cloneable { +public class ShortArray(size: Int) { /** * Creates a new array of the specified [size], where each element is calculated by calling the specified * [init] function. The [init] function returns an array element given its index. @@ -89,15 +85,13 @@ public class ShortArray(size: Int) : Cloneable { /** Creates an iterator over the elements of the array. */ public operator fun iterator(): ShortIterator - - public override fun clone(): ShortArray } /** * An array of ints. When targeting the JVM, instances of this class are represented as `int[]`. * @constructor Creates a new array of the specified [size], with all elements initialized to zero. */ -public class IntArray(size: Int) : Cloneable { +public class IntArray(size: Int) { /** * Creates a new array of the specified [size], where each element is calculated by calling the specified * [init] function. The [init] function returns an array element given its index. @@ -114,15 +108,13 @@ public class IntArray(size: Int) : Cloneable { /** Creates an iterator over the elements of the array. */ public operator fun iterator(): IntIterator - - public override fun clone(): IntArray } /** * An array of longs. When targeting the JVM, instances of this class are represented as `long[]`. * @constructor Creates a new array of the specified [size], with all elements initialized to zero. */ -public class LongArray(size: Int) : Cloneable { +public class LongArray(size: Int) { /** * Creates a new array of the specified [size], where each element is calculated by calling the specified * [init] function. The [init] function returns an array element given its index. @@ -139,15 +131,13 @@ public class LongArray(size: Int) : Cloneable { /** Creates an iterator over the elements of the array. */ public operator fun iterator(): LongIterator - - public override fun clone(): LongArray } /** * An array of floats. When targeting the JVM, instances of this class are represented as `float[]`. * @constructor Creates a new array of the specified [size], with all elements initialized to zero. */ -public class FloatArray(size: Int) : Cloneable { +public class FloatArray(size: Int) { /** * Creates a new array of the specified [size], where each element is calculated by calling the specified * [init] function. The [init] function returns an array element given its index. @@ -164,15 +154,13 @@ public class FloatArray(size: Int) : Cloneable { /** Creates an iterator over the elements of the array. */ public operator fun iterator(): FloatIterator - - public override fun clone(): FloatArray } /** * An array of doubles. When targeting the JVM, instances of this class are represented as `double[]`. * @constructor Creates a new array of the specified [size], with all elements initialized to zero. */ -public class DoubleArray(size: Int) : Cloneable { +public class DoubleArray(size: Int) { /** * Creates a new array of the specified [size], where each element is calculated by calling the specified * [init] function. The [init] function returns an array element given its index. @@ -189,15 +177,13 @@ public class DoubleArray(size: Int) : Cloneable { /** Creates an iterator over the elements of the array. */ public operator fun iterator(): DoubleIterator - - public override fun clone(): DoubleArray } /** * An array of booleans. When targeting the JVM, instances of this class are represented as `boolean[]`. * @constructor Creates a new array of the specified [size], with all elements initialized to false. */ -public class BooleanArray(size: Int) : Cloneable { +public class BooleanArray(size: Int) { /** * Creates a new array of the specified [size], where each element is calculated by calling the specified * [init] function. The [init] function returns an array element given its index. @@ -214,7 +200,5 @@ public class BooleanArray(size: Int) : Cloneable { /** Creates an iterator over the elements of the array. */ public operator fun iterator(): BooleanIterator - - public override fun clone(): BooleanArray } diff --git a/core/builtins/native/kotlin/Cloneable.kt b/core/builtins/native/kotlin/Cloneable.kt deleted file mode 100644 index 7588573eae8..00000000000 --- a/core/builtins/native/kotlin/Cloneable.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2010-2015 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 - -/** - * Classes that inherit from this interface support creating field-by-field copies of their instances. - */ -public interface Cloneable { - /** - * Creates and returns a field-by-field copy of this object. - */ - protected fun clone(): Any { /* intrinsic */ } -} diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/CloneableClassScope.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/CloneableClassScope.kt new file mode 100644 index 00000000000..7686595177e --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/CloneableClassScope.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2016 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.kotlin.builtins + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl +import org.jetbrains.kotlin.incremental.components.LookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy +import org.jetbrains.kotlin.resolve.OverridingUtil +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl +import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.storage.getValue +import org.jetbrains.kotlin.utils.Printer +import java.util.* + +class CloneableClassScope(storageManager: StorageManager, private val classDescriptor: ClassDescriptor) : MemberScopeImpl() { + private val allDescriptors by storageManager.createLazyValue { + val cloneFunction = + SimpleFunctionDescriptorImpl.create(classDescriptor, Annotations.EMPTY, CLONE_NAME, DECLARATION, SourceElement.NO_SOURCE) + cloneFunction.initialize(null, classDescriptor.thisAsReceiverParameter, emptyList(), emptyList(), classDescriptor.builtIns.anyType, + Modality.OPEN, Visibilities.PROTECTED) + + listOf(cloneFunction) + createFakeOverrides() + } + + private val functionNames = setOf(CLONE_NAME) + classDescriptor.builtIns.anyType.memberScope.getFunctionNames() + + override fun getContributedFunctions(name: Name, location: LookupLocation): Collection = + if (name in functionNames) allDescriptors.filter { it.name == name } else emptySet() + + override fun getContributedDescriptors( + kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean + ): Collection = allDescriptors + + override fun getFunctionNames(): Set = functionNames + + private fun createFakeOverrides(): List { + val result = ArrayList(3) + val allSuperDescriptors = classDescriptor.typeConstructor.supertypes + .flatMap { it.memberScope.getContributedDescriptors() } + .filterIsInstance() + for ((name, descriptors) in allSuperDescriptors.groupBy { it.name }) { + OverridingUtil.generateOverridesInFunctionGroup( + name, + /* membersFromSupertypes = */ descriptors, + /* membersFromCurrent = */ emptyList(), + classDescriptor, + object : NonReportingOverrideStrategy() { + override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) { + OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, null) + result.add(fakeOverride as SimpleFunctionDescriptor) + } + + override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) { + error("Conflict in scope of $classDescriptor: $fromSuper vs $fromCurrent") + } + } + ) + } + + return result + } + + override fun printScopeStructure(p: Printer) { + p.println("kotlin.Cloneable member scope") + } + + companion object { + internal val CLONE_NAME = Name.identifier("clone") + } +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/JvmBuiltInClassDescriptorFactory.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/JvmBuiltInClassDescriptorFactory.kt new file mode 100644 index 00000000000..7f0f9763bb7 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/builtins/JvmBuiltInClassDescriptorFactory.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2016 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.kotlin.builtins + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory +import org.jetbrains.kotlin.storage.StorageManager +import org.jetbrains.kotlin.storage.getValue + +class JvmBuiltInClassDescriptorFactory( + storageManager: StorageManager, + private val moduleDescriptor: ModuleDescriptor +) : ClassDescriptorFactory { + private val cloneable by storageManager.createLazyValue { + ClassDescriptorImpl( + moduleDescriptor.getPackage(KOTLIN_FQ_NAME).fragments.single(), + CLONEABLE_NAME, Modality.ABSTRACT, ClassKind.INTERFACE, listOf(moduleDescriptor.builtIns.anyType), + SourceElement.NO_SOURCE + ).apply { + initialize(CloneableClassScope(storageManager, this), emptySet(), null) + } + } + + override fun shouldCreateClass(packageFqName: FqName, name: Name): Boolean = + name == CLONEABLE_NAME && packageFqName == KOTLIN_FQ_NAME + + override fun createClass(classId: ClassId): ClassDescriptor? = + when (classId) { + CLONEABLE_CLASS_ID -> cloneable + else -> null + } + + override fun getAllContributedClassesIfPossible(packageFqName: FqName): Collection = + when (packageFqName) { + KOTLIN_FQ_NAME -> setOf(cloneable) + else -> emptySet() + } + + companion object { + private val KOTLIN_FQ_NAME = KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME + private val CLONEABLE_NAME = KotlinBuiltIns.FQ_NAMES.cloneable.shortName() + val CLONEABLE_CLASS_ID = ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.cloneable.toSafe()) + } +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt index 0437e9c3fa4..87b3875a686 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt @@ -17,6 +17,8 @@ package org.jetbrains.kotlin.load.kotlin import org.jetbrains.kotlin.builtins.BuiltInsInitializer +import org.jetbrains.kotlin.builtins.CloneableClassScope +import org.jetbrains.kotlin.builtins.JvmBuiltInClassDescriptorFactory import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl @@ -28,6 +30,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.load.java.components.JavaResolverCache import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaClassDescriptor import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.platform.createMappedTypeParametersSubstitution @@ -65,6 +68,9 @@ open class JvmBuiltInsSettings( private val isAdditionalBuiltInsFeatureSupported: Boolean by lazy(isAdditionalBuiltInsFeatureSupported) private val mockSerializableType = storageManager.createMockJavaIoSerializableType() + private val cloneableType by storageManager.createLazyValue { + moduleDescriptor.builtIns.getBuiltInClassByName(JvmBuiltInClassDescriptorFactory.CLONEABLE_CLASS_ID.shortClassName).defaultType + } private val javaAnalogueClassesWithCustomSupertypeCache = storageManager.createCacheWithNotNullValues() @@ -114,58 +120,66 @@ open class JvmBuiltInsSettings( } override fun getSupertypes(classDescriptor: DeserializedClassDescriptor): Collection { - if (isSerializableInJava(classDescriptor.fqNameSafe)) { - return listOf(mockSerializableType) + val fqName = classDescriptor.fqNameUnsafe + return when { + isArrayOrPrimitiveArray(fqName) -> listOf(cloneableType, mockSerializableType) + isSerializableInJava(fqName) -> listOf(mockSerializableType) + else -> listOf() } - else return listOf() } - override fun getFunctions(name: Name, classDescriptor: DeserializedClassDescriptor): Collection = - getAdditionalFunctions(classDescriptor) { - it.getContributedFunctions(name, NoLookupLocation.FROM_BUILTINS) - } - .mapNotNull { - additionalMember -> - val substitutedWithKotlinTypeParameters = - additionalMember.substitute( - createMappedTypeParametersSubstitution( - additionalMember.containingDeclaration as ClassDescriptor, classDescriptor).buildSubstitutor() - ) as SimpleFunctionDescriptor + override fun getFunctions(name: Name, classDescriptor: DeserializedClassDescriptor): Collection { + if (name == CloneableClassScope.CLONE_NAME && KotlinBuiltIns.isArrayOrPrimitiveArray(classDescriptor)) { + return listOf(createCloneForArray( + classDescriptor, cloneableType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BUILTINS).single() + )) + } - substitutedWithKotlinTypeParameters.newCopyBuilder().apply { - setOwner(classDescriptor) - setDispatchReceiverParameter(classDescriptor.thisAsReceiverParameter) - setPreserveSourceElement() - setSubstitution(UnsafeVarianceTypeSubstitution(moduleDescriptor.builtIns)) + return getAdditionalFunctions(classDescriptor) { + it.getContributedFunctions(name, NoLookupLocation.FROM_BUILTINS) + }.mapNotNull { + additionalMember -> + val substitutedWithKotlinTypeParameters = + additionalMember.substitute( + createMappedTypeParametersSubstitution( + additionalMember.containingDeclaration as ClassDescriptor, classDescriptor).buildSubstitutor() + ) as SimpleFunctionDescriptor - val memberStatus = additionalMember.getJdkMethodStatus() - when (memberStatus) { - JDKMemberStatus.BLACK_LIST -> { - // Black list methods in final class can't be overridden or called with 'super' - if (classDescriptor.isFinalClass) return@mapNotNull null - setHiddenForResolutionEverywhereBesideSupercalls() + substitutedWithKotlinTypeParameters.newCopyBuilder().apply { + setOwner(classDescriptor) + setDispatchReceiverParameter(classDescriptor.thisAsReceiverParameter) + setPreserveSourceElement() + setSubstitution(UnsafeVarianceTypeSubstitution(moduleDescriptor.builtIns)) + + val memberStatus = additionalMember.getJdkMethodStatus() + when (memberStatus) { + JDKMemberStatus.BLACK_LIST -> { + // Black list methods in final class can't be overridden or called with 'super' + if (classDescriptor.isFinalClass) return@mapNotNull null + setHiddenForResolutionEverywhereBesideSupercalls() + } + + JDKMemberStatus.NOT_CONSIDERED -> { + if (!isAdditionalBuiltInsFeatureSupported) { + setAdditionalAnnotations(notSupportedDeprecation) } - - JDKMemberStatus.NOT_CONSIDERED -> { - if (!isAdditionalBuiltInsFeatureSupported) { - setAdditionalAnnotations(notSupportedDeprecation) - } - else { - setAdditionalAnnotations(notConsideredDeprecation) - } - } - - JDKMemberStatus.DROP -> return@mapNotNull null - - JDKMemberStatus.WHITE_LIST -> { - if (!isAdditionalBuiltInsFeatureSupported) { - setAdditionalAnnotations(notSupportedDeprecation) - } + else { + setAdditionalAnnotations(notConsideredDeprecation) } } - }.build()!! - } + JDKMemberStatus.DROP -> return@mapNotNull null + + JDKMemberStatus.WHITE_LIST -> { + if (!isAdditionalBuiltInsFeatureSupported) { + setAdditionalAnnotations(notSupportedDeprecation) + } + } + } + + }.build()!! + } + } override fun getFunctionsNames(classDescriptor: DeserializedClassDescriptor): Set = // NB: It's just an approximation that could be calculated relatively fast @@ -206,6 +220,15 @@ open class JvmBuiltInsSettings( } } + private fun createCloneForArray( + arrayClassDescriptor: DeserializedClassDescriptor, + cloneFromCloneable: SimpleFunctionDescriptor + ): SimpleFunctionDescriptor = cloneFromCloneable.newCopyBuilder().apply { + setOwner(arrayClassDescriptor) + setVisibility(Visibilities.PUBLIC) + setReturnType(arrayClassDescriptor.defaultType) + }.build()!! + private fun SimpleFunctionDescriptor.isMutabilityViolation(isMutable: Boolean): Boolean { val owner = containingDeclaration as ClassDescriptor val jvmDescriptor = computeJvmDescriptor() @@ -323,12 +346,11 @@ open class JvmBuiltInsSettings( valueParameters.single().type.constructor.declarationDescriptor?.fqNameUnsafe == classDescriptor.fqNameUnsafe companion object { - fun isSerializableInJava(classFqName: FqName): Boolean { - val fqNameUnsafe = classFqName.toUnsafe() - if (fqNameUnsafe == KotlinBuiltIns.FQ_NAMES.array || KotlinBuiltIns.isPrimitiveArray(fqNameUnsafe)) { + fun isSerializableInJava(fqName: FqNameUnsafe): Boolean { + if (isArrayOrPrimitiveArray(fqName)) { return true } - val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqNameUnsafe) ?: return false + val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(fqName) ?: return false val classViaReflection = try { Class.forName(javaClassId.asSingleFqName().asString()) } @@ -338,6 +360,10 @@ open class JvmBuiltInsSettings( return Serializable::class.java.isAssignableFrom(classViaReflection) } + private fun isArrayOrPrimitiveArray(fqName: FqNameUnsafe): Boolean { + return fqName == KotlinBuiltIns.FQ_NAMES.array || KotlinBuiltIns.isPrimitiveArray(fqName) + } + val DROP_LIST_METHOD_SIGNATURES: Set = SignatureBuildingComponents.inJavaUtil( "Collection", diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt index b164eaf4987..25a971a2a61 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/platform/JvmBuiltIns.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.platform +import org.jetbrains.kotlin.builtins.JvmBuiltInClassDescriptorFactory import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.load.kotlin.JvmBuiltInsSettings @@ -49,4 +50,7 @@ class JvmBuiltIns(storageManager: StorageManager) : KotlinBuiltIns(storageManage } override fun getAdditionalClassPartsProvider() = settings + + override fun getClassDescriptorFactories() = + super.getClassDescriptorFactories() + JvmBuiltInClassDescriptorFactory(storageManager, builtInsModule) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java index d491af86cb8..4daac83d303 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.scopes.MemberScope; import org.jetbrains.kotlin.serialization.deserialization.AdditionalClassPartsProvider; +import org.jetbrains.kotlin.serialization.deserialization.ClassDescriptorFactory; import org.jetbrains.kotlin.serialization.deserialization.PlatformDependentDeclarationFilter; import org.jetbrains.kotlin.storage.StorageManager; import org.jetbrains.kotlin.types.*; @@ -86,7 +87,7 @@ public abstract class KotlinBuiltIns { PackageFragmentProvider packageFragmentProvider = BuiltInsPackageFragmentProviderKt.createBuiltInPackageFragmentProvider( storageManager, builtInsModule, BUILT_INS_PACKAGE_FQ_NAMES, - Collections.singletonList(new BuiltInFictitiousFunctionClassFactory(storageManager, builtInsModule)), + getClassDescriptorFactories(), getPlatformDependentDeclarationFilter(), getAdditionalClassPartsProvider(), new Function1() { @@ -129,6 +130,11 @@ public abstract class KotlinBuiltIns { return PlatformDependentDeclarationFilter.NoPlatformDependent.INSTANCE; } + @NotNull + protected Iterable getClassDescriptorFactories() { + return Collections.singletonList(new BuiltInFictitiousFunctionClassFactory(storageManager, builtInsModule)); + } + private void makePrimitive(@NotNull PrimitiveType primitiveType) { SimpleType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString()); SimpleType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString()); @@ -443,11 +449,6 @@ public abstract class KotlinBuiltIns { return getBuiltInClassByName("Throwable"); } - @NotNull - public ClassDescriptor getCloneable() { - return getBuiltInClassByName("Cloneable"); - } - @NotNull public ClassDescriptor getDeprecatedAnnotation() { return getBuiltInClassByName(FQ_NAMES.deprecated.shortName()); diff --git a/generators/src/org/jetbrains/kotlin/generators/builtins/arrays.kt b/generators/src/org/jetbrains/kotlin/generators/builtins/arrays.kt index aa95a049474..f914e305f21 100644 --- a/generators/src/org/jetbrains/kotlin/generators/builtins/arrays.kt +++ b/generators/src/org/jetbrains/kotlin/generators/builtins/arrays.kt @@ -32,7 +32,7 @@ class GenerateArrays(out: PrintWriter) : BuiltInsSourceGenerator(out) { out.println(" * An array of ${typeLower}s. When targeting the JVM, instances of this class are represented as `$typeLower[]`.") out.println(" * @constructor Creates a new array of the specified [size], with all elements initialized to $defaultValue.") out.println(" */") - out.println("public class ${s}Array(size: Int) : Cloneable {") + out.println("public class ${s}Array(size: Int) {") out.println(" /**") out.println(" * Creates a new array of the specified [size], where each element is calculated by calling the specified") out.println(" * [init] function. The [init] function returns an array element given its index.") @@ -49,8 +49,6 @@ class GenerateArrays(out: PrintWriter) : BuiltInsSourceGenerator(out) { out.println() out.println(" /** Creates an iterator over the elements of the array. */") out.println(" public operator fun iterator(): ${s}Iterator") - out.println() - out.println(" public override fun clone(): ${s}Array") out.println("}") out.println() } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/findDecompiledDeclaration.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/findDecompiledDeclaration.kt index bd787b091d4..597d3f30603 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/findDecompiledDeclaration.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/navigation/findDecompiledDeclaration.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRendererModifier import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass import org.jetbrains.kotlin.types.ErrorUtils @@ -150,9 +151,10 @@ object ByDescriptorIndexer : DecompiledTextIndexer { return file.getDeclaration(this, original.toStringKey()) ?: run { if (descriptor !is ClassDescriptor) return null - val classFqName = descriptor.fqNameSafe + val classFqName = descriptor.fqNameUnsafe if (JvmBuiltInsSettings.isSerializableInJava(classFqName)) { - val builtInDescriptor = DefaultBuiltIns.Instance.builtInsModule.resolveTopLevelClass(classFqName, NoLookupLocation.FROM_IDE) + val builtInDescriptor = + DefaultBuiltIns.Instance.builtInsModule.resolveTopLevelClass(classFqName.toSafe(), NoLookupLocation.FROM_IDE) return builtInDescriptor?.let { file.getDeclaration(this, it.toStringKey()) } } return null @@ -168,4 +170,3 @@ object ByDescriptorIndexer : DecompiledTextIndexer { withDefinedIn = true } } - diff --git a/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt b/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt index 4fd8c1f91c3..1232eda632d 100644 --- a/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt +++ b/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt @@ -1,6 +1,6 @@ -// PARAM_TYPES: kotlin.Array, kotlin.Cloneable, java.io.Serializable, kotlin.Any +// PARAM_TYPES: kotlin.Array, kotlin.Any, kotlin.Cloneable, java.io.Serializable // PARAM_DESCRIPTOR: public fun kotlin.Array.test(): kotlin.Unit defined in root package // SIBLING: fun Array.test() { this.isEmpty() -} \ No newline at end of file +} diff --git a/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt.after b/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt.after index d52f422ff13..bec7278d3a8 100644 --- a/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt.after +++ b/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt.after @@ -1,4 +1,4 @@ -// PARAM_TYPES: kotlin.Array, kotlin.Cloneable, java.io.Serializable, kotlin.Any +// PARAM_TYPES: kotlin.Array, kotlin.Any, kotlin.Cloneable, java.io.Serializable // PARAM_DESCRIPTOR: public fun kotlin.Array.test(): kotlin.Unit defined in root package // SIBLING: fun Array.test() { @@ -7,4 +7,4 @@ fun Array.test() { private fun Array.__dummyTestFun__() { this.isEmpty() -} \ No newline at end of file +}