[JVM IR] ForLoopsLowering: Keep IMPLICIT_NOTNULL type-casts in next()

and `componentN()` calls.

There were issues when we have iterables from Java where the element
type has "not null" type information.
This commit is contained in:
Mark Punzalan
2019-12-18 01:10:07 -08:00
committed by Dmitry Petrov
parent e54ef3bdb8
commit 2dd8727baf
41 changed files with 2102 additions and 20 deletions
@@ -0,0 +1,30 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int>()
for (i in JImpl().arrayOfNotNull()) {
actualValues += i
}
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
interface J {
fun arrayOfNotNull(): Array<Int>
}
// FILE: JImpl.java
public class JImpl implements J {
// The only way to get @EnhancedNullability on the array element type (Int) is to override a Kotlin function that
// returns `Array<Int>` (where Int is not nullable). `@NotNull Integer[]` makes the array not nullable, not String.
@Override
public Integer[] arrayOfNotNull() {
return new Integer[] { 42, -42 };
}
}
@@ -0,0 +1,42 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with "Fail: should throw on get() in loop header". The not-null assertion is not generated when
// assigning to the loop variable. The root cause seems to be that the loop variable is a KtParameter and
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on KtParameters.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val i = JImpl().arrayOfNotNull()[0]
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for (i in JImpl().arrayOfNotNull()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
interface J {
fun arrayOfNotNull(): Array<Int>
}
// FILE: JImpl.java
public class JImpl implements J {
// The only way to get @EnhancedNullability on the array element type (Int) is to override a Kotlin function that
// returns `Array<Int>` (where Int is not nullable). `@NotNull Integer[]` makes the array not nullable, not String.
@Override
public Integer[] arrayOfNotNull() {
return new Integer[] { null };
}
}
@@ -0,0 +1,23 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int>()
for (i in J.arrayOfMaybeNullable()) {
actualValues += i
}
assertEquals(listOf(42, null), actualValues)
return "OK"
}
// FILE: J.java
public class J {
public static Integer[] arrayOfMaybeNullable() {
return new Integer[] { 42, null };
}
}
@@ -0,0 +1,23 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int>()
for (i: Int in J.arrayOfMaybeNullable()) {
actualValues += i
}
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
// FILE: J.java
public class J {
public static Integer[] arrayOfMaybeNullable() {
return new Integer[] { 42, -42 };
}
}
@@ -0,0 +1,36 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with a NullPointerException in the loop header. The not-null assertion is not generated when
// assigning to the loop variable. The root cause seems to be that the loop variable is a KtParameter and
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on KtParameters.
// The NPE is due to calling `intValue()` on the null Int; it is expected to be asserted as non-null first.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val i: Int = J.arrayOfMaybeNullable()[0]
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for (i: Int in J.arrayOfMaybeNullable()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
// FILE: J.java
public class J {
public static Integer[] arrayOfMaybeNullable() {
return new Integer[] { null };
}
}
@@ -0,0 +1,42 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int>()
for (i in J.listOfNotNull()) {
actualValues += i
}
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static List<@NotNull Integer> listOfNotNull() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(-42);
return list;
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}
@@ -0,0 +1,51 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with "Fail: should throw on get() in loop header". The not-null assertion is not generated when
// assigning to the loop variable. The root cause seems to be that the loop variable is a KtParameter and
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on KtParameters.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val i = J.listOfNotNull()[0]
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for (i in J.listOfNotNull()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static List<@NotNull Integer> listOfNotNull() {
return Collections.singletonList(null);
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}
@@ -0,0 +1,42 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int?>()
for (i in J.listOfNullable()) {
actualValues += i
}
assertEquals(listOf(42, null), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static List<@Nullable Integer> listOfNullable() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(null);
return list;
}
}
// FILE: Nullable.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @Nullable does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.Nullable for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface Nullable {
}
@@ -0,0 +1,34 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int>()
for (i in JImpl().listOfNotNull()) {
actualValues += i
}
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
interface J {
fun listOfNotNull(): List<Int>
}
// FILE: JImpl.java
import java.util.*;
public class JImpl implements J {
// Type argument (Int) gets @EnhancedNullability because it is not nullable in overridden Kotlin function.
@Override
public List<Integer> listOfNotNull() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(-42);
return list;
}
}
@@ -0,0 +1,43 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with "Fail: should throw on get() in loop header". The not-null assertion is not generated when
// assigning to the loop variable. The root cause seems to be that the loop variable is a KtParameter and
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on KtParameters.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val i = JImpl().listOfNotNull()[0]
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for (i in JImpl().listOfNotNull()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
interface J {
fun listOfNotNull(): List<Int>
}
// FILE: JImpl.java
import java.util.*;
public class JImpl implements J {
// Type argument (Int) gets @EnhancedNullability because it is not nullable in overridden Kotlin function.
@Override
public List<Integer> listOfNotNull() {
return Collections.singletonList(null);
}
}
@@ -0,0 +1,28 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int>()
for (i in J.listOfMaybeNullable()) {
actualValues += i
}
assertEquals(listOf(42, null), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
public class J {
public static List<Integer> listOfMaybeNullable() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(null);
return list;
}
}
@@ -0,0 +1,28 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int>()
for (i: Int in J.listOfMaybeNullable()) {
actualValues += i
}
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
public class J {
public static List<Integer> listOfMaybeNullable() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(-42);
return list;
}
}
@@ -0,0 +1,38 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with a NullPointerException in the loop header. The not-null assertion is not generated when
// assigning to the loop variable. The root cause seems to be that the loop variable is a KtParameter and
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on KtParameters.
// The NPE is due to calling `intValue()` on the null Int; it is expected to be asserted as non-null first.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val i: Int = J.listOfMaybeNullable()[0]
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for (i: Int in J.listOfMaybeNullable()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
// FILE: J.java
import java.util.*;
public class J {
public static List<Integer> listOfMaybeNullable() {
return Collections.singletonList(null);
}
}
@@ -0,0 +1,22 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FULL_JDK
import kotlin.test.*
fun box(): String {
val map = java.util.LinkedHashMap<Int, Int>()
map.put(3, 42)
map.put(14, -42)
// Even though the type parameters on `map` are not nullable, the `values` property is implemented in Java and therefore there is
// @EnhancedNullability on its type argument (Int).
val actualValues = mutableListOf<Int>()
for (v in map.values) {
actualValues += v
}
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
@@ -0,0 +1,23 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FULL_JDK
import kotlin.test.*
fun box(): String {
val map = java.util.LinkedHashMap<Int, Int>()
map.put(3, 42)
map.put(14, -42)
// Even though the type parameters on `map` are not nullable, the `values` property is implemented in Java and therefore there is
// @EnhancedNullability on its type argument (Int), which gets propagated on the call to `toTypedArray()`.
// If we simply called `map.toTypedArray()` there would be no @EnhancedNullability on Int.
val actualValues = mutableListOf<Int>()
for (v in map.values.toTypedArray()) {
actualValues += v
}
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
@@ -0,0 +1,42 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int>()
for (i in J.listOfNotNull().toTypedArray()) {
actualValues += i
}
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static List<@NotNull Integer> listOfNotNull() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(-42);
return list;
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}
@@ -0,0 +1,51 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with "Fail: should throw on get() in loop header". The not-null assertion is not generated when
// assigning to the loop variable. The root cause seems to be that the loop variable is a KtParameter and
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on KtParameters.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val i = J.listOfNotNull().toTypedArray()[0]
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for (i in J.listOfNotNull().toTypedArray()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static List<@NotNull Integer> listOfNotNull() {
return Collections.singletonList(null);
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}
@@ -0,0 +1,42 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualValues = mutableListOf<Int>()
for (i in J.iteratorOfNotNull()) {
actualValues += i
}
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static Iterator<@NotNull Integer> iteratorOfNotNull() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(-42);
return list.iterator();
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}
@@ -0,0 +1,51 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with "Fail: should throw on get() in loop header". The not-null assertion is not generated when
// assigning to the loop variable. The root cause seems to be that the loop variable is a KtParameter and
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on KtParameters.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val i = J.iteratorOfNotNull().next()
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for (i in J.iteratorOfNotNull()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static Iterator<@NotNull Integer> iteratorOfNotNull() {
return Collections.<Integer>singletonList(null).iterator();
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}
@@ -0,0 +1,33 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualIndices = mutableListOf<Int>()
val actualValues = mutableListOf<Int>()
for ((index, i) in JImpl().arrayOfNotNull().withIndex()) {
actualIndices += index
actualValues += i
}
assertEquals(listOf(0, 1), actualIndices)
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
interface J {
fun arrayOfNotNull(): Array<Int>
}
// FILE: JImpl.java
public class JImpl implements J {
// The only way to get @EnhancedNullability on the array element type (Int) is to override a Kotlin function that
// returns `Array<Int>` (where Int is not nullable). `@NotNull Integer[]` makes the array not nullable, not String.
@Override
public Integer[] arrayOfNotNull() {
return new Integer[] { 42, -42 };
}
}
@@ -0,0 +1,43 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with "Fail: should throw on get()". The not-null assertion is not generated when assigning to the
// variables in the destructuring declaration. The root cause seems to be that
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on
// KtDestructuringDeclarations and their entries.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val (index, i) = JImpl().arrayOfNotNull().withIndex().first()
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for ((index, i) in JImpl().arrayOfNotNull().withIndex()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
interface J {
fun arrayOfNotNull(): Array<Int>
}
// FILE: JImpl.java
public class JImpl implements J {
// The only way to get @EnhancedNullability on the array element type (Int) is to override a Kotlin function that
// returns `Array<Int>` (where Int is not nullable). `@NotNull Integer[]` makes the array not nullable, not String.
@Override
public Integer[] arrayOfNotNull() {
return new Integer[] { null };
}
}
@@ -0,0 +1,26 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualIndices = mutableListOf<Int>()
val actualValues = mutableListOf<Int>()
for ((index, i) in J.arrayOfMaybeNullable().withIndex()) {
actualIndices += index
actualValues += i
}
assertEquals(listOf(0, 1), actualIndices)
assertEquals(listOf(42, null), actualValues)
return "OK"
}
// FILE: J.java
public class J {
public static Integer[] arrayOfMaybeNullable() {
return new Integer[] { 42, null };
}
}
@@ -0,0 +1,26 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualIndices = mutableListOf<Int>()
val actualValues = mutableListOf<Int>()
for ((index, i: Int) in J.arrayOfMaybeNullable().withIndex()) {
actualIndices += index
actualValues += i
}
assertEquals(listOf(0, 1), actualIndices)
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
// FILE: J.java
public class J {
public static Integer[] arrayOfMaybeNullable() {
return new Integer[] { 42, -42 };
}
}
@@ -0,0 +1,33 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM, JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails because explicit types are ignored in destructuring declarations (KT-22392).
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val (index, i: Int) = J.arrayOfMaybeNullable().withIndex().first()
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for ((index, i: Int) in J.arrayOfMaybeNullable().withIndex()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
// FILE: J.java
public class J {
public static Integer[] arrayOfMaybeNullable() {
return new Integer[] { null };
}
}
@@ -0,0 +1,45 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualIndices = mutableListOf<Int>()
val actualValues = mutableListOf<Int>()
for ((index, i) in J.listOfNotNull().withIndex()) {
actualIndices += index
actualValues += i
}
assertEquals(listOf(0, 1), actualIndices)
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static List<@NotNull Integer> listOfNotNull() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(-42);
return list;
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}
@@ -0,0 +1,52 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with "Fail: should throw on get()". The not-null assertion is not generated when assigning to the
// variables in the destructuring declaration. The root cause seems to be that
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on
// KtDestructuringDeclarations and their entries.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val (index, i) = J.listOfNotNull().withIndex().first()
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for ((index, i) in J.listOfNotNull().withIndex()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static List<@NotNull Integer> listOfNotNull() {
return Collections.singletonList(null);
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}
@@ -0,0 +1,45 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualIndices = mutableListOf<Int>()
val actualValues = mutableListOf<Int?>()
for ((index, i) in J.listOfNullable().withIndex()) {
actualIndices += index
actualValues += i
}
assertEquals(listOf(0, 1), actualIndices)
assertEquals(listOf(42, null), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static List<@Nullable Integer> listOfNullable() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(null);
return list;
}
}
// FILE: Nullable.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @Nullable does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.Nullable for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface Nullable {
}
@@ -0,0 +1,31 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualIndices = mutableListOf<Int>()
val actualValues = mutableListOf<Int>()
for ((index, i) in J.listOfMaybeNullable().withIndex()) {
actualIndices += index
actualValues += i
}
assertEquals(listOf(0, 1), actualIndices)
assertEquals(listOf(42, null), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
public class J {
public static List<Integer> listOfMaybeNullable() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(null);
return list;
}
}
@@ -0,0 +1,31 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualIndices = mutableListOf<Int>()
val actualValues = mutableListOf<Int>()
for ((index, i: Int) in J.listOfMaybeNullable().withIndex()) {
actualIndices += index
actualValues += i
}
assertEquals(listOf(0, 1), actualIndices)
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
public class J {
public static List<Integer> listOfMaybeNullable() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(-42);
return list;
}
}
@@ -0,0 +1,35 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM, JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails because explicit types are ignored in destructuring declarations (KT-22392).
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val (index, i: Int) = J.listOfMaybeNullable().withIndex().first()
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for ((index, i: Int) in J.listOfMaybeNullable().withIndex()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
// FILE: J.java
import java.util.*;
public class J {
public static List<Integer> listOfMaybeNullable() {
return Collections.singletonList(null);
}
}
@@ -0,0 +1,45 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// FILE: box.kt
import kotlin.test.*
fun box(): String {
val actualIndices = mutableListOf<Int>()
val actualValues = mutableListOf<Int>()
for ((index, i) in J.iteratorOfNotNull().withIndex()) {
actualIndices += index
actualValues += i
}
assertEquals(listOf(0, 1), actualIndices)
assertEquals(listOf(42, -42), actualValues)
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static Iterator<@NotNull Integer> iteratorOfNotNull() {
List<Integer> list = new ArrayList<>();
list.add(42);
list.add(-42);
return list.iterator();
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}
@@ -0,0 +1,52 @@
// !LANGUAGE: +StrictJavaNullabilityAssertions
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// Note: This fails on JVM (non-IR) with "Fail: should throw on get()". The not-null assertion is not generated when assigning to the
// variables in the destructuring declaration. The root cause seems to be that
// CodegenAnnotatingVisitor/RuntimeAssertionsOnDeclarationBodyChecker do not analyze the need for not-null assertions on
// KtDestructuringDeclarations and their entries.
// FILE: box.kt
import kotlin.test.*
fun box(): String {
// Sanity check to make sure there IS an exception even when not in a for-loop
try {
val (index, i) = J.iteratorOfNotNull().withIndex().next()
return "Fail: should throw on get()"
} catch (e: IllegalStateException) {}
try {
for ((index, i) in J.iteratorOfNotNull().withIndex()) {
return "Fail: should throw on get() in loop header"
}
}
catch (e: IllegalStateException) {}
return "OK"
}
// FILE: J.java
import java.util.*;
import org.jetbrains.annotations.*;
public class J {
public static Iterator<@NotNull Integer> iteratorOfNotNull() {
return Collections.<Integer>singletonList(null).iterator();
}
}
// FILE: NotNull.java
package org.jetbrains.annotations;
import java.lang.annotation.*;
// org.jetbrains.annotations used in the compiler is version 13, whose @NotNull does not support the TYPE_USE target (version 15 does).
// We're using our own @org.jetbrains.annotations.NotNull for testing purposes.
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
public @interface NotNull {
}