[NI] Soften restictions on using Nothing as proper constraint for full call completion

Consider lower `Nothing` constraint non-proper only if there is a dependant not analyzed postponed atom.
Early completion to `Nothing` provides data flow info for smart casts.

KT-35668 Fixed
This commit is contained in:
Pavel Kirpichenkov
2020-01-22 15:46:33 +03:00
parent f1d9177112
commit 78c9bbcc0d
13 changed files with 234 additions and 24 deletions
@@ -15,7 +15,7 @@ val ww = if (true) {
<!OI;TYPE_MISMATCH!>{ true }<!> <!USELESS_ELVIS!>?: null!!<!>
}
else if (true) {
<!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, TYPE_MISMATCH!>{ <!NI;CONSTANT_EXPECTED_TYPE_MISMATCH!>true<!> }<!> <!USELESS_ELVIS!>?: null!!<!>
<!OI;TYPE_MISMATCH!>{ true }<!> <!USELESS_ELVIS!>?: null!!<!>
}
else {
null!!
@@ -0,0 +1,52 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun <K> id(it: K) = it
fun <E> smartCast(arg: E?, fn: () -> Any?): E = TODO()
fun <E1> noSmartCast1(arg: E1?, fn: () -> E1): E1 = TODO()
fun <E2> noSmartCast2(arg: E2?, fn: E2): E2 = TODO()
fun <E3, F : E3> noSmartCast3(arg: E3?, fn: () -> F): E3 = TODO()
fun <E4, F : E4> noSmartCast4(arg: E4?, fn: F): E4 = TODO()
fun testSmartCast(s: String?) {
id(
if (s != null) ""
else smartCast(null) { "" }
)
s.length
}
fun testNoSmartCast1(s: String?) {
id(
if (s != null) ""
else noSmartCast1(null) { "" }
)
s.<!INAPPLICABLE_CANDIDATE!>length<!>
}
fun testNoSmartCast2(s: String?) {
id(
if (s != null) ( {""} )
else noSmartCast2(null) { "" }
)
s.<!INAPPLICABLE_CANDIDATE!>length<!>
}
fun testNoSmartCast3(s: String?) {
id(
if (s != null) ""
else noSmartCast3(null) { "" }
)
s.<!INAPPLICABLE_CANDIDATE!>length<!>
}
// KT-36069
fun testNoSmartCast4(s: String?) {
id(
if (s != null) ( {""} )
else noSmartCast4(null) { "" }
)
s.<!INAPPLICABLE_CANDIDATE!>length<!>
}
@@ -0,0 +1,52 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun <K> id(it: K) = it
fun <E> smartCast(arg: E?, fn: () -> Any?): E = TODO()
fun <E1> noSmartCast1(arg: E1?, fn: () -> E1): E1 = TODO()
fun <E2> noSmartCast2(arg: E2?, fn: E2): E2 = TODO()
fun <E3, F : E3> noSmartCast3(arg: E3?, fn: () -> F): E3 = TODO()
fun <E4, F : E4> noSmartCast4(arg: E4?, fn: F): E4 = TODO()
fun testSmartCast(s: String?) {
id(
if (s != null) ""
else <!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>smartCast<!>(null) { "" }
)
<!DEBUG_INFO_SMARTCAST!>s<!>.length
}
fun testNoSmartCast1(s: String?) {
id(
if (s != null) ""
else noSmartCast1(null) { "" }
)
s<!UNSAFE_CALL!>.<!>length
}
fun testNoSmartCast2(s: String?) {
id(
if (s != null) ( {""} )
else noSmartCast2(null) { "" }
)
s<!UNSAFE_CALL!>.<!>length
}
fun testNoSmartCast3(s: String?) {
id(
if (s != null) ""
else noSmartCast3(null) { "" }
)
s<!UNSAFE_CALL!>.<!>length
}
// KT-36069
fun testNoSmartCast4(s: String?) {
id(
if (s != null) ( {""} )
else <!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>noSmartCast4<!>(null) <!TYPE_MISMATCH!>{ <!TYPE_MISMATCH!>""<!> }<!>
)
s<!UNSAFE_CALL!>.<!>length
}
@@ -0,0 +1,13 @@
package
public fun </*0*/ K> id(/*0*/ it: K): K
public fun </*0*/ E1> noSmartCast1(/*0*/ arg: E1?, /*1*/ fn: () -> E1): E1
public fun </*0*/ E2> noSmartCast2(/*0*/ arg: E2?, /*1*/ fn: E2): E2
public fun </*0*/ E3, /*1*/ F : E3> noSmartCast3(/*0*/ arg: E3?, /*1*/ fn: () -> F): E3
public fun </*0*/ E4, /*1*/ F : E4> noSmartCast4(/*0*/ arg: E4?, /*1*/ fn: F): E4
public fun </*0*/ E> smartCast(/*0*/ arg: E?, /*1*/ fn: () -> kotlin.Any?): E
public fun testNoSmartCast1(/*0*/ s: kotlin.String?): kotlin.Unit
public fun testNoSmartCast2(/*0*/ s: kotlin.String?): kotlin.Unit
public fun testNoSmartCast3(/*0*/ s: kotlin.String?): kotlin.Unit
public fun testNoSmartCast4(/*0*/ s: kotlin.String?): kotlin.Unit
public fun testSmartCast(/*0*/ s: kotlin.String?): kotlin.Unit
@@ -0,0 +1,20 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun main() {
val baseDir: String? = ""
val networkParameters: String? = ""
if (baseDir != null) {
if (networkParameters != null) {
Unit
} else if (true){
return
} else {
return
}
} else {
return
}
networkParameters.length // unsafe call
}
@@ -0,0 +1,20 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun main() {
val baseDir: String? = ""
val networkParameters: String? = ""
if (baseDir != null) {
if (networkParameters != null) {
Unit
} else if (true){
return
} else {
return
}
} else {
return
}
<!DEBUG_INFO_SMARTCAST!>networkParameters<!>.length // unsafe call
}
@@ -0,0 +1,3 @@
package
public fun main(): kotlin.Unit
+1 -1
View File
@@ -1,5 +1,5 @@
// !WITH_NEW_INFERENCE
val test: Int = <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>if (true) {
val test: Int = <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>if (true) {
when (2) {
1 -> 1
else -> <!OI;NULL_FOR_NONNULL_TYPE!>null<!>