[FIR] Implement new bound smartcast algorithm
#KT-36055 Fixed
This commit is contained in:
@@ -6,10 +6,10 @@ class A() {
|
||||
fun f(): Unit {
|
||||
var x: Int? = 1
|
||||
x = null
|
||||
x + 1
|
||||
x plus 1
|
||||
x <!INAPPLICABLE_CANDIDATE!>+<!> 1
|
||||
x <!INAPPLICABLE_CANDIDATE!>plus<!> 1
|
||||
x < 1
|
||||
x += 1
|
||||
<!UNRESOLVED_REFERENCE!>x += 1<!>
|
||||
|
||||
x == 1
|
||||
x != 1
|
||||
@@ -22,8 +22,8 @@ fun f(): Unit {
|
||||
x === 1
|
||||
x !== 1
|
||||
|
||||
x..2
|
||||
x in 1..2
|
||||
x<!INAPPLICABLE_CANDIDATE!>..<!>2
|
||||
x <!INAPPLICABLE_CANDIDATE!>in<!> 1..2
|
||||
|
||||
val y : Boolean? = true
|
||||
false || y
|
||||
|
||||
@@ -11,7 +11,7 @@ fun foo() {
|
||||
while (y != null) {
|
||||
bar(y)
|
||||
}
|
||||
bar(y)
|
||||
<!INAPPLICABLE_CANDIDATE!>bar<!>(y)
|
||||
|
||||
val z: Int? = null
|
||||
while (z == null) {
|
||||
|
||||
+1
-1
@@ -22,5 +22,5 @@ fun whileWithNoCondition(x: Int?) {
|
||||
while (<!SYNTAX!><!>) {
|
||||
x!!
|
||||
}
|
||||
checkSubtype<Int>(x)
|
||||
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Int>(x)
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ class A<out T, in E> {
|
||||
fun foo(x: A<String, Any?>, cs: CharSequence, ls: List<CharSequence>) {
|
||||
val y: A<CharSequence, String> = x
|
||||
|
||||
y.foo(cs)
|
||||
val s: String = y.foo(cs, ls)
|
||||
y.<!INAPPLICABLE_CANDIDATE!>foo<!>(cs)
|
||||
val s: String = y.<!INAPPLICABLE_CANDIDATE!>foo<!>(cs, ls)
|
||||
|
||||
val ls2: List<String> = y.bar()
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ class CtxImpl : Ctx {
|
||||
open class Test(open val ctx: Ctx) {
|
||||
fun test() {
|
||||
when (ctx) {
|
||||
is CtxImpl -> ctx.doJob(2)
|
||||
is CtxImpl -> ctx.<!UNRESOLVED_REFERENCE!>doJob<!>(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -9,6 +9,6 @@ var a: A? = null
|
||||
|
||||
fun smartCastInterference(b: B) {
|
||||
if (a != null) {
|
||||
a.foo(b)
|
||||
a.<!INAPPLICABLE_CANDIDATE!>foo<!>(b)
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
fun foo(): String {
|
||||
var s: String?
|
||||
s = null
|
||||
s?.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s?.length
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
if (s == null) return s!!
|
||||
var t: String? = "y"
|
||||
if (t == null) t = "x"
|
||||
|
||||
@@ -41,7 +41,7 @@ fun f(a: SomeClass?) {
|
||||
if (aa as? SomeSubClass != null) {
|
||||
aa = null
|
||||
// 'aa' cannot be cast to SomeSubClass
|
||||
aa.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
aa.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
aa.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(aa as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
(aa as SomeSubClass).foo
|
||||
@@ -50,7 +50,7 @@ fun f(a: SomeClass?) {
|
||||
aa = null
|
||||
if (b != null) {
|
||||
// 'aa' cannot be cast to SomeSubClass
|
||||
aa.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
aa.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
aa.<!UNRESOLVED_REFERENCE!>foo<!>
|
||||
(aa as? SomeSubClass).<!INAPPLICABLE_CANDIDATE!>foo<!>
|
||||
(aa as SomeSubClass).foo
|
||||
|
||||
+4
-4
@@ -28,11 +28,11 @@ fun test() {
|
||||
x.foo().checkType { _<CharSequence?>() }
|
||||
|
||||
if (x is B && x is C) {
|
||||
x.foo().checkType { <!INAPPLICABLE_CANDIDATE!>_<!><CharSequence?>() }
|
||||
x.foo().checkType { _<CharSequence?>() }
|
||||
x.baz("")
|
||||
x.baz(1).checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Unit>() }
|
||||
x.baz(1, 2)
|
||||
x.baz(1).checkType { _<Unit>() }
|
||||
x.<!INAPPLICABLE_CANDIDATE!>baz<!>(1, 2)
|
||||
|
||||
x.foobar().checkType { _<String>() }
|
||||
x.<!UNRESOLVED_REFERENCE!>foobar<!>().<!INAPPLICABLE_CANDIDATE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,5 +6,5 @@ public fun foo(p: String?): Int {
|
||||
if (x()) break
|
||||
}
|
||||
// p is nullable because it's possible loop body is not executed at all
|
||||
return p.length
|
||||
return p.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
@@ -7,5 +7,5 @@ public fun foo(p: String?): Int {
|
||||
if (x()) break
|
||||
}
|
||||
// Smart cast should not work in this case, see KT-6284
|
||||
return p.length
|
||||
return p.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
Vendored
+2
-2
@@ -8,7 +8,7 @@ fun foo() {
|
||||
|
||||
}
|
||||
// TODO: this testdata fixates undesired behavior (it should be an unsafe call)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!> // 'x' is unsoundly smartcasted here
|
||||
x.length // 'x' is unsoundly smartcasted here
|
||||
}
|
||||
|
||||
fun bar() {
|
||||
@@ -19,5 +19,5 @@ fun bar() {
|
||||
|
||||
}
|
||||
// TODO: this testdata fixates undesired behavior (it should be an unsafe call)
|
||||
x.<!UNRESOLVED_REFERENCE!>size<!> // 'x' is unsoundly smartcasted here
|
||||
x.size // 'x' is unsoundly smartcasted here
|
||||
}
|
||||
compiler/testData/diagnostics/tests/smartCasts/loops/whileWithAssertInConditionAndBreakBefore.fir.kt
Vendored
+2
-2
@@ -7,7 +7,7 @@ fun foo() {
|
||||
break
|
||||
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!> // 'x' is unsoundly smartcasted here
|
||||
x.length // 'x' is unsoundly smartcasted here
|
||||
}
|
||||
|
||||
fun bar() {
|
||||
@@ -17,5 +17,5 @@ fun bar() {
|
||||
break
|
||||
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>size<!> // 'x' is unsoundly smartcasted here
|
||||
x.size // 'x' is unsoundly smartcasted here
|
||||
}
|
||||
+1
-1
@@ -9,5 +9,5 @@ fun foo(arg: Int?) {
|
||||
}
|
||||
if (x != null) x = 42
|
||||
// Unsafe because of lambda
|
||||
x.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
x.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@ public class X {
|
||||
public fun fn(): Int {
|
||||
if (y != null)
|
||||
// With non-default getter smartcast is not possible
|
||||
return y.length
|
||||
return y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
else
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ infix fun Int.bar(i: Int) = i
|
||||
fun test() {
|
||||
val p = A()
|
||||
// For open value properties, smart casts should not work
|
||||
if (p.foo is Int) p.foo bar 11
|
||||
if (p.foo is Int) p.foo <!INAPPLICABLE_CANDIDATE!>bar<!> 11
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ public class X {
|
||||
public fun fn(): Int {
|
||||
if (x != null)
|
||||
// Smartcast is not possible for variable properties
|
||||
return x.length
|
||||
return x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
else if (y != null)
|
||||
// Even if they are private
|
||||
return y.length
|
||||
return y.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
else
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -15,6 +15,6 @@ fun bar(): Int {
|
||||
return when(ss) {
|
||||
"abc" -> ss
|
||||
else -> "xyz"
|
||||
}.length
|
||||
}.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ fun test1() {
|
||||
if (newC != null) {
|
||||
c = newC
|
||||
}
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(c)
|
||||
foo(c)
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
@@ -19,7 +19,7 @@ fun test2() {
|
||||
if (newC is String) {
|
||||
c = newC
|
||||
}
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(c)
|
||||
foo(c)
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
@@ -30,6 +30,6 @@ fun test3() {
|
||||
if (newC == null) return
|
||||
c = newC
|
||||
|
||||
<!INAPPLICABLE_CANDIDATE!>foo<!>(c)
|
||||
foo(c)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -6,5 +6,5 @@ fun foo(x: Int, f: () -> Unit, y: Int) {}
|
||||
fun bar() {
|
||||
var x: Int?
|
||||
x = 4
|
||||
foo(x, { x = null; x.<!UNRESOLVED_REFERENCE!>hashCode<!>() }, x)
|
||||
foo(x, { x = null; x.<!INAPPLICABLE_CANDIDATE!>hashCode<!>() }, x)
|
||||
}
|
||||
+1
-1
@@ -13,5 +13,5 @@ fun list(start: String) {
|
||||
e = e.next()
|
||||
}
|
||||
// e can never be null but we do not know it
|
||||
e.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
e.hashCode()
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@ fun foo() {
|
||||
v = "abc"
|
||||
v.length
|
||||
v = null
|
||||
v.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
v.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
v = "abc"
|
||||
v.length
|
||||
}
|
||||
+2
-2
@@ -6,7 +6,7 @@ fun foo() {
|
||||
val y = x
|
||||
x = null
|
||||
if (y != null) {
|
||||
x.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
x.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ fun bar(s: String?) {
|
||||
val hashCode = ss?.hashCode()
|
||||
ss = null
|
||||
if (hashCode != null) {
|
||||
ss.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
ss.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -44,7 +44,7 @@ fun gaz(s: String?) {
|
||||
x = null
|
||||
}
|
||||
run {
|
||||
x.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
x.hashCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -11,11 +11,11 @@ fun list(start: SomeObject) {
|
||||
// In theory smart cast is possible here
|
||||
// But in practice we have a loop with changing e
|
||||
// ?: should we "or" entrance type info with condition type info?
|
||||
if (<!UNRESOLVED_REFERENCE!>!<!>e.<!INAPPLICABLE_CANDIDATE!>doSomething<!>())
|
||||
if (!e.doSomething())
|
||||
break
|
||||
// Smart cast here is still not possible
|
||||
e = e.<!INAPPLICABLE_CANDIDATE!>next<!>()
|
||||
e = e.next()
|
||||
} while (e != null)
|
||||
// e can be null because of next()
|
||||
e.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
|
||||
e.doSomething()
|
||||
}
|
||||
+1
-1
@@ -8,5 +8,5 @@ public fun foo(pp: String?): Int {
|
||||
p = null
|
||||
} while (!x())
|
||||
// Smart cast is NOT possible here
|
||||
return p.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
return p.length
|
||||
}
|
||||
@@ -9,8 +9,8 @@ fun list(start: SomeObject): SomeObject {
|
||||
var e: SomeObject? = start
|
||||
for (i in 0..42) {
|
||||
// Unsafe calls because of nullable e at the beginning
|
||||
e.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
|
||||
e = e.<!INAPPLICABLE_CANDIDATE!>next<!>()
|
||||
e.doSomething()
|
||||
e = e.next()
|
||||
}
|
||||
// Smart cast is not possible here due to next()
|
||||
return e
|
||||
|
||||
+1
-1
@@ -16,5 +16,5 @@ fun list(start: SomeObject) {
|
||||
e = e.next()
|
||||
}
|
||||
// e can be null because of next()
|
||||
e.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
|
||||
e.doSomething()
|
||||
}
|
||||
+1
-1
@@ -76,5 +76,5 @@ fun test6() {
|
||||
finally {
|
||||
a = null
|
||||
}
|
||||
a.<!UNRESOLVED_REFERENCE!>hashCode<!>() // a is null here
|
||||
a.<!INAPPLICABLE_CANDIDATE!>hashCode<!>() // a is null here
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,5 +4,5 @@ fun foo() {
|
||||
// It is possible in principle to provide smart cast here
|
||||
v.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
v = null
|
||||
v.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
v.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
+1
-1
@@ -6,5 +6,5 @@ fun foo() {
|
||||
try {
|
||||
s = null
|
||||
} catch (ex: Exception) {}
|
||||
s.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
+1
-1
@@ -12,5 +12,5 @@ fun foo() {
|
||||
finally {
|
||||
bar()
|
||||
}
|
||||
s.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
+1
-1
@@ -6,5 +6,5 @@ fun foo() {
|
||||
try {
|
||||
s = null
|
||||
} catch (ex: Exception) {}
|
||||
s.<!UNRESOLVED_REFERENCE!>hashCode<!>()
|
||||
s.<!INAPPLICABLE_CANDIDATE!>hashCode<!>()
|
||||
}
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
fun foo(): Int {
|
||||
var i: Int? = 42
|
||||
i = null
|
||||
return i + 1
|
||||
return i <!INAPPLICABLE_CANDIDATE!>+<!> 1
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
fun foo(): Int {
|
||||
var s: String? = "abc"
|
||||
s = null
|
||||
return s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
return s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
@@ -9,5 +9,5 @@ public fun foo(pp: String?): Int {
|
||||
}
|
||||
// Smart cast is NOT possible here
|
||||
// (we could provide it but p = null makes it much harder)
|
||||
return p.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
return p.length
|
||||
}
|
||||
+1
-1
@@ -9,5 +9,5 @@ public fun foo(pp: String?): Int {
|
||||
}
|
||||
// Smart cast is NOT possible here
|
||||
// (we could provide it but p = null makes it much harder)
|
||||
return p.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
return p.length
|
||||
}
|
||||
+1
-1
@@ -9,5 +9,5 @@ public fun foo(pp: String?): Int {
|
||||
}
|
||||
// Smart cast is NOT possible here
|
||||
// (we could provide it but p = null makes it much harder)
|
||||
return p.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
return p.length
|
||||
}
|
||||
+1
-1
@@ -13,5 +13,5 @@ fun list(start: SomeObject) {
|
||||
e = e.next()
|
||||
}
|
||||
// e can be null because of next()
|
||||
e.<!INAPPLICABLE_CANDIDATE!>doSomething<!>()
|
||||
e.doSomething()
|
||||
}
|
||||
+2
-2
@@ -27,11 +27,11 @@ fun testUnsafeCaptureVarInInitializer() {
|
||||
|
||||
val s = when (val y = run { x = null; 32 }) {
|
||||
0 -> {
|
||||
x.<!UNRESOLVED_REFERENCE!>inc<!>() // NB smart cast should be impossible
|
||||
x.<!INAPPLICABLE_CANDIDATE!>inc<!>() // NB smart cast should be impossible
|
||||
"0"
|
||||
}
|
||||
else -> "!= 0"
|
||||
}
|
||||
|
||||
x.<!UNRESOLVED_REFERENCE!>inc<!>() // NB smart cast should be impossible
|
||||
x.<!INAPPLICABLE_CANDIDATE!>inc<!>() // NB smart cast should be impossible
|
||||
}
|
||||
+1
-1
@@ -3,5 +3,5 @@
|
||||
fun foo(y: String) {
|
||||
var x: String? = null
|
||||
y.let { x = it }
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!> // Smart cast is not possible
|
||||
x.length // Smart cast is not possible
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,6 +4,6 @@ fun foo(y: String?) {
|
||||
var x: String? = null
|
||||
if (x != null) {
|
||||
y?.let { x = it }
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!> // not-null or not-null
|
||||
x.length // not-null or not-null
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -15,7 +15,7 @@ fun test1(s: String?) {
|
||||
catch (e: Exception) {
|
||||
requireNotNull(s)
|
||||
}
|
||||
t2.<!UNRESOLVED_REFERENCE!>not<!>()
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>()
|
||||
s.length
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ fun test3() {
|
||||
s = null
|
||||
return
|
||||
}
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
fun test4() {
|
||||
@@ -61,7 +61,7 @@ fun test4() {
|
||||
catch (e: ExcB) {
|
||||
|
||||
}
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
fun test5(s: String?) {
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@ fun test1(s: String?) {
|
||||
catch (e: Exception) {
|
||||
requireNotNull(s)
|
||||
}
|
||||
t2.<!UNRESOLVED_REFERENCE!>not<!>()
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>()
|
||||
s.length
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ fun test3() {
|
||||
s = null
|
||||
return
|
||||
}
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
fun test4() {
|
||||
@@ -62,7 +62,7 @@ fun test4() {
|
||||
catch (e: ExcB) {
|
||||
|
||||
}
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
fun test5(s: String?) {
|
||||
|
||||
+12
-12
@@ -13,15 +13,15 @@ fun test1() {
|
||||
try {
|
||||
x = null
|
||||
} catch (e: Exception) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!> // smartcast shouldn't be allowed (OOME could happen after `x = null`)
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!> // smartcast shouldn't be allowed (OOME could happen after `x = null`)
|
||||
throw e
|
||||
}
|
||||
finally {
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
// With old DFA of try/catch info about unsound smartcasts after try
|
||||
@@ -33,12 +33,12 @@ fun test2() {
|
||||
try {
|
||||
x = null
|
||||
} catch (e: Exception) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
finally {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
@@ -49,7 +49,7 @@ fun test3() {
|
||||
} catch (e: Exception) {
|
||||
t2 = null
|
||||
}
|
||||
t2.<!UNRESOLVED_REFERENCE!>not<!>() // wrong smartcast, NPE
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ fun test4() {
|
||||
try {
|
||||
t2 = null
|
||||
} finally { }
|
||||
t2.<!UNRESOLVED_REFERENCE!>not<!>() // wrong smartcast, NPE
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +80,10 @@ fun test5() {
|
||||
}
|
||||
finally {
|
||||
s1.length
|
||||
s2.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s2.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
s1.length
|
||||
s2.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s2.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
fun test6(s1: String?, s2: String?) {
|
||||
@@ -97,10 +97,10 @@ fun test6(s1: String?, s2: String?) {
|
||||
return
|
||||
}
|
||||
finally {
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
requireNotNull(s2)
|
||||
}
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s1.length
|
||||
s2.length
|
||||
}
|
||||
Vendored
+12
-12
@@ -14,15 +14,15 @@ fun test1() {
|
||||
try {
|
||||
x = null
|
||||
} catch (e: Exception) {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!> // smartcast shouldn't be allowed (OOME could happen after `x = null`)
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!> // smartcast shouldn't be allowed (OOME could happen after `x = null`)
|
||||
throw e
|
||||
}
|
||||
finally {
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
// smartcast shouldn't be allowed, `x = null` could've happened
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
// With old DFA of try/catch info about unsound smartcasts after try
|
||||
@@ -35,12 +35,12 @@ fun test2() {
|
||||
x = null
|
||||
} catch (e: Exception) {
|
||||
// BAD
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
finally {
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
@@ -51,7 +51,7 @@ fun test3() {
|
||||
} catch (e: Exception) {
|
||||
t2 = null
|
||||
}
|
||||
t2.<!UNRESOLVED_REFERENCE!>not<!>() // wrong smartcast, NPE
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ fun test4() {
|
||||
try {
|
||||
t2 = null
|
||||
} finally { }
|
||||
t2.<!UNRESOLVED_REFERENCE!>not<!>() // wrong smartcast, NPE
|
||||
t2.<!INAPPLICABLE_CANDIDATE!>not<!>() // wrong smartcast, NPE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,10 +82,10 @@ fun test5() {
|
||||
}
|
||||
finally {
|
||||
s1.length
|
||||
s2.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s2.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
s1.length
|
||||
s2.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s2.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
}
|
||||
|
||||
fun test6(s1: String?, s2: String?) {
|
||||
@@ -99,10 +99,10 @@ fun test6(s1: String?, s2: String?) {
|
||||
return
|
||||
}
|
||||
finally {
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
requireNotNull(s2)
|
||||
}
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||
s1.length
|
||||
s2.length
|
||||
}
|
||||
Reference in New Issue
Block a user