[FIR-TEST] Add new testdata generated after changes in previous commit
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package o
|
||||
|
||||
class A {
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun foo(b: B) = b<!>
|
||||
}
|
||||
|
||||
class B {
|
||||
fun bar() {}
|
||||
}
|
||||
|
||||
fun test(a: A, b: B?) {
|
||||
a foo b!!
|
||||
b.bar()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun foo(): String {
|
||||
var s: String?
|
||||
s = null
|
||||
s?.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
if (s == null) return s!!
|
||||
var t: String? = "y"
|
||||
if (t == null) t = "x"
|
||||
var x: Int? = null
|
||||
if (x == null) <!UNRESOLVED_REFERENCE!>x += null<!>
|
||||
return t + s
|
||||
}
|
||||
|
||||
fun String?.gav() {}
|
||||
|
||||
fun bar(s: String?) {
|
||||
if (s != null) return
|
||||
s.gav()
|
||||
s as? String
|
||||
s as String?
|
||||
s as String
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// FILE: My.java
|
||||
|
||||
public class My {
|
||||
static public My create() { return new My(); }
|
||||
public void foo() {}
|
||||
}
|
||||
|
||||
// FILE: Test.kt
|
||||
|
||||
fun test() {
|
||||
val my = My.create()
|
||||
if (my == null) {
|
||||
my.foo()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// !LANGUAGE: -SafeCastCheckBoundSmartCasts
|
||||
|
||||
interface SomeClass {
|
||||
val data: Any?
|
||||
}
|
||||
|
||||
interface SomeSubClass : SomeClass {
|
||||
val foo: Any?
|
||||
}
|
||||
|
||||
fun g(a: SomeClass?) {
|
||||
if (a as? SomeSubClass != null) {
|
||||
// 'a' can be cast to SomeSubClass
|
||||
a.hashCode()
|
||||
a.foo
|
||||
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
(a as SomeSubClass).foo
|
||||
}
|
||||
val b = (a as? SomeSubClass)?.foo
|
||||
if (b != null) {
|
||||
// 'a' can be cast to SomeSubClass
|
||||
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
(a as SomeSubClass).foo
|
||||
}
|
||||
val c = a as? SomeSubClass
|
||||
if (c != null) {
|
||||
// 'a' and 'c' can be cast to SomeSubClass
|
||||
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
c.hashCode()
|
||||
c.foo
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// !LANGUAGE: +SafeCastCheckBoundSmartCasts
|
||||
|
||||
interface SomeClass {
|
||||
val data: Any?
|
||||
}
|
||||
|
||||
interface SomeSubClass : SomeClass {
|
||||
val foo: Any?
|
||||
}
|
||||
|
||||
fun g(a: SomeClass?) {
|
||||
if (a as? SomeSubClass != null) {
|
||||
// 'a' can be cast to SomeSubClass
|
||||
a.hashCode()
|
||||
a.foo
|
||||
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
(a as SomeSubClass).foo
|
||||
}
|
||||
val b = (a as? SomeSubClass)?.foo
|
||||
if (b != null) {
|
||||
// 'a' can be cast to SomeSubClass
|
||||
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
(a as SomeSubClass).foo
|
||||
}
|
||||
val c = a as? SomeSubClass
|
||||
if (c != null) {
|
||||
// 'a' and 'c' can be cast to SomeSubClass
|
||||
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
c.hashCode()
|
||||
c.foo
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// !LANGUAGE: +SafeCastCheckBoundSmartCasts
|
||||
// See KT-20752
|
||||
|
||||
class Unstable {
|
||||
val first: String? get() = null
|
||||
}
|
||||
|
||||
class StringList {
|
||||
fun remove(s: String) = s
|
||||
}
|
||||
|
||||
fun StringList.remove(s: String?) = s ?: ""
|
||||
|
||||
fun foo(list: StringList, arg: Unstable) {
|
||||
list.remove(arg.first)
|
||||
if (arg.first as? String != null) {
|
||||
// Should be still resolved to extension, without smart cast or smart cast impossible
|
||||
list.remove(arg.first)
|
||||
}
|
||||
val s = arg.first as? String
|
||||
if (s != null) {
|
||||
// Should be still resolved to extension, without smart cast or smart cast impossible
|
||||
list.remove(arg.first)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// !LANGUAGE: +SafeCastCheckBoundSmartCasts
|
||||
// See KT-19007
|
||||
|
||||
// Stub
|
||||
fun String.indexOf(arg: String) = this.length - arg.length
|
||||
|
||||
// Stub
|
||||
fun String.toLowerCase() = this
|
||||
|
||||
fun foo(a: Any) {
|
||||
// Should compile in 1.2
|
||||
(a as? String)?.indexOf(a.toLowerCase())
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
class Item(val link: String?)
|
||||
|
||||
fun test(item: Item) {
|
||||
if (item.link != null) {
|
||||
val href: String = item.link
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !LANGUAGE: +SafeCastCheckBoundSmartCasts
|
||||
interface SomeClass {
|
||||
val data: Any?
|
||||
}
|
||||
|
||||
interface SomeSubClass : SomeClass {
|
||||
val foo: Any?
|
||||
}
|
||||
|
||||
object Impl : SomeSubClass {
|
||||
override val data = ""
|
||||
override val foo = 42
|
||||
}
|
||||
|
||||
fun g(a: SomeClass?) {
|
||||
var b = (a as? SomeSubClass)?.foo
|
||||
b = "Hello"
|
||||
if (b != null) {
|
||||
// 'a' cannot be cast to SomeSubClass!
|
||||
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
(a as SomeSubClass).foo
|
||||
}
|
||||
var c = a as? SomeSubClass
|
||||
c = Impl
|
||||
if (c != null) {
|
||||
// 'a' cannot be cast to SomeSubClass
|
||||
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
a.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(a as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
c.hashCode()
|
||||
c.foo
|
||||
}
|
||||
}
|
||||
|
||||
fun f(a: SomeClass?) {
|
||||
var aa = a
|
||||
|
||||
if (aa as? SomeSubClass != null) {
|
||||
aa = null
|
||||
// 'aa' cannot be cast to SomeSubClass
|
||||
aa.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
aa.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(aa as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
(aa as SomeSubClass).foo
|
||||
}
|
||||
val b = (aa as? SomeSubClass)?.foo
|
||||
aa = null
|
||||
if (b != null) {
|
||||
// 'aa' cannot be cast to SomeSubClass
|
||||
aa.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
aa.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(aa as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
(aa as SomeSubClass).foo
|
||||
}
|
||||
aa = a
|
||||
val c = aa as? SomeSubClass
|
||||
if (c != null) {
|
||||
// 'c' can be cast to SomeSubClass
|
||||
aa.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
aa.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(aa as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
c.hashCode()
|
||||
c.foo
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
open class T {
|
||||
val x : Int? = null
|
||||
}
|
||||
|
||||
class A {
|
||||
companion object: T() {
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
companion object: T() {
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
if (A.x != null) {
|
||||
useInt(A.x)
|
||||
useInt(B.x)
|
||||
}
|
||||
}
|
||||
|
||||
fun useInt(i: Int) = i
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package foo
|
||||
|
||||
fun dispatch(request: Request) {
|
||||
val url = request.getRequestURI() as String
|
||||
|
||||
if (request.getMethod()?.length != 0) {
|
||||
}
|
||||
}
|
||||
|
||||
interface Request {
|
||||
fun getRequestURI(): String?
|
||||
fun getMethod(): String?
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun foo(x : String?, y : String?) {
|
||||
if (y != null && x == y) {
|
||||
// Both not null
|
||||
x.length
|
||||
y.length
|
||||
}
|
||||
else {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
if (y != null || x == y) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
else {
|
||||
// y == null but x != y
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
if (y == null && x != y) {
|
||||
// y == null but x != y
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
else {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
if (y == null || x != y) {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
else {
|
||||
// Both not null
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
y.length
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun foo(x: String?, y: String?, z: String?, w: String?) {
|
||||
if (x != null && y != null && (x == z || y == z))
|
||||
z.length
|
||||
else
|
||||
z.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
if (x != null || y != null || (x != z && y != z))
|
||||
z.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
else
|
||||
z.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
if (x == null || y == null || (x != z && y != z))
|
||||
z.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
else
|
||||
z.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
if (x != null && y == x && z == y && w == z)
|
||||
w.length
|
||||
else
|
||||
w.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
if ((x != null && y == x) || (z != null && y == z))
|
||||
y.length
|
||||
else
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
fun foo(x: String?, y: String?, z: String?) {
|
||||
if ((x!!.hashCode() == 0 || y!!.hashCode() == 1) && z!!.hashCode() == 2) {
|
||||
x.length
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
// condition is true => z!! after and is called
|
||||
z.length
|
||||
}
|
||||
else {
|
||||
x.length
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
z.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
// First element is always analyzed
|
||||
x.length
|
||||
var xx = y ?: z
|
||||
if ((xx!!.hashCode() == 0 && y!!.hashCode() == 1) || z!!.hashCode() == 2) {
|
||||
xx.length
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
z.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
else {
|
||||
xx.length
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
// condition is false => z!! after or is called
|
||||
z.length
|
||||
}
|
||||
// First element is always analyzed
|
||||
x.length
|
||||
xx = y ?: z
|
||||
if (xx!!.hashCode() == 0 && y!!.hashCode() == 1 && z!!.hashCode() == 2) {
|
||||
// all three are called
|
||||
xx.length
|
||||
y.length
|
||||
z.length
|
||||
}
|
||||
else {
|
||||
xx.length
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
z.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
// First element is always analyzed
|
||||
x.length
|
||||
xx = y ?: z
|
||||
if (xx!!.hashCode() == 0 || y!!.hashCode() == 1 || z!!.hashCode() == 2) {
|
||||
xx.length
|
||||
y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
z.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
else {
|
||||
// all three are called
|
||||
xx.length
|
||||
y.length
|
||||
z.length
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package aaa
|
||||
|
||||
fun bar(a: Int, b: Int) {}
|
||||
|
||||
fun foo(a: Int?) {
|
||||
bar(a!!, a)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
interface Foo
|
||||
fun foo(): Foo? = null
|
||||
|
||||
val foo: Foo = run {
|
||||
run {
|
||||
val x = foo()
|
||||
if (x == null) throw Exception()
|
||||
x
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// !LANGUAGE: -BooleanElvisBoundSmartCasts
|
||||
|
||||
interface Order {
|
||||
val expired: Boolean?
|
||||
|
||||
fun notExpired(): Boolean
|
||||
|
||||
fun doSomething()
|
||||
}
|
||||
|
||||
fun foo(o: Any) {
|
||||
val order = o as? Order
|
||||
if (order?.expired ?: false) {
|
||||
order.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
if (order?.notExpired() ?: false) {
|
||||
order.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun bar(o: Any) {
|
||||
val order = o as? Order
|
||||
if (order?.expired ?: true) {
|
||||
|
||||
}
|
||||
else {
|
||||
order!!.doSomething()
|
||||
}
|
||||
if (order?.notExpired() ?: true) {
|
||||
|
||||
}
|
||||
else {
|
||||
order!!.doSomething()
|
||||
}
|
||||
}
|
||||
|
||||
fun baz(o: Boolean?) {
|
||||
if (o ?: false) {
|
||||
o.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
if (o ?: true) {
|
||||
|
||||
}
|
||||
else {
|
||||
o.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// !LANGUAGE: +BooleanElvisBoundSmartCasts
|
||||
|
||||
interface Order {
|
||||
val expired: Boolean?
|
||||
|
||||
fun notExpired(): Boolean
|
||||
|
||||
fun doSomething()
|
||||
}
|
||||
|
||||
fun foo(o: Any) {
|
||||
val order = o as? Order
|
||||
if (order?.expired ?: false) {
|
||||
order.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
if (order?.notExpired() ?: false) {
|
||||
order.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
|
||||
}
|
||||
}
|
||||
|
||||
fun bar(o: Any) {
|
||||
val order = o as? Order
|
||||
if (order?.expired ?: true) {
|
||||
|
||||
}
|
||||
else {
|
||||
order!!.doSomething()
|
||||
}
|
||||
if (order?.notExpired() ?: true) {
|
||||
|
||||
}
|
||||
else {
|
||||
order!!.doSomething()
|
||||
}
|
||||
}
|
||||
|
||||
fun baz(o: Boolean?) {
|
||||
if (o ?: false) {
|
||||
o.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
if (o ?: true) {
|
||||
|
||||
}
|
||||
else {
|
||||
o.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !LANGUAGE: +BooleanElvisBoundSmartCasts
|
||||
// See KT-20752
|
||||
|
||||
class Unstable {
|
||||
val first: String? get() = null
|
||||
}
|
||||
|
||||
class StringList {
|
||||
fun remove(s: String) = s
|
||||
}
|
||||
|
||||
fun StringList.remove(s: String?) = s ?: ""
|
||||
|
||||
fun String.isEmpty() = this == ""
|
||||
|
||||
fun foo(list: StringList, arg: Unstable) {
|
||||
list.remove(arg.first)
|
||||
if (arg.first?.isEmpty() ?: false) {
|
||||
// Should be still resolved to extension, without smart cast or smart cast impossible
|
||||
list.remove(arg.first)
|
||||
}
|
||||
}
|
||||
|
||||
class UnstableBoolean {
|
||||
val first: Boolean? get() = null
|
||||
}
|
||||
|
||||
class BooleanList {
|
||||
fun remove(b: Boolean) = b
|
||||
}
|
||||
|
||||
fun BooleanList.remove(b: Boolean?) = b ?: false
|
||||
|
||||
fun bar(list: BooleanList, arg: UnstableBoolean) {
|
||||
list.remove(arg.first)
|
||||
if (arg.first ?: false) {
|
||||
// Should be still resolved to extension, without smart cast or smart cast impossible
|
||||
list.remove(arg.first)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// Based on KT-9100
|
||||
fun test(x: Any?, y: Any?): Any {
|
||||
val z = x ?: y!!
|
||||
y.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
// !! / ?. is necessary here, because y!! above may not be executed
|
||||
y?.hashCode()
|
||||
y!!.hashCode()
|
||||
return z
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun test(x: Any?): Any {
|
||||
val z = x ?: x!!
|
||||
// x is not null in both branches
|
||||
x.hashCode()
|
||||
return z
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// FILE: p/My.java
|
||||
|
||||
package p;
|
||||
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
class My {
|
||||
@Nullable static String create() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: test.kt
|
||||
|
||||
package p
|
||||
|
||||
fun bar(x: String) = x
|
||||
|
||||
fun test(x: String?): Any {
|
||||
val y = My.create()
|
||||
val z = x ?: y!!
|
||||
bar(y)
|
||||
// !! / ?. is necessary here, because y!! above may not be executed
|
||||
y?.hashCode()
|
||||
y!!.hashCode()
|
||||
return z
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
fun foo(s: Any?): String {
|
||||
val t = when {
|
||||
// To resolve: String U Nothing? = String?
|
||||
s is String -> s
|
||||
else -> null
|
||||
} ?: ""
|
||||
return t
|
||||
}
|
||||
|
||||
fun bar(s: Any?): String {
|
||||
// To resolve: String U Nothing? = String?
|
||||
val t = (if (s == null) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
val u: Any? = null
|
||||
if (u !is String) return ""
|
||||
u
|
||||
}) ?: "xyz"
|
||||
// Ideally we should have smart cast to String here
|
||||
return t
|
||||
}
|
||||
|
||||
fun baz(s: String?, r: String?): String {
|
||||
val t = r ?: when {
|
||||
s != null -> s
|
||||
else -> ""
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
fun withNull(s: String?): String {
|
||||
val t = s ?: null
|
||||
// Error: nullable
|
||||
return t
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class C {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
fun test(a: C?, nn: () -> Nothing?) {
|
||||
a ?: nn()
|
||||
a.<!INAPPLICABLE_CANDIDATE!>foo<!>()
|
||||
|
||||
a ?: return
|
||||
a.foo()
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
// KT-5335
|
||||
|
||||
fun foo(p1: String?, p2: String?) {
|
||||
if (p2 != null) {
|
||||
val v = p1 ?: p2
|
||||
val size = v.length
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// !LANGUAGE: +SoundSmartcastForEnumEntries
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// SKIP_TXT
|
||||
|
||||
enum class Message(val text: String?) {
|
||||
HELLO("hello"),
|
||||
WORLD("world"),
|
||||
NOTHING(null)
|
||||
}
|
||||
|
||||
fun printMessages() {
|
||||
Message.HELLO.text!!
|
||||
Message.HELLO.text.length
|
||||
|
||||
Message.NOTHING.text.length
|
||||
|
||||
Message.NOTHING.text!!
|
||||
Message.NOTHING.text.length
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// !LANGUAGE: -SoundSmartcastForEnumEntries
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// SKIP_TXT
|
||||
|
||||
enum class Message(val text: String?) {
|
||||
HELLO("hello"),
|
||||
WORLD("world"),
|
||||
NOTHING(null)
|
||||
}
|
||||
|
||||
fun printMessages() {
|
||||
Message.HELLO.text!!
|
||||
Message.HELLO.text.length
|
||||
|
||||
Message.NOTHING.text.length
|
||||
|
||||
Message.NOTHING.text!!
|
||||
Message.NOTHING.text.length
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
fun foo(x: String?) = x
|
||||
|
||||
class Test
|
||||
|
||||
class TestWithEquals {
|
||||
override fun equals(other: Any?) = super.equals(other)
|
||||
}
|
||||
|
||||
fun bar(i: Test?) {
|
||||
if (i == null) <!INAPPLICABLE_CANDIDATE!>foo<!>(i)
|
||||
}
|
||||
|
||||
fun bar(i: TestWithEquals?) {
|
||||
if (i == null) <!INAPPLICABLE_CANDIDATE!>foo<!>(i)
|
||||
if (null == i) <!INAPPLICABLE_CANDIDATE!>foo<!>(i)
|
||||
when (i) {
|
||||
null -> <!INAPPLICABLE_CANDIDATE!>foo<!>(i)
|
||||
}
|
||||
}
|
||||
|
||||
fun gav(i: TestWithEquals?, j: TestWithEquals?) {
|
||||
if (j == null) {
|
||||
if (i == j) <!INAPPLICABLE_CANDIDATE!>foo<!>(i)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class D(val a: String, val b: Boolean)
|
||||
|
||||
fun foo(p: Boolean, v: D?): String {
|
||||
if (p && v!!.b) v.a
|
||||
else v.<!INAPPLICABLE_CANDIDATE!>a<!>
|
||||
if (p && v!! == D("?", false)) v.a
|
||||
else v.<!INAPPLICABLE_CANDIDATE!>a<!>
|
||||
if (p || v!!.b) v.<!INAPPLICABLE_CANDIDATE!>a<!>
|
||||
else v.a
|
||||
if (p || v!! == D("?", false)) v.<!INAPPLICABLE_CANDIDATE!>a<!>
|
||||
else v.a
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
class ExplicitAccessorForAnnotation {
|
||||
val tt: String? = "good"
|
||||
get
|
||||
|
||||
fun foo(): String {
|
||||
if (tt is String) {
|
||||
return tt
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class Your
|
||||
|
||||
fun Your.foo() = Any()
|
||||
|
||||
fun <T> T?.let(f: (T) -> Unit) {
|
||||
if (this != null) f(this)
|
||||
}
|
||||
|
||||
fun test(your: Your?) {
|
||||
(your?.foo() as? Any)?.let {}
|
||||
// strange smart cast to 'Your' at this point
|
||||
your.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
abstract class Base {
|
||||
override fun equals(other: Any?) = other is Base
|
||||
}
|
||||
|
||||
class Derived1 : Base() {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class Derived2 : Base()
|
||||
|
||||
fun check(x1: Derived1, x: Base) {
|
||||
if (x1 == x) {
|
||||
// Smart cast here will provoke CCA
|
||||
x.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
if (x1 === x) {
|
||||
// OK
|
||||
x.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
if (x1 !== x) {} else {
|
||||
// OK
|
||||
x.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
}
|
||||
|
||||
class FinalClass { // <-- 'equals' on instances of this class is useful for smart casts
|
||||
fun use() {}
|
||||
|
||||
fun equals(x: Int): Boolean = x > 42
|
||||
}
|
||||
|
||||
fun foo(x: FinalClass?, y: Any) {
|
||||
if (x == y) {
|
||||
// OK
|
||||
x.hashCode()
|
||||
// OK
|
||||
y.<!UNRESOLVED_REFERENCE!>use<!>()
|
||||
}
|
||||
when (x) {
|
||||
// OK (equals from FinalClass)
|
||||
y -> y.<!UNRESOLVED_REFERENCE!>use<!>()
|
||||
}
|
||||
when (y) {
|
||||
// ERROR (equals from Any)
|
||||
x -> y.<!UNRESOLVED_REFERENCE!>use<!>()
|
||||
}
|
||||
}
|
||||
|
||||
open class OpenClass {
|
||||
override fun equals(other: Any?) = other is OpenClass
|
||||
}
|
||||
|
||||
interface Dummy // should not influence anything
|
||||
|
||||
class FinalClass2 : Dummy, OpenClass() { // but here not
|
||||
fun use() {}
|
||||
}
|
||||
|
||||
fun bar(x: FinalClass2?, y: Any) {
|
||||
if (x == y) {
|
||||
// OK
|
||||
x.hashCode()
|
||||
// ERROR
|
||||
y.<!UNRESOLVED_REFERENCE!>use<!>()
|
||||
}
|
||||
}
|
||||
|
||||
open class OpenClass2 // and here too
|
||||
|
||||
fun bar(x: OpenClass2?, y: Any) {
|
||||
if (x == y) {
|
||||
// OK
|
||||
x.hashCode()
|
||||
// ERROR
|
||||
y.<!UNRESOLVED_REFERENCE!>use<!>()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Sealed {
|
||||
override fun equals(other: Any?) = other is Sealed
|
||||
|
||||
class Sealed1 : Sealed() {
|
||||
fun gav() {}
|
||||
}
|
||||
|
||||
object Sealed2 : Sealed()
|
||||
|
||||
fun check(arg: Sealed1) {
|
||||
if (arg == this) {
|
||||
// Smart cast here will provoke CCA
|
||||
this.<!UNRESOLVED_REFERENCE!>gav<!>()
|
||||
<!UNRESOLVED_REFERENCE!>gav<!>()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
open class SuperFoo {
|
||||
public fun bar(): String {
|
||||
if (this is Foo) {
|
||||
superFoo()
|
||||
return baz()
|
||||
}
|
||||
return baz()
|
||||
}
|
||||
|
||||
public fun baz() = "OK"
|
||||
}
|
||||
|
||||
class Foo : SuperFoo() {
|
||||
public fun superFoo() {}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// See KT-10276
|
||||
|
||||
class Bar() {
|
||||
var test: String? = null
|
||||
fun foo() {
|
||||
if (test != null) {
|
||||
// No warning: test is a mutable property
|
||||
test?.hashCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// !DIAGNOSTICS: -UNNECESSARY_NOT_NULL_ASSERTION
|
||||
// See KT-9126: Variable change does not affect data flow info for its fields
|
||||
|
||||
class My(val x: Int?)
|
||||
|
||||
fun foo() {
|
||||
var y: My? = My(42)
|
||||
if (y!!.x != null) {
|
||||
y = My(null)
|
||||
y!!.x.hashCode()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
val x: Int? = 0
|
||||
get() {
|
||||
if (field != null) return field.hashCode()
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// !DIAGNOSTICS: -UNNECESSARY_NOT_NULL_ASSERTION
|
||||
// Advancement of KT-9126
|
||||
|
||||
class My(val x: Int?) {
|
||||
operator fun plus(y: My) = if (this.x != null) this else y
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
var y: My? = My(42)
|
||||
if (y!!.x != null) {
|
||||
y = My(null)
|
||||
(y + My(0)).x.hashCode()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// See also KT-7801
|
||||
class A
|
||||
|
||||
fun <T> test(v: T): T {
|
||||
val a: T = if (v !is A) v else v
|
||||
return a
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class Wrapper<T>(var x: T)
|
||||
|
||||
inline fun <reified T> change(w: Wrapper<T>, x: Any?) {
|
||||
if (x is T) {
|
||||
w.x = x
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fun baz(s: String?): String {
|
||||
val t = if (s == null) {
|
||||
""
|
||||
}
|
||||
else if (s == "") {
|
||||
val u: String? = null
|
||||
if (u == null) return ""
|
||||
u
|
||||
}
|
||||
else {
|
||||
s
|
||||
}
|
||||
return t
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fun baz(s: String?, b: Boolean?): String {
|
||||
val t = if (if (b == null) return "" else b) {
|
||||
if (s == null) return ""
|
||||
s
|
||||
}
|
||||
else {
|
||||
if (s != null) return s
|
||||
""
|
||||
}
|
||||
return t
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fun baz(s: String?, u: String?): String {
|
||||
val t = when(if (u == null) return "" else u) {
|
||||
"abc" -> u
|
||||
"" -> {
|
||||
if (s == null) return ""
|
||||
s
|
||||
}
|
||||
else -> u
|
||||
}
|
||||
return t
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fun baz(s: String?): String {
|
||||
// If String type is given explicitly, problem disappears
|
||||
val t = if (s == null) {
|
||||
""
|
||||
}
|
||||
else {
|
||||
val u: String? = null
|
||||
if (u == null) return ""
|
||||
// !! is detected as unnecessary here
|
||||
u
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
fun foo(s: String?): String {
|
||||
if (s == null) return ""
|
||||
val t = if (s == "abc") s else "xyz"
|
||||
return t
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fun baz(s: String?): String {
|
||||
val t = if (s == null) {
|
||||
""
|
||||
}
|
||||
else {
|
||||
val u: String? = null
|
||||
when (u) {
|
||||
null -> ""
|
||||
else -> u
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
open class A {
|
||||
class B : A() {
|
||||
val a = "FAIL"
|
||||
}
|
||||
|
||||
class C : A() {
|
||||
val a = "FATAL"
|
||||
}
|
||||
|
||||
fun foo(): String {
|
||||
if (this is B) return a
|
||||
else if (this is C) return a
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
fun A?.bar() {
|
||||
if (this != null) foo()
|
||||
}
|
||||
|
||||
fun A.gav() = if (this is A.B) a else ""
|
||||
|
||||
class C {
|
||||
fun A?.complex(): String {
|
||||
if (this is A.B) return a
|
||||
else if (this != null) return foo()
|
||||
else return ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
open class A {
|
||||
open fun foo() = "FAIL"
|
||||
|
||||
fun bar() = if (this is C) foo() else "FAIL"
|
||||
}
|
||||
|
||||
open class B : A()
|
||||
|
||||
open class C : B() {
|
||||
override fun foo() = "OK"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
class IncDec {
|
||||
operator fun inc(): Unit {}
|
||||
}
|
||||
|
||||
fun foo(): IncDec {
|
||||
var x = IncDec()
|
||||
x = x++
|
||||
x++
|
||||
return x
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package a
|
||||
|
||||
fun <T> foo(u: T, v: T): T = u
|
||||
|
||||
fun test(s: String?) {
|
||||
val r: String = foo(s!!, s)
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !CHECK_TYPE
|
||||
|
||||
package a
|
||||
|
||||
fun <T> id(t: T): T = t
|
||||
|
||||
fun <T> two(u: T, v: T): T = u
|
||||
|
||||
fun <T> three(a: T, b: T, c: T): T = c
|
||||
|
||||
interface A
|
||||
interface B: A
|
||||
interface C: A
|
||||
|
||||
fun test(a: A, b: B, c: C) {
|
||||
if (a is B && a is C) {
|
||||
val d: C = id(a)
|
||||
val e: Any = id(a)
|
||||
val f = id(a)
|
||||
checkSubtype<A>(f)
|
||||
val g = two(a, b)
|
||||
checkSubtype<B>(g)
|
||||
checkSubtype<A>(g)
|
||||
|
||||
// smart cast isn't needed, but is reported due to KT-4294
|
||||
val h: Any = two(a, b)
|
||||
|
||||
val k = three(a, b, c)
|
||||
checkSubtype<A>(k)
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><B>(k)
|
||||
val l: Int = three(a, b, c)
|
||||
|
||||
use(d, e, f, g, h, k, l)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> foo(t: T, l: MutableList<T>): T = t
|
||||
|
||||
fun testErrorMessages(a: A, ml: MutableList<String>) {
|
||||
if (a is B && a is C) {
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(a, ml)
|
||||
}
|
||||
|
||||
if(a is C) {
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(a, ml)
|
||||
}
|
||||
}
|
||||
|
||||
fun rr(s: String?) {
|
||||
if (s != null) {
|
||||
val l = arrayListOf("", s)
|
||||
checkSubtype<MutableList<String>>(l)
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><MutableList<String?>>(l)
|
||||
}
|
||||
}
|
||||
|
||||
//from library
|
||||
fun <T> arrayListOf(vararg values: T): MutableList<T> = throw Exception()
|
||||
|
||||
fun use(vararg a: Any) = a
|
||||
@@ -0,0 +1,11 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
fun foo(s : String?, b : Boolean) {
|
||||
if (s == null) return
|
||||
|
||||
val s1 = if (b) "" else s
|
||||
s1 checkType { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
|
||||
val s2 = s
|
||||
s2 checkType { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//KT-1355 Type inference fails with smartcast and generic function
|
||||
//tests for Map.set
|
||||
package a
|
||||
|
||||
import java.util.HashMap
|
||||
|
||||
fun foo(map: MutableMap<Int, String>, value: String?) {
|
||||
if (value != null) {
|
||||
map.put(1, value) //ok
|
||||
map.set(1, value) //type inference failed
|
||||
map[1] = value //type inference failed
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
|
||||
public data class Tag(public var tagName: String) {
|
||||
public val attributes: MutableMap<String, String> = HashMap<String, String>()
|
||||
public val contents: MutableList<Tag> = arrayListOf()
|
||||
|
||||
public var id: String?
|
||||
get() = attributes["id"]
|
||||
set(value) {
|
||||
if(value == null) {
|
||||
attributes.remove("id")
|
||||
}
|
||||
else {
|
||||
attributes["id"] = value!!
|
||||
attributes["id"] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//from library
|
||||
operator fun <K, V> MutableMap<K, V>.set(key : K, value : V) = this.put(key, value)
|
||||
|
||||
fun <T> arrayListOf(vararg values: T): MutableList<T> = throw Exception()
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// ISSUE: KT-25432
|
||||
|
||||
class Data<T>(val s: T)
|
||||
|
||||
fun test(d: Data<out Any>) {
|
||||
if (d.s is String) {
|
||||
d.s.length
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//KT-2746 Do.smartcasts in inference
|
||||
|
||||
class C<T>(t :T)
|
||||
|
||||
fun test1(a: Any) {
|
||||
if (a is String) {
|
||||
val c: C<String> = C(a)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun <T> f(t :T): C<T> = C(t)
|
||||
|
||||
fun test2(a: Any) {
|
||||
if (a is String) {
|
||||
val c1: C<String> = f(a)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
//KT-2851 Type inference failed passing in not-null after smart-cast value in Pair
|
||||
package a
|
||||
|
||||
fun main() {
|
||||
val value: String? = ""
|
||||
if (value != null) {
|
||||
foo(Pair("val", value))
|
||||
foo(Pair("val", value!!))
|
||||
foo(Pair<String, String>("val", value))
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(map: Pair<String, String>) {}
|
||||
|
||||
|
||||
//from library
|
||||
public class Pair<out A, out B> (
|
||||
public val first: A,
|
||||
public val second: B
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// ISSUE: KT-29767
|
||||
|
||||
fun test(a: MutableList<out Int?>?) {
|
||||
if (a != null) {
|
||||
val b = a[0] // no SMARTCAST diagnostic
|
||||
if (b != null) {
|
||||
b.inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
interface PsiElement {
|
||||
fun getText(): String
|
||||
fun getParent(): PsiElement
|
||||
}
|
||||
|
||||
interface JetExpression : PsiElement
|
||||
|
||||
fun foo1(e: PsiElement) {
|
||||
var current: PsiElement? = e
|
||||
var first = true
|
||||
while (current != null) {
|
||||
if (current is JetExpression && first) {
|
||||
// Smartcast is possible here
|
||||
println(current.getText())
|
||||
}
|
||||
|
||||
current = current.getParent()
|
||||
}
|
||||
}
|
||||
|
||||
//from library
|
||||
fun println(any: Any?): Nothing = throw Exception("$any")
|
||||
@@ -0,0 +1,11 @@
|
||||
//KT-4403 Wrong "type mismatch" on smart cast with inference
|
||||
|
||||
interface A
|
||||
interface B : A
|
||||
|
||||
fun <T> T.f(): T = this
|
||||
|
||||
fun test(a: A) {
|
||||
if (a !is B) return
|
||||
val c = a.f() // type mismatch
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
//KT-4415 Class Auto-Cast Bug
|
||||
|
||||
interface SelfJson
|
||||
|
||||
object A {
|
||||
fun find(clz:Class<*>){ }
|
||||
|
||||
fun toJson2(obj:Any){
|
||||
if(obj is SelfJson){
|
||||
// A.find( (obj as SelfJson).javaClass) // OK
|
||||
A.find( obj.javaClass ) // ERROR: Type mismatch: inferred type is kotlin.Any but SelfJson was expected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//from library
|
||||
val <T> T.javaClass : Class<T> get() = throw Exception()
|
||||
@@ -0,0 +1,12 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
|
||||
inline fun<T> foo(block: () -> T):T = block()
|
||||
|
||||
fun baz() {
|
||||
val x: String = foo {
|
||||
val task: String? = null
|
||||
if (task == null) {
|
||||
return
|
||||
} else task
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
interface A
|
||||
interface B
|
||||
|
||||
class Test {
|
||||
fun test(a: A?, b: B, list: MutableList<Pair<A, B>>) {
|
||||
if (a != null) {
|
||||
list.add(a to b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Pair<out A, out B>(val first: A, val second: B)
|
||||
infix fun <A, B> A.to(that: B) = Pair(this, that)
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
interface A {
|
||||
fun <T, E> foo(): E
|
||||
}
|
||||
|
||||
interface B {
|
||||
fun <Q, W> foo(): Q
|
||||
}
|
||||
|
||||
fun test(c: Any) {
|
||||
if (c is B && c is A) {
|
||||
c.<!AMBIGUITY!>foo<!><String, Int>()
|
||||
}
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
interface A {
|
||||
fun foo(): CharSequence
|
||||
}
|
||||
|
||||
interface B {
|
||||
fun foo(): String?
|
||||
}
|
||||
|
||||
fun test(c: Any) {
|
||||
if (c is B && c is A) {
|
||||
c.<!AMBIGUITY!>foo<!>()
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !CHECK_TYPE
|
||||
// FILE: A.java
|
||||
public interface A {
|
||||
String foo();
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
interface B {
|
||||
fun foo(): String?
|
||||
}
|
||||
|
||||
interface C {
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
fun foo(x: Any?) {
|
||||
if (x is A && x is B) {
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() }
|
||||
}
|
||||
|
||||
if (x is B && x is A) {
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() }
|
||||
}
|
||||
|
||||
if (x is A && x is C) {
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() }
|
||||
}
|
||||
|
||||
if (x is C && x is A) {
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() }
|
||||
}
|
||||
|
||||
if (x is A && x is B && x is C) {
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() }
|
||||
}
|
||||
|
||||
if (x is B && x is A && x is C) {
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() }
|
||||
}
|
||||
|
||||
if (x is B && x is C && x is A) {
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String?>() }
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
open class A {
|
||||
open var value: Int = 4
|
||||
protected set
|
||||
}
|
||||
|
||||
class MutableA : A() {
|
||||
override var value: Int = 4
|
||||
public set
|
||||
}
|
||||
|
||||
fun test(myA: A) {
|
||||
if (myA is MutableA) {
|
||||
myA.value = 5
|
||||
}
|
||||
}
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
abstract class A {
|
||||
abstract protected fun foo(): String
|
||||
abstract protected val bar: String
|
||||
}
|
||||
|
||||
interface B {
|
||||
fun foo(): String
|
||||
val bar: String
|
||||
}
|
||||
|
||||
fun test(x: A) {
|
||||
if (x is B) {
|
||||
x.foo()
|
||||
x.bar
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
interface Common {
|
||||
fun foo(): CharSequence?
|
||||
}
|
||||
|
||||
interface A : Common {
|
||||
override fun foo(): CharSequence
|
||||
}
|
||||
|
||||
interface B : Common {
|
||||
override fun foo(): String
|
||||
}
|
||||
|
||||
fun test(c: Common) {
|
||||
if (c is B && c is A) {
|
||||
c.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
}
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
interface A {
|
||||
fun foo(): CharSequence?
|
||||
}
|
||||
|
||||
interface B {
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
fun test(c: Any) {
|
||||
if (c is B && c is A) {
|
||||
c.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
interface A {
|
||||
val foo: Any?
|
||||
}
|
||||
|
||||
interface C: A {
|
||||
override val foo: String?
|
||||
}
|
||||
interface B: A {
|
||||
override var foo: String
|
||||
}
|
||||
|
||||
fun test(a: A) {
|
||||
if (a is B && a is C) {
|
||||
a.<!AMBIGUITY!>foo<!> = ""
|
||||
a.<!AMBIGUITY!>foo<!> = null
|
||||
|
||||
a.<!AMBIGUITY!>foo<!>.<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
interface A {
|
||||
val foo: Any?
|
||||
}
|
||||
|
||||
interface C: A {
|
||||
override val foo: String
|
||||
}
|
||||
interface B: A {
|
||||
override var foo: String?
|
||||
}
|
||||
|
||||
fun test(a: A) {
|
||||
if (a is B && a is C) {
|
||||
a.<!AMBIGUITY!>foo<!> = ""
|
||||
a.<!AMBIGUITY!>foo<!> = null
|
||||
a.<!AMBIGUITY!>foo<!>
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
interface A {
|
||||
fun foo(): CharSequence?
|
||||
}
|
||||
|
||||
interface B : A {
|
||||
override fun foo(): String
|
||||
}
|
||||
|
||||
fun test(a: A) {
|
||||
if (a is B) {
|
||||
a.foo()
|
||||
a.foo().checkType { _<String>() }
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
interface A {
|
||||
fun foo()
|
||||
}
|
||||
|
||||
interface C: A
|
||||
interface B: A
|
||||
|
||||
fun test(c: C) {
|
||||
if (c is B) {
|
||||
c.foo() // OVERLOAD_RESOLUTION_AMBIGUITY: B.foo() and C.foo()
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !CHECK_TYPE
|
||||
|
||||
interface A {
|
||||
fun foo(): CharSequence?
|
||||
fun baz(x: Any) {}
|
||||
}
|
||||
|
||||
interface B {
|
||||
fun foo(): String
|
||||
fun baz(x: Int): String =""
|
||||
fun baz(x: Int, y: Int) {}
|
||||
|
||||
fun foobar(): CharSequence?
|
||||
}
|
||||
|
||||
interface C {
|
||||
fun foo(): String
|
||||
fun baz(x: Int): String =""
|
||||
fun baz(x: Int, y: Int) {}
|
||||
|
||||
fun foobar(): String
|
||||
}
|
||||
|
||||
var x: A = null!!
|
||||
|
||||
fun test() {
|
||||
x.foo().checkType { _<CharSequence?>() }
|
||||
|
||||
if (x is B && x is C) {
|
||||
x.<!AMBIGUITY!>foo<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><CharSequence?>() }
|
||||
x.baz("")
|
||||
x.<!AMBIGUITY!>baz<!>(1).<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Unit>() }
|
||||
x.<!AMBIGUITY!>baz<!>(1, 2)
|
||||
|
||||
x.<!AMBIGUITY!>foobar<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
}
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
interface A {
|
||||
fun <T, E> foo(): E
|
||||
}
|
||||
|
||||
interface B {
|
||||
fun <Q, W> foo(): W
|
||||
}
|
||||
|
||||
fun test(c: Any) {
|
||||
if (c is B && c is A) {
|
||||
c.<!AMBIGUITY!>foo<!><String, Int>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
interface A {
|
||||
fun <T, E> foo(): E
|
||||
}
|
||||
|
||||
interface B : A {
|
||||
override fun <Q, W> foo(): W
|
||||
}
|
||||
|
||||
fun test(a: A) {
|
||||
if (a is B) {
|
||||
a.foo<String, Int>().checkType { _<Int>() }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Type inference failed after smart cast
|
||||
|
||||
interface A<T>
|
||||
interface B<T> : A<T>
|
||||
|
||||
fun <T> foo(b: A<T>) = b
|
||||
|
||||
fun <T> test(a: A<T>) {
|
||||
if (a is Any) {
|
||||
// Error:(9, 9) Kotlin: Type inference failed: fun <T> foo(b: A<T>): kotlin.Unit
|
||||
// cannot be applied to (A<T>)
|
||||
foo(a)
|
||||
}
|
||||
foo(a) // ok
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// KT-10444 Do not ignore smart (unchecked) casts to the same classifier
|
||||
|
||||
class Qwe<T : Any>(val a: T?) {
|
||||
fun test1(obj: Any) {
|
||||
obj as Qwe<T>
|
||||
check(obj.a)
|
||||
}
|
||||
|
||||
fun test1(obj: Qwe<*>) {
|
||||
obj as Qwe<T>
|
||||
check(obj.a)
|
||||
}
|
||||
|
||||
fun check(a: T?) {
|
||||
}
|
||||
}
|
||||
|
||||
open class Foo
|
||||
open class Bar<T: Foo>(open val a: T?, open val b: T?) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun compare(obj: Any) {
|
||||
if (obj !is Bar<*>) {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
if (System.currentTimeMillis() > 100) {
|
||||
val b = (obj as Bar<T>).b
|
||||
if (b == null) throw IllegalArgumentException()
|
||||
check(obj.a, b)
|
||||
}
|
||||
}
|
||||
fun check(a: T?, b: T) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
interface A
|
||||
class B : A {
|
||||
operator fun invoke() = this
|
||||
}
|
||||
|
||||
class C : A
|
||||
|
||||
operator fun C.invoke(): B = B()
|
||||
|
||||
fun foo(arg: A): B? {
|
||||
if (arg is B) return arg()
|
||||
|
||||
if (arg is C) return arg()
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//KT-1461 Front-end complains on overload resolution when superclass property is accessed from string template and implicit type cast is performed
|
||||
package f
|
||||
|
||||
open class Super(val property : String) {}
|
||||
|
||||
class Sub(str : String) : Super(str) {}
|
||||
|
||||
fun foo(sup : Super, sub : Sub) {
|
||||
if (sup is Sub) {
|
||||
println("${sup.property}")
|
||||
println(sup.property)
|
||||
}
|
||||
println("${sub.property}")
|
||||
println(sub.property)
|
||||
}
|
||||
|
||||
//from library
|
||||
fun println(message : Any?) { throw Exception() }
|
||||
@@ -0,0 +1,23 @@
|
||||
package bar
|
||||
|
||||
class Test {
|
||||
val foo: Int? = null
|
||||
fun foo(o: Test) = foo == null && o.foo == null // ERROR warning: o.test == null is always true
|
||||
|
||||
fun bar(a: Test, b: Test) {
|
||||
if (a.foo != null) {
|
||||
useInt(b.foo)
|
||||
}
|
||||
if (a.foo != null) {
|
||||
useInt(foo)
|
||||
}
|
||||
if (this.foo != null) {
|
||||
useInt(foo)
|
||||
}
|
||||
if (foo != null) {
|
||||
useInt(this.foo)
|
||||
}
|
||||
}
|
||||
|
||||
fun useInt(i: Int) = i
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// SKIP_TXT
|
||||
|
||||
sealed class A
|
||||
sealed class B : A()
|
||||
sealed class C : B()
|
||||
object BB : B()
|
||||
object CC : C()
|
||||
|
||||
fun foo(a: A) {
|
||||
if (a is B) {
|
||||
if (a is C) {
|
||||
val t = when (a) {
|
||||
is CC -> "CC"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun foo2(a: A) {
|
||||
if (a is C) {
|
||||
if (a is B) {
|
||||
val t = when (a) {
|
||||
is CC -> "CC"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// SKIP_TXT
|
||||
|
||||
sealed class A
|
||||
sealed class B : A()
|
||||
sealed class C : B()
|
||||
sealed class D : C()
|
||||
object BB : B()
|
||||
object CC : C()
|
||||
object DD : D()
|
||||
|
||||
fun foo1(a: A) {
|
||||
if (a is B) {
|
||||
if (a is D) {
|
||||
if (a is C) {
|
||||
val t =
|
||||
when (a) {
|
||||
is DD -> "DD"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun foo2(a: A) {
|
||||
if (a is B) {
|
||||
if (a is D) {
|
||||
if (a is C) {
|
||||
val t =
|
||||
when (a) {
|
||||
is DD -> "DD"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// SKIP_TXT
|
||||
|
||||
sealed class A
|
||||
sealed class B : A()
|
||||
sealed class C : A()
|
||||
object BB : B()
|
||||
object CC : C()
|
||||
|
||||
fun foo(a: A) {
|
||||
if (a is B) {
|
||||
if (a is C) {
|
||||
val t = when (a) {
|
||||
is CC -> "CC"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun foo2(a: A) {
|
||||
if (a is C) {
|
||||
if (a is B) {
|
||||
val t = when (a) {
|
||||
is CC -> "CC"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
operator fun <K, V> MutableMap<K, V>.set(k: K, v: V) {}
|
||||
|
||||
fun foo(a: MutableMap<String, String>, x: String?) {
|
||||
a[x!!] = x
|
||||
a[x] = x!!
|
||||
}
|
||||
|
||||
fun foo1(a: MutableMap<String, String>, x: String?) {
|
||||
a[x] = x!!
|
||||
a[x!!] = x
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
// Issue: KT-30826
|
||||
|
||||
interface I1
|
||||
interface I2 {
|
||||
fun foo() {}
|
||||
}
|
||||
|
||||
class A : I1, I2
|
||||
|
||||
fun foo(x: I1?) {
|
||||
var y = x
|
||||
y as I2
|
||||
val bar = {
|
||||
y.foo() // NPE in NI, smartcast impossible in OI
|
||||
}
|
||||
y = null
|
||||
bar()
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION
|
||||
// !WITH_NEW_INFERENCE
|
||||
// !CHECK_TYPE
|
||||
|
||||
fun case_0() {
|
||||
val z: Any? = 10
|
||||
val y = z.run {
|
||||
this as Int
|
||||
this // error in NI: required Int, found Any?; just inferred to Any? in OI
|
||||
}
|
||||
y checkType { <!UNRESOLVED_REFERENCE!>_<!><Any?>() }
|
||||
y checkType { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
|
||||
}
|
||||
|
||||
fun case_1(z: Any?) {
|
||||
val y = z.run {
|
||||
when (this) {
|
||||
is String -> return@run this // type mismatch in the new inference (required String, found Any?)
|
||||
is Float -> ""
|
||||
else -> return@run ""
|
||||
}
|
||||
}
|
||||
y checkType { <!UNRESOLVED_REFERENCE!>_<!><Any?>() }
|
||||
y checkType { <!UNRESOLVED_REFERENCE!>_<!><kotlin.String>() }
|
||||
// y is inferred to Any?
|
||||
}
|
||||
|
||||
fun case_2(z: Any?) {
|
||||
val y = z.run {
|
||||
when (this) {
|
||||
is String -> this
|
||||
is Float -> ""
|
||||
else -> return@run ""
|
||||
}
|
||||
}
|
||||
y checkType { <!UNRESOLVED_REFERENCE!>_<!><kotlin.String>() }
|
||||
// y is inferred to String
|
||||
}
|
||||
|
||||
fun case_3(z: Any?) {
|
||||
val y = z.let {
|
||||
when (it) {
|
||||
is String -> return@let it
|
||||
is Float -> ""
|
||||
else -> return@let ""
|
||||
}
|
||||
}
|
||||
y checkType { <!UNRESOLVED_REFERENCE!>_<!><Any?>() }
|
||||
y checkType { <!UNRESOLVED_REFERENCE!>_<!><kotlin.String>() }
|
||||
// y is inferred to String
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Works already in M11
|
||||
|
||||
fun test(c : Class<*>) {
|
||||
val sc = c as Class<String>
|
||||
// No ambiguous overload
|
||||
c.getAnnotations();
|
||||
sc.getAnnotations();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Should work already in M11
|
||||
|
||||
open class A(val s : String)
|
||||
class B(s : String) : A(s)
|
||||
|
||||
fun test(a : A): String? {
|
||||
if (a is B) {
|
||||
// Earlier (14.01.2013) reported overload ambiguity over s
|
||||
return a.s
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
interface Printer {
|
||||
fun print()
|
||||
}
|
||||
|
||||
class OKPrinter : Printer {
|
||||
override fun print() { }
|
||||
}
|
||||
|
||||
class MyClass(var printer: Printer)
|
||||
|
||||
|
||||
fun main(m: MyClass) {
|
||||
if (m.printer is OKPrinter) {
|
||||
// We do not need smart cast here, so we should not get SMARTCAST_IMPOSSIBLE
|
||||
m.printer.print()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
data class StringPair(val first: String, val second: String)
|
||||
|
||||
infix fun String.to(second: String) = StringPair(this, second)
|
||||
|
||||
fun f(a: String?) {
|
||||
if (a != null) {
|
||||
val b: StringPair = a to a
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
data class StringPair(val first: String, val second: String)
|
||||
|
||||
infix fun String.to(second: String) = StringPair(this, second)
|
||||
|
||||
fun hashMapOf(pair: StringPair): MutableMap<String, String> {
|
||||
}
|
||||
|
||||
fun F() : MutableMap<String, String> {
|
||||
val value: String? = "xyz"
|
||||
if (value == null) throw Error()
|
||||
// Smart cast should be here
|
||||
return hashMapOf("sss" to value)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
class User(val login : Boolean) {}
|
||||
|
||||
fun currentAccess(user: User?): Int {
|
||||
return when {
|
||||
user == null -> 0
|
||||
// We should get smartcast here
|
||||
user.login -> 1
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo(p: String?): Int {
|
||||
// We should get smart cast here
|
||||
val x = if (p != null) { p } else "a"
|
||||
return x.length
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//KT-5455 Need warning about redundant type cast
|
||||
fun foo(o: Any): Int {
|
||||
if (o is String) {
|
||||
return (o as String).length
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
open class A {
|
||||
fun foo() {}
|
||||
}
|
||||
class B: A()
|
||||
|
||||
fun test(a: Any?) {
|
||||
if (a is B) {
|
||||
(a as A).foo()
|
||||
}
|
||||
}
|
||||
|
||||
fun test1(a: B) {
|
||||
(a as A?)?.foo()
|
||||
}
|
||||
|
||||
fun test2(b: B?) {
|
||||
if (b != null) {
|
||||
(b as A).foo()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public fun test(o: String?): Boolean {
|
||||
return when {
|
||||
// Data flow info should propagate from o == null to o.length
|
||||
o == null, o.length == 0 -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Test for a potential byte code mistake for a postfix operation on a smart casted variable
|
||||
public fun box() : Int {
|
||||
var i : Int?
|
||||
i = 10
|
||||
val ii: Int = i
|
||||
// k also should be Int
|
||||
val k : Int = i++
|
||||
// KT-7561: both i and i++ should be Int, otherwise VerifyError can arise here
|
||||
// VerifyError reason: byte code tries to store (i++) result which is Int (smart cast)
|
||||
// into a j which is Int?
|
||||
val j = i++
|
||||
// and m also
|
||||
val m = ++i
|
||||
return j + k + m + i + ii
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// !DIAGNOSTICS: -NOTHING_TO_INLINE
|
||||
|
||||
inline fun <T> foo(t1: T, t2: T) = t1 ?: t2
|
||||
|
||||
inline fun <T> bar(l: (T) -> Unit): T = null!!
|
||||
|
||||
fun use() {
|
||||
var x: Int?
|
||||
x = 5
|
||||
// Write is AFTER
|
||||
x.hashCode()
|
||||
// x is nullable at the second argument
|
||||
foo(bar { x = null }, x!!)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// !DIAGNOSTICS: -NOTHING_TO_INLINE
|
||||
// See KT-9143: smart cast on a variable nulled inside a lambda argument
|
||||
inline fun <T> foo(t1: T, t2: T) = t1 ?: t2
|
||||
|
||||
inline fun <T> bar(l: (T) -> Unit): T = null!!
|
||||
|
||||
fun use() {
|
||||
var x: Int?
|
||||
x = 5
|
||||
// Write to x is AFTER
|
||||
x.hashCode()
|
||||
// No smart cast should be here!
|
||||
foo(bar { x = null }, x.hashCode())
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
class Indexed<T>(val x: T, val y: Int)
|
||||
|
||||
class Value<out T>(val x: T)
|
||||
|
||||
interface WithValue<out T> {
|
||||
fun value(): Value<T>
|
||||
}
|
||||
|
||||
class Singleton<T>(val x: T) : WithValue<T> {
|
||||
override fun value() = Value(x)
|
||||
}
|
||||
|
||||
class WithValueIndexed<T>(val f: () -> Value<T>) : WithValue<Indexed<T>> {
|
||||
override fun value() = Value(Indexed(f().x, 0))
|
||||
}
|
||||
|
||||
fun <T> Singleton<out T>.indexed(): WithValue<Indexed<T>> {
|
||||
return WithValueIndexed { value() }
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// !WITH_NEW_INFERENCE
|
||||
interface Foo
|
||||
interface Bar : Foo
|
||||
|
||||
fun foo(): Foo? = null
|
||||
fun bar(): Bar? = null
|
||||
|
||||
fun <T : Bar> run(f: () -> T): T = f()
|
||||
|
||||
val foo: Foo = run {
|
||||
val x = bar()
|
||||
if (x == null) throw Exception()
|
||||
x
|
||||
}
|
||||
|
||||
val foofoo: Foo = run {
|
||||
val x = foo()
|
||||
if (x == null) throw Exception()
|
||||
x
|
||||
}
|
||||
|
||||
val bar: Bar = run {
|
||||
val x = foo()
|
||||
if (x == null) throw Exception()
|
||||
x
|
||||
}
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
class My<T: Any>(val y: T?) {
|
||||
|
||||
fun get(): T = run {
|
||||
val x = y
|
||||
if (x == null) throw Exception()
|
||||
x
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user