From a25f23a286fba8fc2cd75d313e0e77875eb9ab8f Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Sun, 22 Nov 2015 20:55:54 +0300 Subject: [PATCH] Apply @OnlyInputTypes on type parameter for contains, indexOf, lastIndexOf extensions for Iterables, Sequences and Arrays instead of @NoInfer on element parameter. Provide covariant extensions annotated with @OnlyInputTypes: - Collection: containsAll(Collection), - MutableCollection: remove(T), removeAll, retainAll (Collection), - List: indexOf(T), lastIndexOf(T) - Map: get(K), containsKey(K), contains(K) - Map: containsValue(V) - MutableMap: remove(K) All *Raw extensions are deprecated. --- libraries/stdlib/src/generated/_Arrays.kt | 27 +++--- .../stdlib/src/generated/_Collections.kt | 29 +++--- libraries/stdlib/src/generated/_Sequences.kt | 27 +++--- .../stdlib/src/kotlin/collections/Maps.kt | 34 +++++-- .../kotlin/collections/MutableCollections.kt | 95 ++++++++++++++----- .../src/templates/Elements.kt | 18 ++-- .../src/templates/engine/Engine.kt | 11 ++- 7 files changed, 161 insertions(+), 80 deletions(-) diff --git a/libraries/stdlib/src/generated/_Arrays.kt b/libraries/stdlib/src/generated/_Arrays.kt index e540edc3e9c..f2e94aae0b1 100644 --- a/libraries/stdlib/src/generated/_Arrays.kt +++ b/libraries/stdlib/src/generated/_Arrays.kt @@ -375,7 +375,7 @@ public inline operator fun ShortArray.component5(): Short { /** * Returns `true` if [element] is found in the array. */ -public operator fun Array.contains(element: @kotlin.internal.NoInfer T): Boolean { +public operator fun <@kotlin.internal.OnlyInputTypes T> Array.contains(element: T): Boolean { return indexOf(element) >= 0 } @@ -438,20 +438,21 @@ public operator fun ShortArray.contains(element: Short): Boolean { /** * Returns `true` if [element] is found in the collection. */ -@Deprecated("Use 'containsRaw' instead.", ReplaceWith("containsRaw(element)")) +@Deprecated("Array and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("contains(element as Any?)")) @kotlin.jvm.JvmName("containsAny") @kotlin.internal.LowPriorityInOverloadResolution public operator fun Array.contains(element: T): Boolean { - return containsRaw(element) + return contains(element as Any?) } /** * Returns `true` if [element] is found in the array. * Allows to overcome type-safety restriction of `contains` that requires to pass an element of type `T`. */ +@Deprecated("Array and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("contains(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun Array.containsRaw(element: Any?): Boolean { - return contains(element) + return contains(element as Any?) } /** @@ -1204,7 +1205,7 @@ public fun ShortArray.getOrNull(index: Int): Short? { /** * Returns first index of [element], or -1 if the array does not contain element. */ -public fun Array.indexOf(element: @kotlin.internal.NoInfer T): Int { +public fun <@kotlin.internal.OnlyInputTypes T> Array.indexOf(element: T): Int { if (element == null) { for (index in indices) { if (this[index] == null) { @@ -1320,12 +1321,12 @@ public fun ShortArray.indexOf(element: Short): Int { /** * Returns first index of [element], or -1 if the collection does not contain element. */ -@Deprecated("Use 'indexOfRaw' instead.", ReplaceWith("indexOfRaw(element)")) +@Deprecated("Array and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("indexOf(element as Any?)")) @kotlin.jvm.JvmName("indexOfAny") @kotlin.internal.LowPriorityInOverloadResolution @Suppress("NOTHING_TO_INLINE") public fun Array.indexOf(element: T): Int { - return indexOfRaw(element) + return indexOf(element as Any?) } /** @@ -1548,9 +1549,10 @@ public inline fun ShortArray.indexOfLast(predicate: (Short) -> Boolean): Int { * Returns first index of [element], or -1 if the array does not contain element. * Allows to overcome type-safety restriction of `indexOf` that requires to pass an element of type `T`. */ +@Deprecated("Array and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("indexOf(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun Array.indexOfRaw(element: Any?): Int { - return indexOf(element) + return indexOf(element as Any?) } /** @@ -1754,7 +1756,7 @@ public inline fun ShortArray.last(predicate: (Short) -> Boolean): Short { /** * Returns last index of [element], or -1 if the array does not contain element. */ -public fun Array.lastIndexOf(element: @kotlin.internal.NoInfer T): Int { +public fun <@kotlin.internal.OnlyInputTypes T> Array.lastIndexOf(element: T): Int { if (element == null) { for (index in indices.reversed()) { if (this[index] == null) { @@ -1870,21 +1872,22 @@ public fun ShortArray.lastIndexOf(element: Short): Int { /** * Returns last index of [element], or -1 if the collection does not contain element. */ -@Deprecated("Use 'indexOfRaw' instead.", ReplaceWith("indexOfRaw(element)")) +@Deprecated("Array and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("lastIndexOf(element as Any?)")) @kotlin.jvm.JvmName("lastIndexOfAny") @kotlin.internal.LowPriorityInOverloadResolution @Suppress("NOTHING_TO_INLINE") public fun Array.lastIndexOf(element: T): Int { - return indexOfRaw(element) + return lastIndexOf(element as Any?) } /** * Returns last index of [element], or -1 if the array does not contain element. * Allows to overcome type-safety restriction of `lastIndexOf` that requires to pass an element of type `T`. */ +@Deprecated("Array and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("lastIndexOf(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun Array.lastIndexOfRaw(element: Any?): Int { - return lastIndexOf(element) + return lastIndexOf(element as Any?) } /** diff --git a/libraries/stdlib/src/generated/_Collections.kt b/libraries/stdlib/src/generated/_Collections.kt index 9cc280ce8ea..5fcbdcd0012 100644 --- a/libraries/stdlib/src/generated/_Collections.kt +++ b/libraries/stdlib/src/generated/_Collections.kt @@ -55,7 +55,7 @@ public inline operator fun List.component5(): T { /** * Returns `true` if [element] is found in the collection. */ -public operator fun Iterable.contains(element: @kotlin.internal.NoInfer T): Boolean { +public operator fun <@kotlin.internal.OnlyInputTypes T> Iterable.contains(element: T): Boolean { if (this is Collection) return contains(element) return indexOf(element) >= 0 @@ -64,20 +64,21 @@ public operator fun Iterable.contains(element: @kotlin.internal.NoInfer T /** * Returns `true` if [element] is found in the collection. */ -@Deprecated("Use 'containsRaw' instead.", ReplaceWith("containsRaw(element)")) +@Deprecated("Collection and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("contains(element as Any?)")) @kotlin.jvm.JvmName("containsAny") @kotlin.internal.LowPriorityInOverloadResolution public operator fun Iterable.contains(element: T): Boolean { - return containsRaw(element) + return contains(element as Any?) } /** * Returns `true` if [element] is found in the collection. * Allows to overcome type-safety restriction of `contains` that requires to pass an element of type `T`. */ +@Deprecated("Collection and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("contains(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun Iterable<*>.containsRaw(element: Any?): Boolean { - return contains(element) + return contains(element as Any?) } /** @@ -259,7 +260,7 @@ public fun List.getOrNull(index: Int): T? { /** * Returns first index of [element], or -1 if the collection does not contain element. */ -public fun Iterable.indexOf(element: @kotlin.internal.NoInfer T): Int { +public fun <@kotlin.internal.OnlyInputTypes T> Iterable.indexOf(element: T): Int { if (this is List) return this.indexOf(element) var index = 0 for (item in this) { @@ -273,12 +274,12 @@ public fun Iterable.indexOf(element: @kotlin.internal.NoInfer T): Int { /** * Returns first index of [element], or -1 if the collection does not contain element. */ -@Deprecated("Use 'indexOfRaw' instead.", ReplaceWith("indexOfRaw(element)")) +@Deprecated("Collection and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("indexOf(element as Any?)")) @kotlin.jvm.JvmName("indexOfAny") @kotlin.internal.LowPriorityInOverloadResolution @Suppress("NOTHING_TO_INLINE") public fun Iterable.indexOf(element: T): Int { - return indexOfRaw(element) + return indexOf(element as Any?) } /** @@ -336,15 +337,17 @@ public inline fun List.indexOfLast(predicate: (T) -> Boolean): Int { * Returns first index of [element], or -1 if the collection does not contain element. * Allows to overcome type-safety restriction of `indexOf` that requires to pass an element of type `T`. */ +@Deprecated("Collection and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("indexOf(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun Iterable<*>.indexOfRaw(element: Any?): Int { - return indexOf(element) + return indexOf(element as Any?) } /** * Returns first index of [element], or -1 if the list does not contain element. * Allows to overcome type-safety restriction of `indexOf` that requires to pass an element of type `T`. */ +@Deprecated("List and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("indexOf(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun List.indexOfRaw(element: Any?): Int { return (this as List).indexOf(element) @@ -418,7 +421,7 @@ public inline fun List.last(predicate: (T) -> Boolean): T { /** * Returns last index of [element], or -1 if the collection does not contain element. */ -public fun Iterable.lastIndexOf(element: @kotlin.internal.NoInfer T): Int { +public fun <@kotlin.internal.OnlyInputTypes T> Iterable.lastIndexOf(element: T): Int { if (this is List) return this.lastIndexOf(element) var lastIndex = -1 var index = 0 @@ -433,27 +436,29 @@ public fun Iterable.lastIndexOf(element: @kotlin.internal.NoInfer T): Int /** * Returns last index of [element], or -1 if the collection does not contain element. */ -@Deprecated("Use 'indexOfRaw' instead.", ReplaceWith("indexOfRaw(element)")) +@Deprecated("Collection and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("lastIndexOf(element as Any?)")) @kotlin.jvm.JvmName("lastIndexOfAny") @kotlin.internal.LowPriorityInOverloadResolution @Suppress("NOTHING_TO_INLINE") public fun Iterable.lastIndexOf(element: T): Int { - return indexOfRaw(element) + return lastIndexOf(element as Any?) } /** * Returns last index of [element], or -1 if the collection does not contain element. * Allows to overcome type-safety restriction of `lastIndexOf` that requires to pass an element of type `T`. */ +@Deprecated("Collection and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("lastIndexOf(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun Iterable<*>.lastIndexOfRaw(element: Any?): Int { - return lastIndexOf(element) + return lastIndexOf(element as Any?) } /** * Returns last index of [element], or -1 if the list does not contain element. * Allows to overcome type-safety restriction of `lastIndexOf` that requires to pass an element of type `T`. */ +@Deprecated("List and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("lastIndexOf(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun List.lastIndexOfRaw(element: Any?): Int { return (this as List).lastIndexOf(element) diff --git a/libraries/stdlib/src/generated/_Sequences.kt b/libraries/stdlib/src/generated/_Sequences.kt index 7aed5ab8476..3551bc98375 100644 --- a/libraries/stdlib/src/generated/_Sequences.kt +++ b/libraries/stdlib/src/generated/_Sequences.kt @@ -15,27 +15,28 @@ import java.util.Collections // TODO: it's temporary while we have java.util.Col /** * Returns `true` if [element] is found in the sequence. */ -public operator fun Sequence.contains(element: @kotlin.internal.NoInfer T): Boolean { +public operator fun <@kotlin.internal.OnlyInputTypes T> Sequence.contains(element: T): Boolean { return indexOf(element) >= 0 } /** * Returns `true` if [element] is found in the collection. */ -@Deprecated("Use 'containsRaw' instead.", ReplaceWith("containsRaw(element)")) +@Deprecated("Sequence and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("contains(element as Any?)")) @kotlin.jvm.JvmName("containsAny") @kotlin.internal.LowPriorityInOverloadResolution public operator fun Sequence.contains(element: T): Boolean { - return containsRaw(element) + return contains(element as Any?) } /** * Returns `true` if [element] is found in the sequence. * Allows to overcome type-safety restriction of `contains` that requires to pass an element of type `T`. */ +@Deprecated("Sequence and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("contains(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun Sequence<*>.containsRaw(element: Any?): Boolean { - return contains(element) + return contains(element as Any?) } /** @@ -132,7 +133,7 @@ public inline fun Sequence.firstOrNull(predicate: (T) -> Boolean): T? { /** * Returns first index of [element], or -1 if the sequence does not contain element. */ -public fun Sequence.indexOf(element: @kotlin.internal.NoInfer T): Int { +public fun <@kotlin.internal.OnlyInputTypes T> Sequence.indexOf(element: T): Int { var index = 0 for (item in this) { if (element == item) @@ -145,12 +146,12 @@ public fun Sequence.indexOf(element: @kotlin.internal.NoInfer T): Int { /** * Returns first index of [element], or -1 if the collection does not contain element. */ -@Deprecated("Use 'indexOfRaw' instead.", ReplaceWith("indexOfRaw(element)")) +@Deprecated("Sequence and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("indexOf(element as Any?)")) @kotlin.jvm.JvmName("indexOfAny") @kotlin.internal.LowPriorityInOverloadResolution @Suppress("NOTHING_TO_INLINE") public fun Sequence.indexOf(element: T): Int { - return indexOfRaw(element) + return indexOf(element as Any?) } /** @@ -184,9 +185,10 @@ public inline fun Sequence.indexOfLast(predicate: (T) -> Boolean): Int { * Returns first index of [element], or -1 if the sequence does not contain element. * Allows to overcome type-safety restriction of `indexOf` that requires to pass an element of type `T`. */ +@Deprecated("Sequence and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("indexOf(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun Sequence<*>.indexOfRaw(element: Any?): Int { - return indexOf(element) + return indexOf(element as Any?) } /** @@ -223,7 +225,7 @@ public inline fun Sequence.last(predicate: (T) -> Boolean): T { /** * Returns last index of [element], or -1 if the sequence does not contain element. */ -public fun Sequence.lastIndexOf(element: @kotlin.internal.NoInfer T): Int { +public fun <@kotlin.internal.OnlyInputTypes T> Sequence.lastIndexOf(element: T): Int { var lastIndex = -1 var index = 0 for (item in this) { @@ -237,21 +239,22 @@ public fun Sequence.lastIndexOf(element: @kotlin.internal.NoInfer T): Int /** * Returns last index of [element], or -1 if the collection does not contain element. */ -@Deprecated("Use 'indexOfRaw' instead.", ReplaceWith("indexOfRaw(element)")) +@Deprecated("Sequence and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("lastIndexOf(element as Any?)")) @kotlin.jvm.JvmName("lastIndexOfAny") @kotlin.internal.LowPriorityInOverloadResolution @Suppress("NOTHING_TO_INLINE") public fun Sequence.lastIndexOf(element: T): Int { - return indexOfRaw(element) + return lastIndexOf(element as Any?) } /** * Returns last index of [element], or -1 if the sequence does not contain element. * Allows to overcome type-safety restriction of `lastIndexOf` that requires to pass an element of type `T`. */ +@Deprecated("Sequence and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("lastIndexOf(element as Any?)")) @Suppress("NOTHING_TO_INLINE") public inline fun Sequence<*>.lastIndexOfRaw(element: Any?): Int { - return lastIndexOf(element) + return lastIndexOf(element as Any?) } /** diff --git a/libraries/stdlib/src/kotlin/collections/Maps.kt b/libraries/stdlib/src/kotlin/collections/Maps.kt index ef6aae7dafa..0f1c5c237a1 100644 --- a/libraries/stdlib/src/kotlin/collections/Maps.kt +++ b/libraries/stdlib/src/kotlin/collections/Maps.kt @@ -96,31 +96,53 @@ public fun Map?.orEmpty() : Map = this ?: emptyMap() * Checks if the map contains the given key. This method allows to use the `x in map` syntax for checking * whether an object is contained in the map. */ -public operator fun Map.contains(key : K) : Boolean = containsKey(key) +public operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.contains(key: K) : Boolean = containsKey(key) /** * Returns the value corresponding to the given [key], or `null` if such a key is not present in the map. + */ +public operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.get(key: K): V? = (this as Map).get(key) - * Allows to overcome type-safety restriction of `get` that requires to pass a key of type `Key`. +/** + * Returns the value corresponding to the given [key], or `null` if such a key is not present in the map. + * + * Allows to overcome type-safety restriction of `get` that requires to pass a key of type `K`. */ @Suppress("NOTHING_TO_INLINE") -public inline fun Map.getRaw(key: Any?): V? = (this as Map).get(key) +@Deprecated("Map and key have incompatible types. Upcast key to Any? if you're sure.", ReplaceWith("get(key as Any?)")) +public inline fun Map.getRaw(key: Any?): V? = get(key as Any?) /** * Returns `true` if the map contains the specified [key]. * - * Allows to overcome type-safety restriction of `containsKey` that requires to pass a key of type `Key`. + * Allows to overcome type-safety restriction of `containsKey` that requires to pass a key of type `K`. */ +public fun <@kotlin.internal.OnlyInputTypes K> Map.containsKey(key: K): Boolean = (this as Map).containsKey(key) + @Suppress("NOTHING_TO_INLINE") -public inline fun Map.containsKeyRaw(key: Any?): Boolean = (this as Map).containsKey(key) +@Deprecated("Map and key have incompatible types. Upcast key to Any? if you're sure.", ReplaceWith("containsKey(key as Any?)")) +public inline fun Map.containsKeyRaw(key: Any?): Boolean = containsKey(key) /** * Returns `true` if the map maps one or more keys to the specified [value]. * * Allows to overcome type-safety restriction of `containsValue` that requires to pass a value of type `V`. */ +public fun Map.containsValue(value: V): Boolean = this.containsValue(value) + @Suppress("NOTHING_TO_INLINE") -public inline fun Map.containsValueRaw(value: Any?): Boolean = (this as Map).containsValue(value) +@Deprecated("Map and value have incompatible types. Upcast value to Any? if you're sure.", ReplaceWith("containsValue(value as Any?)")) +public inline fun Map.containsValueRaw(value: Any?): Boolean = containsValue(value) + + +/** + * Removes the specified key and its corresponding value from this map. + * + * @return the previous value associated with the key, or `null` if the key was not present in the map. + + * Allows to overcome type-safety restriction of `remove` that requires to pass a key of type `K`. + */ +public fun <@kotlin.internal.OnlyInputTypes K, V> MutableMap.remove(key: K): V? = (this as MutableMap).remove(key) /** * Returns the key component of the map entry. diff --git a/libraries/stdlib/src/kotlin/collections/MutableCollections.kt b/libraries/stdlib/src/kotlin/collections/MutableCollections.kt index a335d7d6189..271c3c9c041 100644 --- a/libraries/stdlib/src/kotlin/collections/MutableCollections.kt +++ b/libraries/stdlib/src/kotlin/collections/MutableCollections.kt @@ -10,8 +10,16 @@ import java.util.* * * Allows to overcome type-safety restriction of `containsAll` that requires to pass a collection of type `Collection`. */ +public fun <@kotlin.internal.OnlyInputTypes T> Collection.containsAll(elements: Collection): Boolean = this.containsAll(elements) + @Suppress("NOTHING_TO_INLINE") -public inline fun Collection<*>.containsAllRaw(elements: Collection): Boolean = (this as Collection).containsAll(elements) +@Deprecated("Collections have incompatible types. Upcast either to Collection if you're sure.", ReplaceWith("containsAll(elements as Collection)")) +public inline fun Collection<*>.containsAllRaw(elements: Collection): Boolean = containsAll(elements) + +@Deprecated("Collections have incompatible types. Upcast either to Collection if you're sure.", ReplaceWith("containsAll(elements as Collection)")) +@kotlin.jvm.JvmName("containsAllOfAny") +@kotlin.internal.LowPriorityInOverloadResolution +public fun Collection.containsAll(elements: Collection): Boolean = containsAll(elements) /** * Removes a single instance of the specified element from this @@ -21,8 +29,16 @@ public inline fun Collection<*>.containsAllRaw(elements: Collection): Bool * * @return `true` if the element has been successfully removed; `false` if it was not present in the collection. */ +public fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.remove(element: T): Boolean = (this as MutableCollection).remove(element) + @Suppress("NOTHING_TO_INLINE") -public inline fun MutableCollection.removeRaw(element: Any?): Boolean = (this as MutableCollection).remove(element) +@Deprecated("Collection and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("remove(element as Any?)")) +public inline fun MutableCollection.removeRaw(element: Any?): Boolean = remove(element) + +@Deprecated("Collection and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("remove(element as Any?)")) +@kotlin.jvm.JvmName("removeAny") +@kotlin.internal.LowPriorityInOverloadResolution +public fun MutableCollection.remove(element: Any?): Boolean = remove(element) /** * Removes all of this collection's elements that are also contained in the specified collection. @@ -31,8 +47,16 @@ public inline fun MutableCollection.removeRaw(element: Any?): Boolean = ( * * @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified. */ +public fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.removeAll(elements: Collection): Boolean = (this as MutableCollection).removeAll(elements) + @Suppress("NOTHING_TO_INLINE") -public inline fun MutableCollection.removeAllRaw(elements: Collection): Boolean = (this as MutableCollection).removeAll(elements) +@Deprecated("Collections have incompatible types. Upcast elements to Collection if you're sure.", ReplaceWith("removeAll(elements as Collection)")) +public inline fun MutableCollection.removeAllRaw(elements: Collection): Boolean = removeAll(elements) + +@Deprecated("Collections have incompatible types. Upcast elements to Collection if you're sure.", ReplaceWith("removeAll(elements as Collection)")) +@kotlin.jvm.JvmName("removeAllOfAny") +@kotlin.internal.LowPriorityInOverloadResolution +public fun MutableCollection.removeAll(elements: Collection): Boolean = removeAll(elements) /** * Retains only the elements in this collection that are contained in the specified collection. @@ -41,9 +65,41 @@ public inline fun MutableCollection.removeAllRaw(elements: Collection MutableCollection.retainAllRaw(elements: Collection): Boolean = (this as MutableCollection).retainAll(elements) +public fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.retainAll(elements: Collection): Boolean = (this as MutableCollection).retainAll(elements) +@Suppress("NOTHING_TO_INLINE") +@Deprecated("Collections have incompatible types. Upcast elements to Collection if you're sure.", ReplaceWith("retainAll(elements as Collection)")) +public inline fun MutableCollection.retainAllRaw(elements: Collection): Boolean = retainAll(elements) + +@Deprecated("Collections have incompatible types. Upcast elements to Collection if you're sure.", ReplaceWith("retainAll(elements as Collection)")) +@kotlin.jvm.JvmName("retainAllOfAny") +@kotlin.internal.LowPriorityInOverloadResolution +public fun MutableCollection.retainAll(elements: Collection): Boolean = retainAll(elements as Collection) + + +/** + * Returns the index of the first occurrence of the specified element in the list, or -1 if the specified + * element is not contained in the list. + * Allows to overcome type-safety restriction of `indexOf` that requires to pass an element of type `T`. + */ +public fun <@kotlin.internal.OnlyInputTypes T> List.indexOf(element: T): Int = indexOf(element) + +@Deprecated("List and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("indexOf(element as Any?)")) +@kotlin.jvm.JvmName("indexOfAny") +@kotlin.internal.LowPriorityInOverloadResolution +public fun List.indexOf(element: Any?): Int = indexOf(element as Any?) + +/** + * Returns the index of the last occurrence of the specified element in the list, or -1 if the specified + * element is not contained in the list. + * Allows to overcome type-safety restriction of `lastIndexOf` that requires to pass an element of type `T`. + */ +public fun <@kotlin.internal.OnlyInputTypes T> List.lastIndexOf(element: T): Int = lastIndexOf(element) + +@Deprecated("List and element have incompatible types. Upcast element to Any? if you're sure.", ReplaceWith("lastIndexOf(element as Any?)")) +@kotlin.jvm.JvmName("lastIndexOfAny") +@kotlin.internal.LowPriorityInOverloadResolution +public fun List.lastIndexOf(element: Any?): Int = lastIndexOf(element as Any?) @Deprecated("Use operator 'get' instead", ReplaceWith("this[index]")) @@ -58,8 +114,6 @@ public inline fun Map<*, *>.size() = size @Deprecated("Use property 'key' instead", ReplaceWith("key")) public fun Map.Entry.getKey(): K = key -@Deprecated("Use containsAllRaw() instead.", ReplaceWith("containsAllRaw(collection)")) -public fun Collection.containsAll(collection: Collection): Boolean = containsAllRaw(collection) @Deprecated("Use property 'value' instead.", ReplaceWith("value")) public fun Map.Entry.getValue(): V = value @@ -67,32 +121,23 @@ public fun Map.Entry.getValue(): V = value @Deprecated("Use 'removeAt' instead.", ReplaceWith("removeAt(index)")) public fun MutableList.remove(index: Int): E = removeAt(index) -@Deprecated("Use 'removeRaw' instead.", ReplaceWith("removeRaw(o)")) -public fun MutableCollection.remove(o: Any?): Boolean = removeRaw(o) -@Deprecated("Use 'removeAllRaw' instead.", ReplaceWith("removeAllRaw(c)")) -public fun MutableCollection.removeAll(c: Collection): Boolean = removeAllRaw(c) -@Deprecated("Use 'retainAllRaw' instead.", ReplaceWith("retainAllRaw(c)")) -public fun MutableCollection.retainAll(c: Collection): Boolean = retainAllRaw(c) - -@Deprecated("Use 'indexOfRaw' instead.", ReplaceWith("indexOfRaw(o)")) -public fun List.indexOf(o: Any?): Int = indexOfRaw(o) - -@Deprecated("Use 'lastIndexOfRaw' instead.", ReplaceWith("lastIndexOfRaw(o)")) -public fun List.lastIndexOf(o: Any?): Int = lastIndexOfRaw(o) @Deprecated("Use property 'length' instead.", ReplaceWith("length")) public fun CharSequence.length(): Int = length -@Deprecated("Use 'getRaw' instead.", ReplaceWith("getRaw(key)")) -public inline operator fun Map.get(key: Any?): V? = getRaw(key) +@Deprecated("Map and key have incompatible types. Upcast key to Any? if you're sure.", ReplaceWith("get(key as Any?)")) +@kotlin.internal.LowPriorityInOverloadResolution +public inline operator fun Map.get(key: Any?): V? = get(key) -@Deprecated("Use 'containsKeyRaw' instead.", ReplaceWith("containsKeyRaw(key)")) -public inline fun Map.containsKey(key: Any?): Boolean = containsKeyRaw(key) +@Deprecated("Map and key have incompatible types. Upcast key to Any? if you're sure.", ReplaceWith("containsKey(key as Any?)")) +@kotlin.internal.LowPriorityInOverloadResolution +public inline fun Map.containsKey(key: Any?): Boolean = containsKey(key) -@Deprecated("Use 'containsValueRaw' instead.", ReplaceWith("containsValueRaw(value)")) -public inline fun Map.containsValue(value: Any?): Boolean = containsValueRaw(value) +@Deprecated("Map and value have incompatible types. Upcast value to Any? if you're sure.", ReplaceWith("containsValue(value as Any?)")) +@kotlin.internal.LowPriorityInOverloadResolution +public inline fun Map.containsValue(value: Any?): Boolean = containsValue(value as Any?) @Deprecated("Use property 'keys' instead.", ReplaceWith("keys")) public inline fun Map.keySet(): Set = keys diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt index ecbb46d09ee..c5cb26110e7 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt @@ -12,7 +12,7 @@ fun elements(): List { only(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives) doc { f -> "Returns `true` if [element] is found in the ${f.collection}." } - customSignature(Iterables, ArraysOfObjects, Sequences) { "contains(element: @kotlin.internal.NoInfer T)" } + typeParam("@kotlin.internal.OnlyInputTypes T") returns("Boolean") body(Iterables) { """ @@ -34,7 +34,7 @@ fun elements(): List { only(Iterables, Sequences, ArraysOfObjects) doc { "Returns `true` if [element] is found in the collection." } returns("Boolean") - deprecate(Deprecation("Use 'containsRaw' instead.", "containsRaw(element)")) + deprecate { f -> with(DocExtensions) { Deprecation("${f.collection.capitalize()} and element have incompatible types. Upcast element to Any? if you're sure.", "contains(element as Any?)") } } annotations(""" @kotlin.jvm.JvmName("containsAny") @kotlin.internal.LowPriorityInOverloadResolution @@ -51,15 +51,15 @@ fun elements(): List { } receiverAsterisk(Iterables, Sequences) { true } inline(true) + deprecate { f -> with(DocExtensions) { Deprecation("${f.collection.capitalize()} and element have incompatible types. Upcast element to Any? if you're sure.", "contains(element as Any?)") } } annotations("""@Suppress("NOTHING_TO_INLINE")""") returns("Boolean") - body { "return contains(element)" } } templates add f("indexOf(element: T)") { only(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives) doc { f -> "Returns first index of [element], or -1 if the ${f.collection} does not contain element." } - customSignature(Iterables, ArraysOfObjects, Sequences) { "indexOf(element: @kotlin.internal.NoInfer T)" } + typeParam("@kotlin.internal.OnlyInputTypes T") returns("Int") body { f -> """ @@ -108,7 +108,7 @@ fun elements(): List { only(Iterables, Sequences, ArraysOfObjects) doc { "Returns first index of [element], or -1 if the collection does not contain element." } returns("Int") - deprecate(Deprecation("Use 'indexOfRaw' instead.", "indexOfRaw(element)")) + deprecate { f -> with(DocExtensions) { Deprecation("${f.collection.capitalize()} and element have incompatible types. Upcast element to Any? if you're sure.", "indexOf(element as Any?)") } } annotations(""" @kotlin.jvm.JvmName("indexOfAny") @kotlin.internal.LowPriorityInOverloadResolution @@ -126,16 +126,16 @@ fun elements(): List { } receiverAsterisk(Iterables, Sequences) { true } inline(true) + deprecate { f -> with(DocExtensions) { Deprecation("${f.collection.capitalize()} and element have incompatible types. Upcast element to Any? if you're sure.", "indexOf(element as Any?)") } } annotations("""@Suppress("NOTHING_TO_INLINE")""") returns("Int") - body { "return indexOf(element)" } body(Lists) { "return (this as List).indexOf(element)" } } templates add f("lastIndexOf(element: T)") { only(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives) doc { f -> "Returns last index of [element], or -1 if the ${f.collection} does not contain element." } - customSignature(Iterables, ArraysOfObjects, Sequences) { "lastIndexOf(element: @kotlin.internal.NoInfer T)" } + typeParam("@kotlin.internal.OnlyInputTypes T") returns("Int") body { f -> """ @@ -185,7 +185,7 @@ fun elements(): List { only(Iterables, Sequences, ArraysOfObjects) doc { "Returns last index of [element], or -1 if the collection does not contain element." } returns("Int") - deprecate(Deprecation("Use 'indexOfRaw' instead.", "indexOfRaw(element)")) + deprecate { f -> with(DocExtensions) { Deprecation("${f.collection.capitalize()} and element have incompatible types. Upcast element to Any? if you're sure.", "lastIndexOf(element as Any?)") } } annotations(""" @kotlin.jvm.JvmName("lastIndexOfAny") @kotlin.internal.LowPriorityInOverloadResolution @@ -203,9 +203,9 @@ fun elements(): List { } receiverAsterisk(Iterables, Sequences) { true } inline(true) + deprecate { f -> with(DocExtensions) { Deprecation("${f.collection.capitalize()} and element have incompatible types. Upcast element to Any? if you're sure.", "lastIndexOf(element as Any?)") } } annotations("""@Suppress("NOTHING_TO_INLINE")""") returns("Int") - body { "return lastIndexOf(element)" } body(Lists) { "return (this as List).lastIndexOf(element)" } } diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/engine/Engine.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/engine/Engine.kt index 5c5c308e537..b9ad14ddfca 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/engine/Engine.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/engine/Engine.kt @@ -316,8 +316,11 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { fun String.renderType(): String = renderType(this, receiver) fun effectiveTypeParams(): List { + fun removeAnnotations(typeParam: String) = + typeParam.replace("""^(@[\w\.]+\s+)+""".toRegex(), "") + fun getGenericTypeParameters(genericType: String) = - genericType + removeAnnotations(genericType) .dropWhile { it != '<' } .drop(1) .takeWhile { it != '>' } @@ -328,7 +331,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { val types = ArrayList(typeParams) if (f == Generic) { // ensure type parameter T, if it's not added to typeParams before - if (!types.any { it == "T" || it.startsWith("T:")}) { + if (!types.any { removeAnnotations(it).let { it == "T" || it.startsWith("T:") } }) { types.add("T") } return types @@ -336,7 +339,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { else if (primitive == null && f != Strings && f != CharSequences) { val implicitTypeParameters = getGenericTypeParameters(receiver) + types.flatMap { getGenericTypeParameters(it) } for (implicit in implicitTypeParameters.reversed()) { - if (implicit != "*" && !types.any { it.startsWith(implicit) || it.startsWith("reified " + implicit) }) { + if (implicit != "*" && !types.any { removeAnnotations(it).let { it.startsWith(implicit) || it.startsWith("reified " + implicit) } }) { types.add(0, implicit) } } @@ -345,7 +348,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") { } else { // remove T as parameter // TODO: Substitute primitive or String instead of T in other parameters from effective types not from original typeParams - return typeParams.filter { !it.startsWith("T") } + return typeParams.filterNot { removeAnnotations(it).startsWith("T") } } }