[stdlib] Fix ArrayDeque.indexOf and lastIndexOf

There are two related bugs:
- KT-80390: ArrayDeque.indexOf(null) returns some index when a deque had some elements, but later was cleaned
- KT-80661: ArrayDeque.lastIndexOf returns -1 when the internal storage is full (i.e. head == internalIndex(size))
In both cases, we have to be more careful when scanning the internal storage if head == internalIndex(size).

^KT-80390 fixed
^KT-80661 fixed

Merge-request: KT-MR-23363
Merged-by: Filipp Zhinkin <filipp.zhinkin@jetbrains.com>
diff --git a/libraries/stdlib/src/kotlin/collections/ArrayDeque.kt b/libraries/stdlib/src/kotlin/collections/ArrayDeque.kt
index 4d16866..27eb6a6 100644
--- a/libraries/stdlib/src/kotlin/collections/ArrayDeque.kt
+++ b/libraries/stdlib/src/kotlin/collections/ArrayDeque.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
  * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
  */
 
@@ -393,7 +393,7 @@
             for (index in head until tail) {
                 if (element == elementData[index]) return index - head
             }
-        } else if (head >= tail) {
+        } else if (isNotEmpty() && head >= tail) {
             for (index in head until elementData.size) {
                 if (element == elementData[index]) return index - head
             }
@@ -412,7 +412,7 @@
             for (index in tail - 1 downTo head) {
                 if (element == elementData[index]) return index - head
             }
-        } else if (head > tail) {
+        } else if (isNotEmpty() && head >= tail) {
             for (index in tail - 1 downTo 0) {
                 if (element == elementData[index]) return index + elementData.size - head
             }
diff --git a/libraries/stdlib/test/collections/ArrayDequeTest.kt b/libraries/stdlib/test/collections/ArrayDequeTest.kt
index c8c6a9a..aa2dd80 100644
--- a/libraries/stdlib/test/collections/ArrayDequeTest.kt
+++ b/libraries/stdlib/test/collections/ArrayDequeTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
  * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
  */
 
@@ -429,6 +429,63 @@
             (0..6).forEach { assertEquals(it, deque.indexOf(it - 4)) }
             assertEquals(-1, deque.indexOf(100))
         }
+
+        testArrayDeque { bufferSize, _, head, tail ->
+            generateArrayDeque(head, tail, bufferSize).let { deque ->
+                deque.forEachIndexed { index, element ->
+                    val actualIndex = deque.indexOf(element)
+                    if (actualIndex != index) {
+                        assertEquals(index, actualIndex, "indexOf($element) for $deque")
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun indexOfNull() {
+        val deque = ArrayDeque<Int?>()
+        assertEquals(-1, deque.indexOf(null))
+        deque.addLast(42)
+        assertEquals(-1, deque.indexOf(null))
+        deque.clear()
+        assertEquals(-1, deque.indexOf(null))
+    }
+
+    @Test
+    fun lastIndexOf() {
+        // head < tail
+        generateArrayDeque(0, 7).let { deque ->
+            (0..6).forEach { assertEquals(it, deque.lastIndexOf(it)) }
+            assertEquals(-1, deque.lastIndexOf(100))
+        }
+
+        // head > tail
+        generateArrayDeque(-4, 3).let { deque ->
+            (0..6).forEach { assertEquals(it, deque.lastIndexOf(it - 4)) }
+            assertEquals(-1, deque.lastIndexOf(100))
+        }
+
+        testArrayDeque { bufferSize, _, head, tail ->
+            generateArrayDeque(head, tail, bufferSize).let { deque ->
+                deque.forEachIndexed { index, element ->
+                    val actualIndex = deque.lastIndexOf(element)
+                    if (actualIndex != index) {
+                        assertEquals(index, actualIndex, "lastIndexOf($element) for $deque")
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    fun lastIndexOfNull() {
+        val deque = ArrayDeque<Int?>()
+        assertEquals(-1, deque.lastIndexOf(null))
+        deque.addLast(42)
+        assertEquals(-1, deque.lastIndexOf(null))
+        deque.clear()
+        assertEquals(-1, deque.lastIndexOf(null))
     }
 
     @Test
@@ -694,4 +751,4 @@
         deque.internalStructure { head, _ -> assertEquals(-2, head) } // deque min capacity is 10
         testContentEquals(arrayOf(-3, -2, -1, 1, 2, 3, 4, 5, 6, 7))
     }
-}
\ No newline at end of file
+}