KT-10752: if (inferred) type for an expression refers to a Java class
non-accessible in the current context, it is a compiler error. Otherwise we might generate a CHECKCAST instruction that causes IAE at run-time. Here we are somewhat less permissive then Java (see inaccessibleType.kt in diagnostics tests).
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
// !DIAGNOSTICS: -USELESS_CAST -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||
|
||||
// FILE: j/Base.java
|
||||
package j;
|
||||
public interface Base {
|
||||
void foo();
|
||||
}
|
||||
|
||||
// FILE: j/Impl.java
|
||||
package j;
|
||||
|
||||
/* package */ abstract class Impl implements Base {
|
||||
public void foo() {}
|
||||
}
|
||||
|
||||
// FILE: j/Derived1.java
|
||||
package j;
|
||||
|
||||
public class Derived1 extends Impl {}
|
||||
|
||||
// FILE: j/Derived2.java
|
||||
package j;
|
||||
|
||||
public class Derived2 extends Impl {}
|
||||
|
||||
// FILE: k/Client.kt
|
||||
package k
|
||||
|
||||
import j.*
|
||||
|
||||
val d1 = Derived1()
|
||||
val d2 = Derived2()
|
||||
|
||||
fun <T> select(x1: T, x2: T) = x1
|
||||
fun <T> selectn(vararg xx: T) = xx[0]
|
||||
fun <T : Base> foo(x: T) = x.foo()
|
||||
fun <T> listOf2(x1: T, x2: T): List<T> = null!!
|
||||
fun <T> arrayOf2(x1: T, x2: T): Array<T> = null!!
|
||||
|
||||
fun test() {
|
||||
val test1: Base = if (true) d1 else d2
|
||||
|
||||
val test2 = <!INACCESSIBLE_TYPE!>if (true) d1 else d2<!>
|
||||
|
||||
val test3 = <!INACCESSIBLE_TYPE!>when {
|
||||
true -> d1
|
||||
else -> d2
|
||||
}<!>
|
||||
|
||||
val test4: Base = when {
|
||||
true -> d1
|
||||
else -> d2
|
||||
}
|
||||
|
||||
val test5 = <!INACCESSIBLE_TYPE!>select(d1, d2)<!>
|
||||
|
||||
val test6 = select<Base>(d1, d2)
|
||||
|
||||
val test7 = select(d1 as Base, d2)
|
||||
|
||||
val test8 = <!INACCESSIBLE_TYPE!>selectn(d1, d2)<!>
|
||||
|
||||
val test9 = selectn<Base>(d1, d2)
|
||||
|
||||
val test10 = <!INACCESSIBLE_TYPE!>listOf2(d1, d2)<!>
|
||||
|
||||
val test11: List<Base> = <!INACCESSIBLE_TYPE!>listOf2(d1, d2)<!>
|
||||
// NB Inferred type is List<Impl> because List is covariant.
|
||||
|
||||
val test12 = listOf2<Base>(d1, d2)
|
||||
|
||||
val test13 = <!INACCESSIBLE_TYPE!>arrayOf2(d1, d2)<!>
|
||||
|
||||
val test14: Array<Base> = arrayOf2(d1, d2)
|
||||
// NB Inferred type is Array<Base> because Array is invariant.
|
||||
|
||||
val test15 = arrayOf2<Base>(d1, d2)
|
||||
|
||||
for (test16 in <!INACCESSIBLE_TYPE!>listOf2(d1, d2)<!>) {}
|
||||
}
|
||||
|
||||
fun testOkInJava() {
|
||||
// The following is Ok in Java, but is an error in Kotlin.
|
||||
// TODO do not generate unneeded CHECKCASTs.
|
||||
// TODO do not report INACCESSIBLE_TYPE for corresponding cases.
|
||||
<!INACCESSIBLE_TYPE!>select(d1, d2)<!>
|
||||
foo(<!INACCESSIBLE_TYPE!>select(d1, d2)<!>)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package
|
||||
|
||||
package k {
|
||||
public val d1: j.Derived1
|
||||
public val d2: j.Derived2
|
||||
public fun </*0*/ T> arrayOf2(/*0*/ x1: T, /*1*/ x2: T): kotlin.Array<T>
|
||||
public fun </*0*/ T : j.Base> foo(/*0*/ x: T): kotlin.Unit
|
||||
public fun </*0*/ T> listOf2(/*0*/ x1: T, /*1*/ x2: T): kotlin.collections.List<T>
|
||||
public fun </*0*/ T> select(/*0*/ x1: T, /*1*/ x2: T): T
|
||||
public fun </*0*/ T> selectn(/*0*/ vararg xx: T /*kotlin.Array<out T>*/): T
|
||||
public fun test(): kotlin.Unit
|
||||
public fun testOkInJava(): kotlin.Unit
|
||||
}
|
||||
@@ -30,6 +30,5 @@ package other
|
||||
import test.My
|
||||
|
||||
class Your {
|
||||
// Ok but dangerous: internal vs package-private in different package
|
||||
internal fun bar() = My.foo()
|
||||
internal fun bar() = <!INACCESSIBLE_TYPE!>My.foo()<!>
|
||||
}
|
||||
|
||||
@@ -26,19 +26,19 @@ package b
|
||||
|
||||
import a.<!INVISIBLE_REFERENCE!>MyJavaClass<!>
|
||||
|
||||
val <!EXPOSED_PROPERTY_TYPE!>mc1<!> = <!INVISIBLE_MEMBER!>MyJavaClass<!>()
|
||||
val <!EXPOSED_PROPERTY_TYPE!>mc1<!> = <!INACCESSIBLE_TYPE!><!INVISIBLE_MEMBER!>MyJavaClass<!>()<!>
|
||||
|
||||
val x = <!INVISIBLE_REFERENCE!>MyJavaClass<!>.<!INVISIBLE_MEMBER!>staticMethod<!>()
|
||||
val y = <!INVISIBLE_REFERENCE!>MyJavaClass<!>.<!INVISIBLE_REFERENCE!>NestedClass<!>.<!INVISIBLE_MEMBER!>staticMethodOfNested<!>()
|
||||
val <!EXPOSED_PROPERTY_TYPE!>z<!> = <!INVISIBLE_REFERENCE!>MyJavaClass<!>.<!INVISIBLE_MEMBER!>NestedClass<!>()
|
||||
val <!EXPOSED_PROPERTY_TYPE!>z<!> = <!INACCESSIBLE_TYPE!><!INVISIBLE_REFERENCE!>MyJavaClass<!>.<!INVISIBLE_MEMBER!>NestedClass<!>()<!>
|
||||
|
||||
//FILE: c.kt
|
||||
package a.c
|
||||
|
||||
import a.<!INVISIBLE_REFERENCE!>MyJavaClass<!>
|
||||
|
||||
val <!EXPOSED_PROPERTY_TYPE!>mc1<!> = <!INVISIBLE_MEMBER!>MyJavaClass<!>()
|
||||
val <!EXPOSED_PROPERTY_TYPE!>mc1<!> = <!INACCESSIBLE_TYPE!><!INVISIBLE_MEMBER!>MyJavaClass<!>()<!>
|
||||
|
||||
val x = <!INVISIBLE_REFERENCE!>MyJavaClass<!>.<!INVISIBLE_MEMBER!>staticMethod<!>()
|
||||
val y = <!INVISIBLE_REFERENCE!>MyJavaClass<!>.<!INVISIBLE_REFERENCE!>NestedClass<!>.<!INVISIBLE_MEMBER!>staticMethodOfNested<!>()
|
||||
val <!EXPOSED_PROPERTY_TYPE!>z<!> = <!INVISIBLE_REFERENCE!>MyJavaClass<!>.<!INVISIBLE_MEMBER!>NestedClass<!>()
|
||||
val <!EXPOSED_PROPERTY_TYPE!>z<!> = <!INACCESSIBLE_TYPE!><!INVISIBLE_REFERENCE!>MyJavaClass<!>.<!INVISIBLE_MEMBER!>NestedClass<!>()<!>
|
||||
Reference in New Issue
Block a user